Jelajahi Sumber

当前libssh2版本:1.9.0

Jeff 5 tahun lalu
induk
melakukan
32c1a75ac9
100 mengubah file dengan 65919 tambahan dan 0 penghapusan
  1. 69 0
      libssh2/libssh2.sln
  2. 1344 0
      libssh2/libssh2/include/libssh2.h
  3. 47 0
      libssh2/libssh2/include/libssh2_config.h
  4. 122 0
      libssh2/libssh2/include/libssh2_publickey.h
  5. 351 0
      libssh2/libssh2/include/libssh2_sftp.h
  6. 45 0
      libssh2/libssh2/libssh2.rc
  7. 877 0
      libssh2/libssh2/libssh2.vcproj
  8. 860 0
      libssh2/libssh2/src/agent.c
  9. 180 0
      libssh2/libssh2/src/bcrypt_pbkdf.c
  10. 90 0
      libssh2/libssh2/src/blf.h
  11. 697 0
      libssh2/libssh2/src/blowfish.c
  12. 2738 0
      libssh2/libssh2/src/channel.c
  13. 141 0
      libssh2/libssh2/src/channel.h
  14. 376 0
      libssh2/libssh2/src/comp.c
  15. 45 0
      libssh2/libssh2/src/comp.h
  16. 349 0
      libssh2/libssh2/src/crypt.c
  17. 248 0
      libssh2/libssh2/src/crypto.h
  18. 77 0
      libssh2/libssh2/src/global.c
  19. 1129 0
      libssh2/libssh2/src/hostkey.c
  20. 100 0
      libssh2/libssh2/src/keepalive.c
  21. 4424 0
      libssh2/libssh2/src/kex.c
  22. 1271 0
      libssh2/libssh2/src/knownhost.c
  23. 667 0
      libssh2/libssh2/src/libgcrypt.c
  24. 234 0
      libssh2/libssh2/src/libgcrypt.h
  25. 1143 0
      libssh2/libssh2/src/libssh2_priv.h
  26. 414 0
      libssh2/libssh2/src/mac.c
  27. 67 0
      libssh2/libssh2/src/mac.h
  28. 733 0
      libssh2/libssh2/src/mbedtls.c
  29. 447 0
      libssh2/libssh2/src/mbedtls.h
  30. 874 0
      libssh2/libssh2/src/misc.c
  31. 125 0
      libssh2/libssh2/src/misc.h
  32. 3240 0
      libssh2/libssh2/src/openssl.c
  33. 409 0
      libssh2/libssh2/src/openssl.h
  34. 2411 0
      libssh2/libssh2/src/os400qc3.c
  35. 373 0
      libssh2/libssh2/src/os400qc3.h
  36. 1288 0
      libssh2/libssh2/src/packet.c
  37. 76 0
      libssh2/libssh2/src/packet.h
  38. 902 0
      libssh2/libssh2/src/pem.c
  39. 1278 0
      libssh2/libssh2/src/publickey.c
  40. 1145 0
      libssh2/libssh2/src/scp.c
  41. 1832 0
      libssh2/libssh2/src/session.c
  42. 93 0
      libssh2/libssh2/src/session.h
  43. 3755 0
      libssh2/libssh2/src/sftp.c
  44. 238 0
      libssh2/libssh2/src/sftp.h
  45. 917 0
      libssh2/libssh2/src/transport.c
  46. 87 0
      libssh2/libssh2/src/transport.h
  47. 2110 0
      libssh2/libssh2/src/userauth.c
  48. 51 0
      libssh2/libssh2/src/userauth.h
  49. 54 0
      libssh2/libssh2/src/version.c
  50. 2168 0
      libssh2/libssh2/src/wincng.c
  51. 571 0
      libssh2/libssh2/src/wincng.h
  52. TEMPAT SAMPAH
      libssh2/openssl/bin/libeay32.dll
  53. TEMPAT SAMPAH
      libssh2/openssl/bin/openssl.exe
  54. TEMPAT SAMPAH
      libssh2/openssl/bin/ssleay32.dll
  55. 149 0
      libssh2/openssl/include/openssl/aes.h
  56. 129 0
      libssh2/openssl/include/openssl/applink.c
  57. 1424 0
      libssh2/openssl/include/openssl/asn1.h
  58. 579 0
      libssh2/openssl/include/openssl/asn1_mac.h
  59. 973 0
      libssh2/openssl/include/openssl/asn1t.h
  60. 883 0
      libssh2/openssl/include/openssl/bio.h
  61. 130 0
      libssh2/openssl/include/openssl/blowfish.h
  62. 1015 0
      libssh2/openssl/include/openssl/bn.h
  63. 125 0
      libssh2/openssl/include/openssl/buffer.h
  64. 132 0
      libssh2/openssl/include/openssl/camellia.h
  65. 107 0
      libssh2/openssl/include/openssl/cast.h
  66. 82 0
      libssh2/openssl/include/openssl/cmac.h
  67. 555 0
      libssh2/openssl/include/openssl/cms.h
  68. 83 0
      libssh2/openssl/include/openssl/comp.h
  69. 268 0
      libssh2/openssl/include/openssl/conf.h
  70. 89 0
      libssh2/openssl/include/openssl/conf_api.h
  71. 661 0
      libssh2/openssl/include/openssl/crypto.h
  72. 257 0
      libssh2/openssl/include/openssl/des.h
  73. 497 0
      libssh2/openssl/include/openssl/des_old.h
  74. 412 0
      libssh2/openssl/include/openssl/dh.h
  75. 335 0
      libssh2/openssl/include/openssl/dsa.h
  76. 451 0
      libssh2/openssl/include/openssl/dso.h
  77. 272 0
      libssh2/openssl/include/openssl/dtls1.h
  78. 328 0
      libssh2/openssl/include/openssl/e_os2.h
  79. 26 0
      libssh2/openssl/include/openssl/ebcdic.h
  80. 1284 0
      libssh2/openssl/include/openssl/ec.h
  81. 134 0
      libssh2/openssl/include/openssl/ecdh.h
  82. 335 0
      libssh2/openssl/include/openssl/ecdsa.h
  83. 960 0
      libssh2/openssl/include/openssl/engine.h
  84. 391 0
      libssh2/openssl/include/openssl/err.h
  85. 1630 0
      libssh2/openssl/include/openssl/evp.h
  86. 109 0
      libssh2/openssl/include/openssl/hmac.h
  87. 105 0
      libssh2/openssl/include/openssl/idea.h
  88. 240 0
      libssh2/openssl/include/openssl/krb5_asn.h
  89. 197 0
      libssh2/openssl/include/openssl/kssl.h
  90. 240 0
      libssh2/openssl/include/openssl/lhash.h
  91. 119 0
      libssh2/openssl/include/openssl/md4.h
  92. 119 0
      libssh2/openssl/include/openssl/md5.h
  93. 94 0
      libssh2/openssl/include/openssl/mdc2.h
  94. 163 0
      libssh2/openssl/include/openssl/modes.h
  95. 4194 0
      libssh2/openssl/include/openssl/obj_mac.h
  96. 1143 0
      libssh2/openssl/include/openssl/objects.h
  97. 637 0
      libssh2/openssl/include/openssl/ocsp.h
  98. 271 0
      libssh2/openssl/include/openssl/opensslconf.h
  99. 97 0
      libssh2/openssl/include/openssl/opensslv.h
  100. 213 0
      libssh2/openssl/include/openssl/ossl_typ.h

+ 69 - 0
libssh2/libssh2.sln

@@ -0,0 +1,69 @@
+
+Microsoft Visual Studio Solution File, Format Version 10.00
+# Visual Studio 2008
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libssh2", "libssh2\libssh2.vcproj", "{656EF6DD-759A-41F2-BB76-2107C27C910E}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "tests", "tests\tests.vcproj", "{8F6D8D67-8512-4810-8599-F9EE33E94F59}"
+	ProjectSection(ProjectDependencies) = postProject
+		{656EF6DD-759A-41F2-BB76-2107C27C910E} = {656EF6DD-759A-41F2-BB76-2107C27C910E}
+	EndProjectSection
+EndProject
+Global
+	GlobalSection(SolutionConfigurationPlatforms) = preSolution
+		Debug|Win32 = Debug|Win32
+		OpenSSL DLL Debug|Win32 = OpenSSL DLL Debug|Win32
+		OpenSSL DLL Release|Win32 = OpenSSL DLL Release|Win32
+		OpenSSL LIB Debug|Win32 = OpenSSL LIB Debug|Win32
+		OpenSSL LIB Release|Win32 = OpenSSL LIB Release|Win32
+		Release|Win32 = Release|Win32
+		WinCNG DLL Debug|Win32 = WinCNG DLL Debug|Win32
+		WinCNG DLL Release|Win32 = WinCNG DLL Release|Win32
+		WinCNG LIB Debug|Win32 = WinCNG LIB Debug|Win32
+		WinCNG LIB Release|Win32 = WinCNG LIB Release|Win32
+	EndGlobalSection
+	GlobalSection(ProjectConfigurationPlatforms) = postSolution
+		{656EF6DD-759A-41F2-BB76-2107C27C910E}.Debug|Win32.ActiveCfg = OpenSSL DLL Debug|Win32
+		{656EF6DD-759A-41F2-BB76-2107C27C910E}.Debug|Win32.Build.0 = OpenSSL DLL Debug|Win32
+		{656EF6DD-759A-41F2-BB76-2107C27C910E}.OpenSSL DLL Debug|Win32.ActiveCfg = OpenSSL DLL Debug|Win32
+		{656EF6DD-759A-41F2-BB76-2107C27C910E}.OpenSSL DLL Debug|Win32.Build.0 = OpenSSL DLL Debug|Win32
+		{656EF6DD-759A-41F2-BB76-2107C27C910E}.OpenSSL DLL Release|Win32.ActiveCfg = OpenSSL DLL Release|Win32
+		{656EF6DD-759A-41F2-BB76-2107C27C910E}.OpenSSL DLL Release|Win32.Build.0 = OpenSSL DLL Release|Win32
+		{656EF6DD-759A-41F2-BB76-2107C27C910E}.OpenSSL LIB Debug|Win32.ActiveCfg = OpenSSL LIB Debug|Win32
+		{656EF6DD-759A-41F2-BB76-2107C27C910E}.OpenSSL LIB Debug|Win32.Build.0 = OpenSSL LIB Debug|Win32
+		{656EF6DD-759A-41F2-BB76-2107C27C910E}.OpenSSL LIB Release|Win32.ActiveCfg = OpenSSL LIB Release|Win32
+		{656EF6DD-759A-41F2-BB76-2107C27C910E}.OpenSSL LIB Release|Win32.Build.0 = OpenSSL LIB Release|Win32
+		{656EF6DD-759A-41F2-BB76-2107C27C910E}.Release|Win32.ActiveCfg = OpenSSL DLL Release|Win32
+		{656EF6DD-759A-41F2-BB76-2107C27C910E}.Release|Win32.Build.0 = OpenSSL DLL Release|Win32
+		{656EF6DD-759A-41F2-BB76-2107C27C910E}.WinCNG DLL Debug|Win32.ActiveCfg = WinCNG DLL Debug|Win32
+		{656EF6DD-759A-41F2-BB76-2107C27C910E}.WinCNG DLL Debug|Win32.Build.0 = WinCNG DLL Debug|Win32
+		{656EF6DD-759A-41F2-BB76-2107C27C910E}.WinCNG DLL Release|Win32.ActiveCfg = WinCNG DLL Release|Win32
+		{656EF6DD-759A-41F2-BB76-2107C27C910E}.WinCNG DLL Release|Win32.Build.0 = WinCNG DLL Release|Win32
+		{656EF6DD-759A-41F2-BB76-2107C27C910E}.WinCNG LIB Debug|Win32.ActiveCfg = WinCNG LIB Debug|Win32
+		{656EF6DD-759A-41F2-BB76-2107C27C910E}.WinCNG LIB Debug|Win32.Build.0 = WinCNG LIB Debug|Win32
+		{656EF6DD-759A-41F2-BB76-2107C27C910E}.WinCNG LIB Release|Win32.ActiveCfg = WinCNG LIB Release|Win32
+		{656EF6DD-759A-41F2-BB76-2107C27C910E}.WinCNG LIB Release|Win32.Build.0 = WinCNG LIB Release|Win32
+		{8F6D8D67-8512-4810-8599-F9EE33E94F59}.Debug|Win32.ActiveCfg = Debug|Win32
+		{8F6D8D67-8512-4810-8599-F9EE33E94F59}.Debug|Win32.Build.0 = Debug|Win32
+		{8F6D8D67-8512-4810-8599-F9EE33E94F59}.OpenSSL DLL Debug|Win32.ActiveCfg = Debug|Win32
+		{8F6D8D67-8512-4810-8599-F9EE33E94F59}.OpenSSL DLL Debug|Win32.Build.0 = Debug|Win32
+		{8F6D8D67-8512-4810-8599-F9EE33E94F59}.OpenSSL DLL Release|Win32.ActiveCfg = Release|Win32
+		{8F6D8D67-8512-4810-8599-F9EE33E94F59}.OpenSSL DLL Release|Win32.Build.0 = Release|Win32
+		{8F6D8D67-8512-4810-8599-F9EE33E94F59}.OpenSSL LIB Debug|Win32.ActiveCfg = Debug|Win32
+		{8F6D8D67-8512-4810-8599-F9EE33E94F59}.OpenSSL LIB Debug|Win32.Build.0 = Debug|Win32
+		{8F6D8D67-8512-4810-8599-F9EE33E94F59}.OpenSSL LIB Release|Win32.ActiveCfg = Release|Win32
+		{8F6D8D67-8512-4810-8599-F9EE33E94F59}.OpenSSL LIB Release|Win32.Build.0 = Release|Win32
+		{8F6D8D67-8512-4810-8599-F9EE33E94F59}.Release|Win32.ActiveCfg = Release|Win32
+		{8F6D8D67-8512-4810-8599-F9EE33E94F59}.Release|Win32.Build.0 = Release|Win32
+		{8F6D8D67-8512-4810-8599-F9EE33E94F59}.WinCNG DLL Debug|Win32.ActiveCfg = Debug|Win32
+		{8F6D8D67-8512-4810-8599-F9EE33E94F59}.WinCNG DLL Debug|Win32.Build.0 = Debug|Win32
+		{8F6D8D67-8512-4810-8599-F9EE33E94F59}.WinCNG DLL Release|Win32.ActiveCfg = Release|Win32
+		{8F6D8D67-8512-4810-8599-F9EE33E94F59}.WinCNG DLL Release|Win32.Build.0 = Release|Win32
+		{8F6D8D67-8512-4810-8599-F9EE33E94F59}.WinCNG LIB Debug|Win32.ActiveCfg = Debug|Win32
+		{8F6D8D67-8512-4810-8599-F9EE33E94F59}.WinCNG LIB Debug|Win32.Build.0 = Debug|Win32
+		{8F6D8D67-8512-4810-8599-F9EE33E94F59}.WinCNG LIB Release|Win32.ActiveCfg = Release|Win32
+		{8F6D8D67-8512-4810-8599-F9EE33E94F59}.WinCNG LIB Release|Win32.Build.0 = Release|Win32
+	EndGlobalSection
+	GlobalSection(SolutionProperties) = preSolution
+		HideSolutionNode = FALSE
+	EndGlobalSection
+EndGlobal

+ 1344 - 0
libssh2/libssh2/include/libssh2.h

@@ -0,0 +1,1344 @@
+/* Copyright (c) 2004-2009, Sara Golemon <sarag@libssh2.org>
+ * Copyright (c) 2009-2015 Daniel Stenberg
+ * Copyright (c) 2010 Simon Josefsson <simon@josefsson.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms,
+ * with or without modification, are permitted provided
+ * that the following conditions are met:
+ *
+ *   Redistributions of source code must retain the above
+ *   copyright notice, this list of conditions and the
+ *   following disclaimer.
+ *
+ *   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.
+ *
+ *   Neither the name of the copyright holder nor the names
+ *   of any other contributors may be used to endorse or
+ *   promote products derived from this software without
+ *   specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+ * CONTRIBUTORS "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 COPYRIGHT OWNER OR
+ * CONTRIBUTORS 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 LIBSSH2_H
+#define LIBSSH2_H 1
+
+#define LIBSSH2_COPYRIGHT "2004-2019 The libssh2 project and its contributors."
+
+/* We use underscore instead of dash when appending DEV in dev versions just
+   to make the BANNER define (used by src/session.c) be a valid SSH
+   banner. Release versions have no appended strings and may of course not
+   have dashes either. */
+#define LIBSSH2_VERSION                             "1.9.0_DEV"
+
+/* The numeric version number is also available "in parts" by using these
+   defines: */
+#define LIBSSH2_VERSION_MAJOR                       1
+#define LIBSSH2_VERSION_MINOR                       9
+#define LIBSSH2_VERSION_PATCH                       0
+
+/* This is the numeric version of the libssh2 version number, meant for easier
+   parsing and comparions by programs. The LIBSSH2_VERSION_NUM define will
+   always follow this syntax:
+
+         0xXXYYZZ
+
+   Where XX, YY and ZZ are the main version, release and patch numbers in
+   hexadecimal (using 8 bits each). All three numbers are always represented
+   using two digits.  1.2 would appear as "0x010200" while version 9.11.7
+   appears as "0x090b07".
+
+   This 6-digit (24 bits) hexadecimal number does not show pre-release number,
+   and it is always a greater number in a more recent release. It makes
+   comparisons with greater than and less than work.
+*/
+#define LIBSSH2_VERSION_NUM                         0x010900
+
+/*
+ * This is the date and time when the full source package was created. The
+ * timestamp is not stored in the source code repo, as the timestamp is
+ * properly set in the tarballs by the maketgz script.
+ *
+ * The format of the date should follow this template:
+ *
+ * "Mon Feb 12 11:35:33 UTC 2007"
+ */
+#define LIBSSH2_TIMESTAMP "DEV"
+
+#ifndef RC_INVOKED
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+#ifdef _WIN32
+# include <basetsd.h>
+# include <winsock2.h>
+#endif
+
+#include <stddef.h>
+#include <string.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+
+/* Allow alternate API prefix from CFLAGS or calling app */
+#ifndef LIBSSH2_API
+# ifdef LIBSSH2_WIN32
+#  ifdef _WINDLL
+#   ifdef LIBSSH2_LIBRARY
+#    define LIBSSH2_API __declspec(dllexport)
+#   else
+#    define LIBSSH2_API __declspec(dllimport)
+#   endif /* LIBSSH2_LIBRARY */
+#  else
+#   define LIBSSH2_API
+#  endif
+# else /* !LIBSSH2_WIN32 */
+#  define LIBSSH2_API
+# endif /* LIBSSH2_WIN32 */
+#endif /* LIBSSH2_API */
+
+#ifdef HAVE_SYS_UIO_H
+# include <sys/uio.h>
+#endif
+
+#if (defined(NETWARE) && !defined(__NOVELL_LIBC__))
+# include <sys/bsdskt.h>
+typedef unsigned char uint8_t;
+typedef unsigned short int uint16_t;
+typedef unsigned int uint32_t;
+typedef int int32_t;
+typedef unsigned long long uint64_t;
+typedef long long int64_t;
+#endif
+
+#ifdef _MSC_VER
+typedef unsigned char uint8_t;
+typedef unsigned short int uint16_t;
+typedef unsigned int uint32_t;
+typedef __int32 int32_t;
+typedef __int64 int64_t;
+typedef unsigned __int64 uint64_t;
+typedef unsigned __int64 libssh2_uint64_t;
+typedef __int64 libssh2_int64_t;
+#if (!defined(HAVE_SSIZE_T) && !defined(ssize_t))
+typedef SSIZE_T ssize_t;
+#define HAVE_SSIZE_T
+#endif
+#else
+#include <stdint.h>
+typedef unsigned long long libssh2_uint64_t;
+typedef long long libssh2_int64_t;
+#endif
+
+#ifdef WIN32
+typedef SOCKET libssh2_socket_t;
+#define LIBSSH2_INVALID_SOCKET INVALID_SOCKET
+#else /* !WIN32 */
+typedef int libssh2_socket_t;
+#define LIBSSH2_INVALID_SOCKET -1
+#endif /* WIN32 */
+
+/*
+ * Determine whether there is small or large file support on windows.
+ */
+
+#if defined(_MSC_VER) && !defined(_WIN32_WCE)
+#  if (_MSC_VER >= 900) && (_INTEGRAL_MAX_BITS >= 64)
+#    define LIBSSH2_USE_WIN32_LARGE_FILES
+#  else
+#    define LIBSSH2_USE_WIN32_SMALL_FILES
+#  endif
+#endif
+
+#if defined(__MINGW32__) && !defined(LIBSSH2_USE_WIN32_LARGE_FILES)
+#  define LIBSSH2_USE_WIN32_LARGE_FILES
+#endif
+
+#if defined(__WATCOMC__) && !defined(LIBSSH2_USE_WIN32_LARGE_FILES)
+#  define LIBSSH2_USE_WIN32_LARGE_FILES
+#endif
+
+#if defined(__POCC__)
+#  undef LIBSSH2_USE_WIN32_LARGE_FILES
+#endif
+
+#if defined(_WIN32) && !defined(LIBSSH2_USE_WIN32_LARGE_FILES) && \
+    !defined(LIBSSH2_USE_WIN32_SMALL_FILES)
+#  define LIBSSH2_USE_WIN32_SMALL_FILES
+#endif
+
+/*
+ * Large file (>2Gb) support using WIN32 functions.
+ */
+
+#ifdef LIBSSH2_USE_WIN32_LARGE_FILES
+#  include <io.h>
+#  include <sys/types.h>
+#  include <sys/stat.h>
+#  define LIBSSH2_STRUCT_STAT_SIZE_FORMAT    "%I64d"
+typedef struct _stati64 libssh2_struct_stat;
+typedef __int64 libssh2_struct_stat_size;
+#endif
+
+/*
+ * Small file (<2Gb) support using WIN32 functions.
+ */
+
+#ifdef LIBSSH2_USE_WIN32_SMALL_FILES
+#  include <sys/types.h>
+#  include <sys/stat.h>
+#  ifndef _WIN32_WCE
+#    define LIBSSH2_STRUCT_STAT_SIZE_FORMAT    "%d"
+typedef struct _stat libssh2_struct_stat;
+typedef off_t libssh2_struct_stat_size;
+#  endif
+#endif
+
+#ifndef LIBSSH2_STRUCT_STAT_SIZE_FORMAT
+#  ifdef __VMS
+/* We have to roll our own format here because %z is a C99-ism we don't
+   have. */
+#    if __USE_OFF64_T || __USING_STD_STAT
+#      define LIBSSH2_STRUCT_STAT_SIZE_FORMAT      "%Ld"
+#    else
+#      define LIBSSH2_STRUCT_STAT_SIZE_FORMAT      "%d"
+#    endif
+#  else
+#    define LIBSSH2_STRUCT_STAT_SIZE_FORMAT      "%zd"
+#  endif
+typedef struct stat libssh2_struct_stat;
+typedef off_t libssh2_struct_stat_size;
+#endif
+
+/* Part of every banner, user specified or not */
+#define LIBSSH2_SSH_BANNER                  "SSH-2.0-libssh2_" LIBSSH2_VERSION
+
+#define LIBSSH2_SSH_DEFAULT_BANNER            LIBSSH2_SSH_BANNER
+#define LIBSSH2_SSH_DEFAULT_BANNER_WITH_CRLF  LIBSSH2_SSH_DEFAULT_BANNER "\r\n"
+
+/* Default generate and safe prime sizes for
+   diffie-hellman-group-exchange-sha1 */
+#define LIBSSH2_DH_GEX_MINGROUP     1024
+#define LIBSSH2_DH_GEX_OPTGROUP     1536
+#define LIBSSH2_DH_GEX_MAXGROUP     2048
+
+/* Defaults for pty requests */
+#define LIBSSH2_TERM_WIDTH      80
+#define LIBSSH2_TERM_HEIGHT     24
+#define LIBSSH2_TERM_WIDTH_PX   0
+#define LIBSSH2_TERM_HEIGHT_PX  0
+
+/* 1/4 second */
+#define LIBSSH2_SOCKET_POLL_UDELAY      250000
+/* 0.25 * 120 == 30 seconds */
+#define LIBSSH2_SOCKET_POLL_MAXLOOPS    120
+
+/* Maximum size to allow a payload to compress to, plays it safe by falling
+   short of spec limits */
+#define LIBSSH2_PACKET_MAXCOMP      32000
+
+/* Maximum size to allow a payload to deccompress to, plays it safe by
+   allowing more than spec requires */
+#define LIBSSH2_PACKET_MAXDECOMP    40000
+
+/* Maximum size for an inbound compressed payload, plays it safe by
+   overshooting spec limits */
+#define LIBSSH2_PACKET_MAXPAYLOAD   40000
+
+/* Malloc callbacks */
+#define LIBSSH2_ALLOC_FUNC(name)   void *name(size_t count, void **abstract)
+#define LIBSSH2_REALLOC_FUNC(name) void *name(void *ptr, size_t count, \
+                                              void **abstract)
+#define LIBSSH2_FREE_FUNC(name)    void name(void *ptr, void **abstract)
+
+typedef struct _LIBSSH2_USERAUTH_KBDINT_PROMPT
+{
+    char *text;
+    unsigned int length;
+    unsigned char echo;
+} LIBSSH2_USERAUTH_KBDINT_PROMPT;
+
+typedef struct _LIBSSH2_USERAUTH_KBDINT_RESPONSE
+{
+    char *text;
+    unsigned int length;
+} LIBSSH2_USERAUTH_KBDINT_RESPONSE;
+
+/* 'publickey' authentication callback */
+#define LIBSSH2_USERAUTH_PUBLICKEY_SIGN_FUNC(name) \
+  int name(LIBSSH2_SESSION *session, unsigned char **sig, size_t *sig_len, \
+           const unsigned char *data, size_t data_len, void **abstract)
+
+/* 'keyboard-interactive' authentication callback */
+#define LIBSSH2_USERAUTH_KBDINT_RESPONSE_FUNC(name_) \
+ void name_(const char *name, int name_len, const char *instruction, \
+            int instruction_len, int num_prompts, \
+            const LIBSSH2_USERAUTH_KBDINT_PROMPT *prompts,              \
+            LIBSSH2_USERAUTH_KBDINT_RESPONSE *responses, void **abstract)
+
+/* Callbacks for special SSH packets */
+#define LIBSSH2_IGNORE_FUNC(name) \
+ void name(LIBSSH2_SESSION *session, const char *message, int message_len, \
+           void **abstract)
+
+#define LIBSSH2_DEBUG_FUNC(name) \
+ void name(LIBSSH2_SESSION *session, int always_display, const char *message, \
+           int message_len, const char *language, int language_len, \
+           void **abstract)
+
+#define LIBSSH2_DISCONNECT_FUNC(name) \
+ void name(LIBSSH2_SESSION *session, int reason, const char *message, \
+           int message_len, const char *language, int language_len, \
+           void **abstract)
+
+#define LIBSSH2_PASSWD_CHANGEREQ_FUNC(name) \
+ void name(LIBSSH2_SESSION *session, char **newpw, int *newpw_len, \
+           void **abstract)
+
+#define LIBSSH2_MACERROR_FUNC(name) \
+ int name(LIBSSH2_SESSION *session, const char *packet, int packet_len, \
+          void **abstract)
+
+#define LIBSSH2_X11_OPEN_FUNC(name) \
+ void name(LIBSSH2_SESSION *session, LIBSSH2_CHANNEL *channel, \
+           const char *shost, int sport, void **abstract)
+
+#define LIBSSH2_CHANNEL_CLOSE_FUNC(name) \
+  void name(LIBSSH2_SESSION *session, void **session_abstract, \
+            LIBSSH2_CHANNEL *channel, void **channel_abstract)
+
+/* I/O callbacks */
+#define LIBSSH2_RECV_FUNC(name)                                         \
+    ssize_t name(libssh2_socket_t socket,                               \
+                 void *buffer, size_t length,                           \
+                 int flags, void **abstract)
+#define LIBSSH2_SEND_FUNC(name)                                         \
+    ssize_t name(libssh2_socket_t socket,                               \
+                 const void *buffer, size_t length,                     \
+                 int flags, void **abstract)
+
+/* libssh2_session_callback_set() constants */
+#define LIBSSH2_CALLBACK_IGNORE             0
+#define LIBSSH2_CALLBACK_DEBUG              1
+#define LIBSSH2_CALLBACK_DISCONNECT         2
+#define LIBSSH2_CALLBACK_MACERROR           3
+#define LIBSSH2_CALLBACK_X11                4
+#define LIBSSH2_CALLBACK_SEND               5
+#define LIBSSH2_CALLBACK_RECV               6
+
+/* libssh2_session_method_pref() constants */
+#define LIBSSH2_METHOD_KEX          0
+#define LIBSSH2_METHOD_HOSTKEY      1
+#define LIBSSH2_METHOD_CRYPT_CS     2
+#define LIBSSH2_METHOD_CRYPT_SC     3
+#define LIBSSH2_METHOD_MAC_CS       4
+#define LIBSSH2_METHOD_MAC_SC       5
+#define LIBSSH2_METHOD_COMP_CS      6
+#define LIBSSH2_METHOD_COMP_SC      7
+#define LIBSSH2_METHOD_LANG_CS      8
+#define LIBSSH2_METHOD_LANG_SC      9
+
+/* flags */
+#define LIBSSH2_FLAG_SIGPIPE        1
+#define LIBSSH2_FLAG_COMPRESS       2
+
+typedef struct _LIBSSH2_SESSION                     LIBSSH2_SESSION;
+typedef struct _LIBSSH2_CHANNEL                     LIBSSH2_CHANNEL;
+typedef struct _LIBSSH2_LISTENER                    LIBSSH2_LISTENER;
+typedef struct _LIBSSH2_KNOWNHOSTS                  LIBSSH2_KNOWNHOSTS;
+typedef struct _LIBSSH2_AGENT                       LIBSSH2_AGENT;
+
+typedef struct _LIBSSH2_POLLFD {
+    unsigned char type; /* LIBSSH2_POLLFD_* below */
+
+    union {
+        libssh2_socket_t socket; /* File descriptors -- examined with
+                                    system select() call */
+        LIBSSH2_CHANNEL *channel; /* Examined by checking internal state */
+        LIBSSH2_LISTENER *listener; /* Read polls only -- are inbound
+                                       connections waiting to be accepted? */
+    } fd;
+
+    unsigned long events; /* Requested Events */
+    unsigned long revents; /* Returned Events */
+} LIBSSH2_POLLFD;
+
+/* Poll FD Descriptor Types */
+#define LIBSSH2_POLLFD_SOCKET       1
+#define LIBSSH2_POLLFD_CHANNEL      2
+#define LIBSSH2_POLLFD_LISTENER     3
+
+/* Note: Win32 Doesn't actually have a poll() implementation, so some of these
+   values are faked with select() data */
+/* Poll FD events/revents -- Match sys/poll.h where possible */
+#define LIBSSH2_POLLFD_POLLIN           0x0001 /* Data available to be read or
+                                                  connection available --
+                                                  All */
+#define LIBSSH2_POLLFD_POLLPRI          0x0002 /* Priority data available to
+                                                  be read -- Socket only */
+#define LIBSSH2_POLLFD_POLLEXT          0x0002 /* Extended data available to
+                                                  be read -- Channel only */
+#define LIBSSH2_POLLFD_POLLOUT          0x0004 /* Can may be written --
+                                                  Socket/Channel */
+/* revents only */
+#define LIBSSH2_POLLFD_POLLERR          0x0008 /* Error Condition -- Socket */
+#define LIBSSH2_POLLFD_POLLHUP          0x0010 /* HangUp/EOF -- Socket */
+#define LIBSSH2_POLLFD_SESSION_CLOSED   0x0010 /* Session Disconnect */
+#define LIBSSH2_POLLFD_POLLNVAL         0x0020 /* Invalid request -- Socket
+                                                  Only */
+#define LIBSSH2_POLLFD_POLLEX           0x0040 /* Exception Condition --
+                                                  Socket/Win32 */
+#define LIBSSH2_POLLFD_CHANNEL_CLOSED   0x0080 /* Channel Disconnect */
+#define LIBSSH2_POLLFD_LISTENER_CLOSED  0x0080 /* Listener Disconnect */
+
+#define HAVE_LIBSSH2_SESSION_BLOCK_DIRECTION
+/* Block Direction Types */
+#define LIBSSH2_SESSION_BLOCK_INBOUND                  0x0001
+#define LIBSSH2_SESSION_BLOCK_OUTBOUND                 0x0002
+
+/* Hash Types */
+#define LIBSSH2_HOSTKEY_HASH_MD5                            1
+#define LIBSSH2_HOSTKEY_HASH_SHA1                           2
+#define LIBSSH2_HOSTKEY_HASH_SHA256                         3
+
+/* Hostkey Types */
+#define LIBSSH2_HOSTKEY_TYPE_UNKNOWN            0
+#define LIBSSH2_HOSTKEY_TYPE_RSA                1
+#define LIBSSH2_HOSTKEY_TYPE_DSS                2
+#define LIBSSH2_HOSTKEY_TYPE_ECDSA_256          3
+#define LIBSSH2_HOSTKEY_TYPE_ECDSA_384          4
+#define LIBSSH2_HOSTKEY_TYPE_ECDSA_521          5
+#define LIBSSH2_HOSTKEY_TYPE_ED25519            6
+
+/* Disconnect Codes (defined by SSH protocol) */
+#define SSH_DISCONNECT_HOST_NOT_ALLOWED_TO_CONNECT          1
+#define SSH_DISCONNECT_PROTOCOL_ERROR                       2
+#define SSH_DISCONNECT_KEY_EXCHANGE_FAILED                  3
+#define SSH_DISCONNECT_RESERVED                             4
+#define SSH_DISCONNECT_MAC_ERROR                            5
+#define SSH_DISCONNECT_COMPRESSION_ERROR                    6
+#define SSH_DISCONNECT_SERVICE_NOT_AVAILABLE                7
+#define SSH_DISCONNECT_PROTOCOL_VERSION_NOT_SUPPORTED       8
+#define SSH_DISCONNECT_HOST_KEY_NOT_VERIFIABLE              9
+#define SSH_DISCONNECT_CONNECTION_LOST                      10
+#define SSH_DISCONNECT_BY_APPLICATION                       11
+#define SSH_DISCONNECT_TOO_MANY_CONNECTIONS                 12
+#define SSH_DISCONNECT_AUTH_CANCELLED_BY_USER               13
+#define SSH_DISCONNECT_NO_MORE_AUTH_METHODS_AVAILABLE       14
+#define SSH_DISCONNECT_ILLEGAL_USER_NAME                    15
+
+/* Error Codes (defined by libssh2) */
+#define LIBSSH2_ERROR_NONE                      0
+
+/* The library once used -1 as a generic error return value on numerous places
+   through the code, which subsequently was converted to
+   LIBSSH2_ERROR_SOCKET_NONE uses over time. As this is a generic error code,
+   the goal is to never ever return this code but instead make sure that a
+   more accurate and descriptive error code is used. */
+#define LIBSSH2_ERROR_SOCKET_NONE               -1
+
+#define LIBSSH2_ERROR_BANNER_RECV               -2
+#define LIBSSH2_ERROR_BANNER_SEND               -3
+#define LIBSSH2_ERROR_INVALID_MAC               -4
+#define LIBSSH2_ERROR_KEX_FAILURE               -5
+#define LIBSSH2_ERROR_ALLOC                     -6
+#define LIBSSH2_ERROR_SOCKET_SEND               -7
+#define LIBSSH2_ERROR_KEY_EXCHANGE_FAILURE      -8
+#define LIBSSH2_ERROR_TIMEOUT                   -9
+#define LIBSSH2_ERROR_HOSTKEY_INIT              -10
+#define LIBSSH2_ERROR_HOSTKEY_SIGN              -11
+#define LIBSSH2_ERROR_DECRYPT                   -12
+#define LIBSSH2_ERROR_SOCKET_DISCONNECT         -13
+#define LIBSSH2_ERROR_PROTO                     -14
+#define LIBSSH2_ERROR_PASSWORD_EXPIRED          -15
+#define LIBSSH2_ERROR_FILE                      -16
+#define LIBSSH2_ERROR_METHOD_NONE               -17
+#define LIBSSH2_ERROR_AUTHENTICATION_FAILED     -18
+#define LIBSSH2_ERROR_PUBLICKEY_UNRECOGNIZED    \
+    LIBSSH2_ERROR_AUTHENTICATION_FAILED
+#define LIBSSH2_ERROR_PUBLICKEY_UNVERIFIED      -19
+#define LIBSSH2_ERROR_CHANNEL_OUTOFORDER        -20
+#define LIBSSH2_ERROR_CHANNEL_FAILURE           -21
+#define LIBSSH2_ERROR_CHANNEL_REQUEST_DENIED    -22
+#define LIBSSH2_ERROR_CHANNEL_UNKNOWN           -23
+#define LIBSSH2_ERROR_CHANNEL_WINDOW_EXCEEDED   -24
+#define LIBSSH2_ERROR_CHANNEL_PACKET_EXCEEDED   -25
+#define LIBSSH2_ERROR_CHANNEL_CLOSED            -26
+#define LIBSSH2_ERROR_CHANNEL_EOF_SENT          -27
+#define LIBSSH2_ERROR_SCP_PROTOCOL              -28
+#define LIBSSH2_ERROR_ZLIB                      -29
+#define LIBSSH2_ERROR_SOCKET_TIMEOUT            -30
+#define LIBSSH2_ERROR_SFTP_PROTOCOL             -31
+#define LIBSSH2_ERROR_REQUEST_DENIED            -32
+#define LIBSSH2_ERROR_METHOD_NOT_SUPPORTED      -33
+#define LIBSSH2_ERROR_INVAL                     -34
+#define LIBSSH2_ERROR_INVALID_POLL_TYPE         -35
+#define LIBSSH2_ERROR_PUBLICKEY_PROTOCOL        -36
+#define LIBSSH2_ERROR_EAGAIN                    -37
+#define LIBSSH2_ERROR_BUFFER_TOO_SMALL          -38
+#define LIBSSH2_ERROR_BAD_USE                   -39
+#define LIBSSH2_ERROR_COMPRESS                  -40
+#define LIBSSH2_ERROR_OUT_OF_BOUNDARY           -41
+#define LIBSSH2_ERROR_AGENT_PROTOCOL            -42
+#define LIBSSH2_ERROR_SOCKET_RECV               -43
+#define LIBSSH2_ERROR_ENCRYPT                   -44
+#define LIBSSH2_ERROR_BAD_SOCKET                -45
+#define LIBSSH2_ERROR_KNOWN_HOSTS               -46
+#define LIBSSH2_ERROR_CHANNEL_WINDOW_FULL       -47
+#define LIBSSH2_ERROR_KEYFILE_AUTH_FAILED       -48
+
+/* this is a define to provide the old (<= 1.2.7) name */
+#define LIBSSH2_ERROR_BANNER_NONE LIBSSH2_ERROR_BANNER_RECV
+
+/* Global API */
+#define LIBSSH2_INIT_NO_CRYPTO        0x0001
+
+/*
+ * libssh2_init()
+ *
+ * Initialize the libssh2 functions.  This typically initialize the
+ * crypto library.  It uses a global state, and is not thread safe --
+ * you must make sure this function is not called concurrently.
+ *
+ * Flags can be:
+ * 0:                              Normal initialize
+ * LIBSSH2_INIT_NO_CRYPTO:         Do not initialize the crypto library (ie.
+ *                                 OPENSSL_add_cipher_algoritms() for OpenSSL
+ *
+ * Returns 0 if succeeded, or a negative value for error.
+ */
+LIBSSH2_API int libssh2_init(int flags);
+
+/*
+ * libssh2_exit()
+ *
+ * Exit the libssh2 functions and free's all memory used internal.
+ */
+LIBSSH2_API void libssh2_exit(void);
+
+/*
+ * libssh2_free()
+ *
+ * Deallocate memory allocated by earlier call to libssh2 functions.
+ */
+LIBSSH2_API void libssh2_free(LIBSSH2_SESSION *session, void *ptr);
+
+/*
+ * libssh2_session_supported_algs()
+ *
+ * Fills algs with a list of supported acryptographic algorithms. Returns a
+ * non-negative number (number of supported algorithms) on success or a
+ * negative number (an eror code) on failure.
+ *
+ * NOTE: on success, algs must be deallocated (by calling libssh2_free) when
+ * not needed anymore
+ */
+LIBSSH2_API int libssh2_session_supported_algs(LIBSSH2_SESSION* session,
+                                               int method_type,
+                                               const char ***algs);
+
+/* Session API */
+LIBSSH2_API LIBSSH2_SESSION *
+libssh2_session_init_ex(LIBSSH2_ALLOC_FUNC((*my_alloc)),
+                        LIBSSH2_FREE_FUNC((*my_free)),
+                        LIBSSH2_REALLOC_FUNC((*my_realloc)), void *abstract);
+#define libssh2_session_init() libssh2_session_init_ex(NULL, NULL, NULL, NULL)
+
+LIBSSH2_API void **libssh2_session_abstract(LIBSSH2_SESSION *session);
+
+LIBSSH2_API void *libssh2_session_callback_set(LIBSSH2_SESSION *session,
+                                               int cbtype, void *callback);
+LIBSSH2_API int libssh2_session_banner_set(LIBSSH2_SESSION *session,
+                                           const char *banner);
+LIBSSH2_API int libssh2_banner_set(LIBSSH2_SESSION *session,
+                                   const char *banner);
+
+LIBSSH2_API int libssh2_session_startup(LIBSSH2_SESSION *session, int sock);
+LIBSSH2_API int libssh2_session_handshake(LIBSSH2_SESSION *session,
+                                          libssh2_socket_t sock);
+LIBSSH2_API int libssh2_session_disconnect_ex(LIBSSH2_SESSION *session,
+                                              int reason,
+                                              const char *description,
+                                              const char *lang);
+#define libssh2_session_disconnect(session, description) \
+  libssh2_session_disconnect_ex((session), SSH_DISCONNECT_BY_APPLICATION, \
+                                (description), "")
+
+LIBSSH2_API int libssh2_session_free(LIBSSH2_SESSION *session);
+
+LIBSSH2_API const char *libssh2_hostkey_hash(LIBSSH2_SESSION *session,
+                                             int hash_type);
+
+LIBSSH2_API const char *libssh2_session_hostkey(LIBSSH2_SESSION *session,
+                                                size_t *len, int *type);
+
+LIBSSH2_API int libssh2_session_method_pref(LIBSSH2_SESSION *session,
+                                            int method_type,
+                                            const char *prefs);
+LIBSSH2_API const char *libssh2_session_methods(LIBSSH2_SESSION *session,
+                                                int method_type);
+LIBSSH2_API int libssh2_session_last_error(LIBSSH2_SESSION *session,
+                                           char **errmsg,
+                                           int *errmsg_len, int want_buf);
+LIBSSH2_API int libssh2_session_last_errno(LIBSSH2_SESSION *session);
+LIBSSH2_API int libssh2_session_set_last_error(LIBSSH2_SESSION* session,
+                                               int errcode,
+                                               const char *errmsg);
+LIBSSH2_API int libssh2_session_block_directions(LIBSSH2_SESSION *session);
+
+LIBSSH2_API int libssh2_session_flag(LIBSSH2_SESSION *session, int flag,
+                                     int value);
+LIBSSH2_API const char *libssh2_session_banner_get(LIBSSH2_SESSION *session);
+
+/* Userauth API */
+LIBSSH2_API char *libssh2_userauth_list(LIBSSH2_SESSION *session,
+                                        const char *username,
+                                        unsigned int username_len);
+LIBSSH2_API int libssh2_userauth_authenticated(LIBSSH2_SESSION *session);
+
+LIBSSH2_API int
+libssh2_userauth_password_ex(LIBSSH2_SESSION *session,
+                             const char *username,
+                             unsigned int username_len,
+                             const char *password,
+                             unsigned int password_len,
+                             LIBSSH2_PASSWD_CHANGEREQ_FUNC
+                             ((*passwd_change_cb)));
+
+#define libssh2_userauth_password(session, username, password) \
+ libssh2_userauth_password_ex((session), (username),           \
+                              (unsigned int)strlen(username),  \
+                              (password), (unsigned int)strlen(password), NULL)
+
+LIBSSH2_API int
+libssh2_userauth_publickey_fromfile_ex(LIBSSH2_SESSION *session,
+                                       const char *username,
+                                       unsigned int username_len,
+                                       const char *publickey,
+                                       const char *privatekey,
+                                       const char *passphrase);
+
+#define libssh2_userauth_publickey_fromfile(session, username, publickey, \
+                                            privatekey, passphrase)     \
+    libssh2_userauth_publickey_fromfile_ex((session), (username),       \
+                                           (unsigned int)strlen(username), \
+                                           (publickey),                 \
+                                           (privatekey), (passphrase))
+
+LIBSSH2_API int
+libssh2_userauth_publickey(LIBSSH2_SESSION *session,
+                           const char *username,
+                           const unsigned char *pubkeydata,
+                           size_t pubkeydata_len,
+                           LIBSSH2_USERAUTH_PUBLICKEY_SIGN_FUNC
+                           ((*sign_callback)),
+                           void **abstract);
+
+LIBSSH2_API int
+libssh2_userauth_hostbased_fromfile_ex(LIBSSH2_SESSION *session,
+                                       const char *username,
+                                       unsigned int username_len,
+                                       const char *publickey,
+                                       const char *privatekey,
+                                       const char *passphrase,
+                                       const char *hostname,
+                                       unsigned int hostname_len,
+                                       const char *local_username,
+                                       unsigned int local_username_len);
+
+#define libssh2_userauth_hostbased_fromfile(session, username, publickey, \
+                                            privatekey, passphrase, hostname) \
+ libssh2_userauth_hostbased_fromfile_ex((session), (username), \
+                                        (unsigned int)strlen(username), \
+                                        (publickey),                    \
+                                        (privatekey), (passphrase),     \
+                                        (hostname),                     \
+                                        (unsigned int)strlen(hostname), \
+                                        (username),                     \
+                                        (unsigned int)strlen(username))
+
+LIBSSH2_API int
+libssh2_userauth_publickey_frommemory(LIBSSH2_SESSION *session,
+                                      const char *username,
+                                      size_t username_len,
+                                      const char *publickeyfiledata,
+                                      size_t publickeyfiledata_len,
+                                      const char *privatekeyfiledata,
+                                      size_t privatekeyfiledata_len,
+                                      const char *passphrase);
+
+/*
+ * response_callback is provided with filled by library prompts array,
+ * but client must allocate and fill individual responses. Responses
+ * array is already allocated. Responses data will be freed by libssh2
+ * after callback return, but before subsequent callback invokation.
+ */
+LIBSSH2_API int
+libssh2_userauth_keyboard_interactive_ex(LIBSSH2_SESSION* session,
+                                         const char *username,
+                                         unsigned int username_len,
+                                         LIBSSH2_USERAUTH_KBDINT_RESPONSE_FUNC(
+                                                       (*response_callback)));
+
+#define libssh2_userauth_keyboard_interactive(session, username,        \
+                                              response_callback)        \
+    libssh2_userauth_keyboard_interactive_ex((session), (username),     \
+                                             (unsigned int)strlen(username), \
+                                             (response_callback))
+
+LIBSSH2_API int libssh2_poll(LIBSSH2_POLLFD *fds, unsigned int nfds,
+                             long timeout);
+
+/* Channel API */
+#define LIBSSH2_CHANNEL_WINDOW_DEFAULT  (2*1024*1024)
+#define LIBSSH2_CHANNEL_PACKET_DEFAULT  32768
+#define LIBSSH2_CHANNEL_MINADJUST       1024
+
+/* Extended Data Handling */
+#define LIBSSH2_CHANNEL_EXTENDED_DATA_NORMAL        0
+#define LIBSSH2_CHANNEL_EXTENDED_DATA_IGNORE        1
+#define LIBSSH2_CHANNEL_EXTENDED_DATA_MERGE         2
+
+#define SSH_EXTENDED_DATA_STDERR 1
+
+/* Returned by any function that would block during a read/write opperation */
+#define LIBSSH2CHANNEL_EAGAIN LIBSSH2_ERROR_EAGAIN
+
+LIBSSH2_API LIBSSH2_CHANNEL *
+libssh2_channel_open_ex(LIBSSH2_SESSION *session, const char *channel_type,
+                        unsigned int channel_type_len,
+                        unsigned int window_size, unsigned int packet_size,
+                        const char *message, unsigned int message_len);
+
+#define libssh2_channel_open_session(session) \
+  libssh2_channel_open_ex((session), "session", sizeof("session") - 1, \
+                          LIBSSH2_CHANNEL_WINDOW_DEFAULT, \
+                          LIBSSH2_CHANNEL_PACKET_DEFAULT, NULL, 0)
+
+LIBSSH2_API LIBSSH2_CHANNEL *
+libssh2_channel_direct_tcpip_ex(LIBSSH2_SESSION *session, const char *host,
+                                int port, const char *shost, int sport);
+#define libssh2_channel_direct_tcpip(session, host, port) \
+  libssh2_channel_direct_tcpip_ex((session), (host), (port), "127.0.0.1", 22)
+
+LIBSSH2_API LIBSSH2_LISTENER *
+libssh2_channel_forward_listen_ex(LIBSSH2_SESSION *session, const char *host,
+                                  int port, int *bound_port,
+                                  int queue_maxsize);
+#define libssh2_channel_forward_listen(session, port) \
+ libssh2_channel_forward_listen_ex((session), NULL, (port), NULL, 16)
+
+LIBSSH2_API int libssh2_channel_forward_cancel(LIBSSH2_LISTENER *listener);
+
+LIBSSH2_API LIBSSH2_CHANNEL *
+libssh2_channel_forward_accept(LIBSSH2_LISTENER *listener);
+
+LIBSSH2_API int libssh2_channel_setenv_ex(LIBSSH2_CHANNEL *channel,
+                                          const char *varname,
+                                          unsigned int varname_len,
+                                          const char *value,
+                                          unsigned int value_len);
+
+#define libssh2_channel_setenv(channel, varname, value)                 \
+    libssh2_channel_setenv_ex((channel), (varname),                     \
+                              (unsigned int)strlen(varname), (value),   \
+                              (unsigned int)strlen(value))
+
+LIBSSH2_API int libssh2_channel_request_pty_ex(LIBSSH2_CHANNEL *channel,
+                                               const char *term,
+                                               unsigned int term_len,
+                                               const char *modes,
+                                               unsigned int modes_len,
+                                               int width, int height,
+                                               int width_px, int height_px);
+#define libssh2_channel_request_pty(channel, term)                      \
+    libssh2_channel_request_pty_ex((channel), (term),                   \
+                                   (unsigned int)strlen(term),          \
+                                   NULL, 0,                             \
+                                   LIBSSH2_TERM_WIDTH,                  \
+                                   LIBSSH2_TERM_HEIGHT,                 \
+                                   LIBSSH2_TERM_WIDTH_PX,               \
+                                   LIBSSH2_TERM_HEIGHT_PX)
+
+LIBSSH2_API int libssh2_channel_request_pty_size_ex(LIBSSH2_CHANNEL *channel,
+                                                    int width, int height,
+                                                    int width_px,
+                                                    int height_px);
+#define libssh2_channel_request_pty_size(channel, width, height) \
+  libssh2_channel_request_pty_size_ex((channel), (width), (height), 0, 0)
+
+LIBSSH2_API int libssh2_channel_x11_req_ex(LIBSSH2_CHANNEL *channel,
+                                           int single_connection,
+                                           const char *auth_proto,
+                                           const char *auth_cookie,
+                                           int screen_number);
+#define libssh2_channel_x11_req(channel, screen_number) \
+ libssh2_channel_x11_req_ex((channel), 0, NULL, NULL, (screen_number))
+
+LIBSSH2_API int libssh2_channel_process_startup(LIBSSH2_CHANNEL *channel,
+                                                const char *request,
+                                                unsigned int request_len,
+                                                const char *message,
+                                                unsigned int message_len);
+#define libssh2_channel_shell(channel) \
+  libssh2_channel_process_startup((channel), "shell", sizeof("shell") - 1, \
+                                  NULL, 0)
+#define libssh2_channel_exec(channel, command) \
+  libssh2_channel_process_startup((channel), "exec", sizeof("exec") - 1, \
+                                  (command), (unsigned int)strlen(command))
+#define libssh2_channel_subsystem(channel, subsystem) \
+  libssh2_channel_process_startup((channel), "subsystem",              \
+                                  sizeof("subsystem") - 1, (subsystem), \
+                                  (unsigned int)strlen(subsystem))
+
+LIBSSH2_API ssize_t libssh2_channel_read_ex(LIBSSH2_CHANNEL *channel,
+                                            int stream_id, char *buf,
+                                            size_t buflen);
+#define libssh2_channel_read(channel, buf, buflen) \
+  libssh2_channel_read_ex((channel), 0, (buf), (buflen))
+#define libssh2_channel_read_stderr(channel, buf, buflen) \
+  libssh2_channel_read_ex((channel), SSH_EXTENDED_DATA_STDERR, (buf), (buflen))
+
+LIBSSH2_API int libssh2_poll_channel_read(LIBSSH2_CHANNEL *channel,
+                                          int extended);
+
+LIBSSH2_API unsigned long
+libssh2_channel_window_read_ex(LIBSSH2_CHANNEL *channel,
+                               unsigned long *read_avail,
+                               unsigned long *window_size_initial);
+#define libssh2_channel_window_read(channel) \
+  libssh2_channel_window_read_ex((channel), NULL, NULL)
+
+/* libssh2_channel_receive_window_adjust is DEPRECATED, do not use! */
+LIBSSH2_API unsigned long
+libssh2_channel_receive_window_adjust(LIBSSH2_CHANNEL *channel,
+                                      unsigned long adjustment,
+                                      unsigned char force);
+
+LIBSSH2_API int
+libssh2_channel_receive_window_adjust2(LIBSSH2_CHANNEL *channel,
+                                       unsigned long adjustment,
+                                       unsigned char force,
+                                       unsigned int *storewindow);
+
+LIBSSH2_API ssize_t libssh2_channel_write_ex(LIBSSH2_CHANNEL *channel,
+                                             int stream_id, const char *buf,
+                                             size_t buflen);
+
+#define libssh2_channel_write(channel, buf, buflen) \
+  libssh2_channel_write_ex((channel), 0, (buf), (buflen))
+#define libssh2_channel_write_stderr(channel, buf, buflen)              \
+    libssh2_channel_write_ex((channel), SSH_EXTENDED_DATA_STDERR,       \
+                             (buf), (buflen))
+
+LIBSSH2_API unsigned long
+libssh2_channel_window_write_ex(LIBSSH2_CHANNEL *channel,
+                                unsigned long *window_size_initial);
+#define libssh2_channel_window_write(channel) \
+  libssh2_channel_window_write_ex((channel), NULL)
+
+LIBSSH2_API void libssh2_session_set_blocking(LIBSSH2_SESSION* session,
+                                              int blocking);
+LIBSSH2_API int libssh2_session_get_blocking(LIBSSH2_SESSION* session);
+
+LIBSSH2_API void libssh2_channel_set_blocking(LIBSSH2_CHANNEL *channel,
+                                              int blocking);
+
+LIBSSH2_API void libssh2_session_set_timeout(LIBSSH2_SESSION* session,
+                                             long timeout);
+LIBSSH2_API long libssh2_session_get_timeout(LIBSSH2_SESSION* session);
+
+/* libssh2_channel_handle_extended_data is DEPRECATED, do not use! */
+LIBSSH2_API void libssh2_channel_handle_extended_data(LIBSSH2_CHANNEL *channel,
+                                                      int ignore_mode);
+LIBSSH2_API int libssh2_channel_handle_extended_data2(LIBSSH2_CHANNEL *channel,
+                                                      int ignore_mode);
+
+/* libssh2_channel_ignore_extended_data() is defined below for BC with version
+ * 0.1
+ *
+ * Future uses should use libssh2_channel_handle_extended_data() directly if
+ * LIBSSH2_CHANNEL_EXTENDED_DATA_MERGE is passed, extended data will be read
+ * (FIFO) from the standard data channel
+ */
+/* DEPRECATED */
+#define libssh2_channel_ignore_extended_data(channel, ignore) \
+  libssh2_channel_handle_extended_data((channel),                       \
+                                       (ignore) ?                       \
+                                       LIBSSH2_CHANNEL_EXTENDED_DATA_IGNORE : \
+                                       LIBSSH2_CHANNEL_EXTENDED_DATA_NORMAL)
+
+#define LIBSSH2_CHANNEL_FLUSH_EXTENDED_DATA     -1
+#define LIBSSH2_CHANNEL_FLUSH_ALL               -2
+LIBSSH2_API int libssh2_channel_flush_ex(LIBSSH2_CHANNEL *channel,
+                                         int streamid);
+#define libssh2_channel_flush(channel) libssh2_channel_flush_ex((channel), 0)
+#define libssh2_channel_flush_stderr(channel) \
+ libssh2_channel_flush_ex((channel), SSH_EXTENDED_DATA_STDERR)
+
+LIBSSH2_API int libssh2_channel_get_exit_status(LIBSSH2_CHANNEL* channel);
+LIBSSH2_API int libssh2_channel_get_exit_signal(LIBSSH2_CHANNEL* channel,
+                                                char **exitsignal,
+                                                size_t *exitsignal_len,
+                                                char **errmsg,
+                                                size_t *errmsg_len,
+                                                char **langtag,
+                                                size_t *langtag_len);
+LIBSSH2_API int libssh2_channel_send_eof(LIBSSH2_CHANNEL *channel);
+LIBSSH2_API int libssh2_channel_eof(LIBSSH2_CHANNEL *channel);
+LIBSSH2_API int libssh2_channel_wait_eof(LIBSSH2_CHANNEL *channel);
+LIBSSH2_API int libssh2_channel_close(LIBSSH2_CHANNEL *channel);
+LIBSSH2_API int libssh2_channel_wait_closed(LIBSSH2_CHANNEL *channel);
+LIBSSH2_API int libssh2_channel_free(LIBSSH2_CHANNEL *channel);
+
+/* libssh2_scp_recv is DEPRECATED, do not use! */
+LIBSSH2_API LIBSSH2_CHANNEL *libssh2_scp_recv(LIBSSH2_SESSION *session,
+                                              const char *path,
+                                              struct stat *sb);
+/* Use libssh2_scp_recv2 for large (> 2GB) file support on windows */
+LIBSSH2_API LIBSSH2_CHANNEL *libssh2_scp_recv2(LIBSSH2_SESSION *session,
+                                               const char *path,
+                                               libssh2_struct_stat *sb);
+LIBSSH2_API LIBSSH2_CHANNEL *libssh2_scp_send_ex(LIBSSH2_SESSION *session,
+                                                 const char *path, int mode,
+                                                 size_t size, long mtime,
+                                                 long atime);
+LIBSSH2_API LIBSSH2_CHANNEL *
+libssh2_scp_send64(LIBSSH2_SESSION *session, const char *path, int mode,
+                   libssh2_int64_t size, time_t mtime, time_t atime);
+
+#define libssh2_scp_send(session, path, mode, size) \
+  libssh2_scp_send_ex((session), (path), (mode), (size), 0, 0)
+
+LIBSSH2_API int libssh2_base64_decode(LIBSSH2_SESSION *session, char **dest,
+                                      unsigned int *dest_len,
+                                      const char *src, unsigned int src_len);
+
+LIBSSH2_API
+const char *libssh2_version(int req_version_num);
+
+#define HAVE_LIBSSH2_KNOWNHOST_API 0x010101 /* since 1.1.1 */
+#define HAVE_LIBSSH2_VERSION_API   0x010100 /* libssh2_version since 1.1 */
+
+struct libssh2_knownhost {
+    unsigned int magic;  /* magic stored by the library */
+    void *node; /* handle to the internal representation of this host */
+    char *name; /* this is NULL if no plain text host name exists */
+    char *key;  /* key in base64/printable format */
+    int typemask;
+};
+
+/*
+ * libssh2_knownhost_init
+ *
+ * Init a collection of known hosts. Returns the pointer to a collection.
+ *
+ */
+LIBSSH2_API LIBSSH2_KNOWNHOSTS *
+libssh2_knownhost_init(LIBSSH2_SESSION *session);
+
+/*
+ * libssh2_knownhost_add
+ *
+ * Add a host and its associated key to the collection of known hosts.
+ *
+ * The 'type' argument specifies on what format the given host and keys are:
+ *
+ * plain  - ascii "hostname.domain.tld"
+ * sha1   - SHA1(<salt> <host>) base64-encoded!
+ * custom - another hash
+ *
+ * If 'sha1' is selected as type, the salt must be provided to the salt
+ * argument. This too base64 encoded.
+ *
+ * The SHA-1 hash is what OpenSSH can be told to use in known_hosts files.  If
+ * a custom type is used, salt is ignored and you must provide the host
+ * pre-hashed when checking for it in the libssh2_knownhost_check() function.
+ *
+ * The keylen parameter may be omitted (zero) if the key is provided as a
+ * NULL-terminated base64-encoded string.
+ */
+
+/* host format (2 bits) */
+#define LIBSSH2_KNOWNHOST_TYPE_MASK    0xffff
+#define LIBSSH2_KNOWNHOST_TYPE_PLAIN   1
+#define LIBSSH2_KNOWNHOST_TYPE_SHA1    2 /* always base64 encoded */
+#define LIBSSH2_KNOWNHOST_TYPE_CUSTOM  3
+
+/* key format (2 bits) */
+#define LIBSSH2_KNOWNHOST_KEYENC_MASK     (3<<16)
+#define LIBSSH2_KNOWNHOST_KEYENC_RAW      (1<<16)
+#define LIBSSH2_KNOWNHOST_KEYENC_BASE64   (2<<16)
+
+/* type of key (3 bits) */
+#define LIBSSH2_KNOWNHOST_KEY_MASK         (15<<18)
+#define LIBSSH2_KNOWNHOST_KEY_SHIFT        18
+#define LIBSSH2_KNOWNHOST_KEY_RSA1         (1<<18)
+#define LIBSSH2_KNOWNHOST_KEY_SSHRSA       (2<<18)
+#define LIBSSH2_KNOWNHOST_KEY_SSHDSS       (3<<18)
+#define LIBSSH2_KNOWNHOST_KEY_ECDSA_256    (4<<18)
+#define LIBSSH2_KNOWNHOST_KEY_ECDSA_384    (5<<18)
+#define LIBSSH2_KNOWNHOST_KEY_ECDSA_521    (6<<18)
+#define LIBSSH2_KNOWNHOST_KEY_ED25519      (7<<18)
+#define LIBSSH2_KNOWNHOST_KEY_UNKNOWN      (15<<18)
+
+LIBSSH2_API int
+libssh2_knownhost_add(LIBSSH2_KNOWNHOSTS *hosts,
+                      const char *host,
+                      const char *salt,
+                      const char *key, size_t keylen, int typemask,
+                      struct libssh2_knownhost **store);
+
+/*
+ * libssh2_knownhost_addc
+ *
+ * Add a host and its associated key to the collection of known hosts.
+ *
+ * Takes a comment argument that may be NULL.  A NULL comment indicates
+ * there is no comment and the entry will end directly after the key
+ * when written out to a file.  An empty string "" comment will indicate an
+ * empty comment which will cause a single space to be written after the key.
+ *
+ * The 'type' argument specifies on what format the given host and keys are:
+ *
+ * plain  - ascii "hostname.domain.tld"
+ * sha1   - SHA1(<salt> <host>) base64-encoded!
+ * custom - another hash
+ *
+ * If 'sha1' is selected as type, the salt must be provided to the salt
+ * argument. This too base64 encoded.
+ *
+ * The SHA-1 hash is what OpenSSH can be told to use in known_hosts files.  If
+ * a custom type is used, salt is ignored and you must provide the host
+ * pre-hashed when checking for it in the libssh2_knownhost_check() function.
+ *
+ * The keylen parameter may be omitted (zero) if the key is provided as a
+ * NULL-terminated base64-encoded string.
+ */
+
+LIBSSH2_API int
+libssh2_knownhost_addc(LIBSSH2_KNOWNHOSTS *hosts,
+                       const char *host,
+                       const char *salt,
+                       const char *key, size_t keylen,
+                       const char *comment, size_t commentlen, int typemask,
+                       struct libssh2_knownhost **store);
+
+/*
+ * libssh2_knownhost_check
+ *
+ * Check a host and its associated key against the collection of known hosts.
+ *
+ * The type is the type/format of the given host name.
+ *
+ * plain  - ascii "hostname.domain.tld"
+ * custom - prehashed base64 encoded. Note that this cannot use any salts.
+ *
+ *
+ * 'knownhost' may be set to NULL if you don't care about that info.
+ *
+ * Returns:
+ *
+ * LIBSSH2_KNOWNHOST_CHECK_* values, see below
+ *
+ */
+
+#define LIBSSH2_KNOWNHOST_CHECK_MATCH    0
+#define LIBSSH2_KNOWNHOST_CHECK_MISMATCH 1
+#define LIBSSH2_KNOWNHOST_CHECK_NOTFOUND 2
+#define LIBSSH2_KNOWNHOST_CHECK_FAILURE  3
+
+LIBSSH2_API int
+libssh2_knownhost_check(LIBSSH2_KNOWNHOSTS *hosts,
+                        const char *host, const char *key, size_t keylen,
+                        int typemask,
+                        struct libssh2_knownhost **knownhost);
+
+/* this function is identital to the above one, but also takes a port
+   argument that allows libssh2 to do a better check */
+LIBSSH2_API int
+libssh2_knownhost_checkp(LIBSSH2_KNOWNHOSTS *hosts,
+                         const char *host, int port,
+                         const char *key, size_t keylen,
+                         int typemask,
+                         struct libssh2_knownhost **knownhost);
+
+/*
+ * libssh2_knownhost_del
+ *
+ * Remove a host from the collection of known hosts. The 'entry' struct is
+ * retrieved by a call to libssh2_knownhost_check().
+ *
+ */
+LIBSSH2_API int
+libssh2_knownhost_del(LIBSSH2_KNOWNHOSTS *hosts,
+                      struct libssh2_knownhost *entry);
+
+/*
+ * libssh2_knownhost_free
+ *
+ * Free an entire collection of known hosts.
+ *
+ */
+LIBSSH2_API void
+libssh2_knownhost_free(LIBSSH2_KNOWNHOSTS *hosts);
+
+/*
+ * libssh2_knownhost_readline()
+ *
+ * Pass in a line of a file of 'type'. It makes libssh2 read this line.
+ *
+ * LIBSSH2_KNOWNHOST_FILE_OPENSSH is the only supported type.
+ *
+ */
+LIBSSH2_API int
+libssh2_knownhost_readline(LIBSSH2_KNOWNHOSTS *hosts,
+                           const char *line, size_t len, int type);
+
+/*
+ * libssh2_knownhost_readfile
+ *
+ * Add hosts+key pairs from a given file.
+ *
+ * Returns a negative value for error or number of successfully added hosts.
+ *
+ * This implementation currently only knows one 'type' (openssh), all others
+ * are reserved for future use.
+ */
+
+#define LIBSSH2_KNOWNHOST_FILE_OPENSSH 1
+
+LIBSSH2_API int
+libssh2_knownhost_readfile(LIBSSH2_KNOWNHOSTS *hosts,
+                           const char *filename, int type);
+
+/*
+ * libssh2_knownhost_writeline()
+ *
+ * Ask libssh2 to convert a known host to an output line for storage.
+ *
+ * Note that this function returns LIBSSH2_ERROR_BUFFER_TOO_SMALL if the given
+ * output buffer is too small to hold the desired output.
+ *
+ * This implementation currently only knows one 'type' (openssh), all others
+ * are reserved for future use.
+ *
+ */
+LIBSSH2_API int
+libssh2_knownhost_writeline(LIBSSH2_KNOWNHOSTS *hosts,
+                            struct libssh2_knownhost *known,
+                            char *buffer, size_t buflen,
+                            size_t *outlen, /* the amount of written data */
+                            int type);
+
+/*
+ * libssh2_knownhost_writefile
+ *
+ * Write hosts+key pairs to a given file.
+ *
+ * This implementation currently only knows one 'type' (openssh), all others
+ * are reserved for future use.
+ */
+
+LIBSSH2_API int
+libssh2_knownhost_writefile(LIBSSH2_KNOWNHOSTS *hosts,
+                            const char *filename, int type);
+
+/*
+ * libssh2_knownhost_get()
+ *
+ * Traverse the internal list of known hosts. Pass NULL to 'prev' to get
+ * the first one. Or pass a poiner to the previously returned one to get the
+ * next.
+ *
+ * Returns:
+ * 0 if a fine host was stored in 'store'
+ * 1 if end of hosts
+ * [negative] on errors
+ */
+LIBSSH2_API int
+libssh2_knownhost_get(LIBSSH2_KNOWNHOSTS *hosts,
+                      struct libssh2_knownhost **store,
+                      struct libssh2_knownhost *prev);
+
+#define HAVE_LIBSSH2_AGENT_API 0x010202 /* since 1.2.2 */
+
+struct libssh2_agent_publickey {
+    unsigned int magic;              /* magic stored by the library */
+    void *node;     /* handle to the internal representation of key */
+    unsigned char *blob;           /* public key blob */
+    size_t blob_len;               /* length of the public key blob */
+    char *comment;                 /* comment in printable format */
+};
+
+/*
+ * libssh2_agent_init
+ *
+ * Init an ssh-agent handle. Returns the pointer to the handle.
+ *
+ */
+LIBSSH2_API LIBSSH2_AGENT *
+libssh2_agent_init(LIBSSH2_SESSION *session);
+
+/*
+ * libssh2_agent_connect()
+ *
+ * Connect to an ssh-agent.
+ *
+ * Returns 0 if succeeded, or a negative value for error.
+ */
+LIBSSH2_API int
+libssh2_agent_connect(LIBSSH2_AGENT *agent);
+
+/*
+ * libssh2_agent_list_identities()
+ *
+ * Request an ssh-agent to list identities.
+ *
+ * Returns 0 if succeeded, or a negative value for error.
+ */
+LIBSSH2_API int
+libssh2_agent_list_identities(LIBSSH2_AGENT *agent);
+
+/*
+ * libssh2_agent_get_identity()
+ *
+ * Traverse the internal list of public keys. Pass NULL to 'prev' to get
+ * the first one. Or pass a poiner to the previously returned one to get the
+ * next.
+ *
+ * Returns:
+ * 0 if a fine public key was stored in 'store'
+ * 1 if end of public keys
+ * [negative] on errors
+ */
+LIBSSH2_API int
+libssh2_agent_get_identity(LIBSSH2_AGENT *agent,
+               struct libssh2_agent_publickey **store,
+               struct libssh2_agent_publickey *prev);
+
+/*
+ * libssh2_agent_userauth()
+ *
+ * Do publickey user authentication with the help of ssh-agent.
+ *
+ * Returns 0 if succeeded, or a negative value for error.
+ */
+LIBSSH2_API int
+libssh2_agent_userauth(LIBSSH2_AGENT *agent,
+               const char *username,
+               struct libssh2_agent_publickey *identity);
+
+/*
+ * libssh2_agent_disconnect()
+ *
+ * Close a connection to an ssh-agent.
+ *
+ * Returns 0 if succeeded, or a negative value for error.
+ */
+LIBSSH2_API int
+libssh2_agent_disconnect(LIBSSH2_AGENT *agent);
+
+/*
+ * libssh2_agent_free()
+ *
+ * Free an ssh-agent handle.  This function also frees the internal
+ * collection of public keys.
+ */
+LIBSSH2_API void
+libssh2_agent_free(LIBSSH2_AGENT *agent);
+
+/*
+ * libssh2_agent_set_identity_path()
+ *
+ * Allows a custom agent identity socket path beyond SSH_AUTH_SOCK env
+ *
+ */
+LIBSSH2_API void
+libssh2_agent_set_identity_path(LIBSSH2_AGENT *agent,
+                                const char *path);
+
+/*
+ * libssh2_agent_get_identity_path()
+ *
+ * Returns the custom agent identity socket path if set
+ *
+ */
+LIBSSH2_API const char *
+libssh2_agent_get_identity_path(LIBSSH2_AGENT *agent);
+
+/*
+ * libssh2_keepalive_config()
+ *
+ * Set how often keepalive messages should be sent.  WANT_REPLY
+ * indicates whether the keepalive messages should request a response
+ * from the server.  INTERVAL is number of seconds that can pass
+ * without any I/O, use 0 (the default) to disable keepalives.  To
+ * avoid some busy-loop corner-cases, if you specify an interval of 1
+ * it will be treated as 2.
+ *
+ * Note that non-blocking applications are responsible for sending the
+ * keepalive messages using libssh2_keepalive_send().
+ */
+LIBSSH2_API void libssh2_keepalive_config(LIBSSH2_SESSION *session,
+                                          int want_reply,
+                                          unsigned interval);
+
+/*
+ * libssh2_keepalive_send()
+ *
+ * Send a keepalive message if needed.  SECONDS_TO_NEXT indicates how
+ * many seconds you can sleep after this call before you need to call
+ * it again.  Returns 0 on success, or LIBSSH2_ERROR_SOCKET_SEND on
+ * I/O errors.
+ */
+LIBSSH2_API int libssh2_keepalive_send(LIBSSH2_SESSION *session,
+                                       int *seconds_to_next);
+
+/* NOTE NOTE NOTE
+   libssh2_trace() has no function in builds that aren't built with debug
+   enabled
+ */
+LIBSSH2_API int libssh2_trace(LIBSSH2_SESSION *session, int bitmask);
+#define LIBSSH2_TRACE_TRANS (1<<1)
+#define LIBSSH2_TRACE_KEX   (1<<2)
+#define LIBSSH2_TRACE_AUTH  (1<<3)
+#define LIBSSH2_TRACE_CONN  (1<<4)
+#define LIBSSH2_TRACE_SCP   (1<<5)
+#define LIBSSH2_TRACE_SFTP  (1<<6)
+#define LIBSSH2_TRACE_ERROR (1<<7)
+#define LIBSSH2_TRACE_PUBLICKEY (1<<8)
+#define LIBSSH2_TRACE_SOCKET (1<<9)
+
+typedef void (*libssh2_trace_handler_func)(LIBSSH2_SESSION*,
+                                           void *,
+                                           const char *,
+                                           size_t);
+LIBSSH2_API int libssh2_trace_sethandler(LIBSSH2_SESSION *session,
+                                         void *context,
+                                         libssh2_trace_handler_func callback);
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
+#endif /* !RC_INVOKED */
+
+#endif /* LIBSSH2_H */

+ 47 - 0
libssh2/libssh2/include/libssh2_config.h

@@ -0,0 +1,47 @@
+#ifndef LIBSSH2_CONFIG_H
+#define LIBSSH2_CONFIG_H
+
+#ifndef WIN32
+#define WIN32
+#endif
+#ifndef _CRT_SECURE_NO_DEPRECATE
+#define _CRT_SECURE_NO_DEPRECATE 1
+#endif /* _CRT_SECURE_NO_DEPRECATE */
+#include <winsock2.h>
+#include <mswsock.h>
+#include <ws2tcpip.h>
+
+#ifdef __MINGW32__
+#define HAVE_UNISTD_H
+#define HAVE_INTTYPES_H
+#define HAVE_SYS_TIME_H
+#define HAVE_GETTIMEOFDAY
+#endif /* __MINGW32__ */
+
+#define HAVE_LIBCRYPT32
+#define HAVE_WINSOCK2_H
+#define HAVE_IOCTLSOCKET
+#define HAVE_SELECT
+
+#ifdef _MSC_VER
+#if _MSC_VER < 1900
+#define snprintf _snprintf
+#if _MSC_VER < 1500
+#define vsnprintf _vsnprintf
+#endif
+#define strdup _strdup
+#define strncasecmp _strnicmp
+#define strcasecmp _stricmp
+#endif
+#else
+#ifndef __MINGW32__
+#define strncasecmp strnicmp
+#define strcasecmp stricmp
+#endif /* __MINGW32__ */
+#endif /* _MSC_VER */
+
+/* Enable newer diffie-hellman-group-exchange-sha1 syntax */
+#define LIBSSH2_DH_GEX_NEW 1
+
+#endif /* LIBSSH2_CONFIG_H */
+

+ 122 - 0
libssh2/libssh2/include/libssh2_publickey.h

@@ -0,0 +1,122 @@
+/* Copyright (c) 2004-2006, Sara Golemon <sarag@libssh2.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms,
+ * with or without modification, are permitted provided
+ * that the following conditions are met:
+ *
+ *   Redistributions of source code must retain the above
+ *   copyright notice, this list of conditions and the
+ *   following disclaimer.
+ *
+ *   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.
+ *
+ *   Neither the name of the copyright holder nor the names
+ *   of any other contributors may be used to endorse or
+ *   promote products derived from this software without
+ *   specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+ * CONTRIBUTORS "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 COPYRIGHT OWNER OR
+ * CONTRIBUTORS 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.
+ */
+
+/* Note: This include file is only needed for using the
+ * publickey SUBSYSTEM which is not the same as publickey
+ * authentication.  For authentication you only need libssh2.h
+ *
+ * For more information on the publickey subsystem,
+ * refer to IETF draft: secsh-publickey
+ */
+
+#ifndef LIBSSH2_PUBLICKEY_H
+#define LIBSSH2_PUBLICKEY_H 1
+
+#include "libssh2.h"
+
+typedef struct _LIBSSH2_PUBLICKEY               LIBSSH2_PUBLICKEY;
+
+typedef struct _libssh2_publickey_attribute {
+    const char *name;
+    unsigned long name_len;
+    const char *value;
+    unsigned long value_len;
+    char mandatory;
+} libssh2_publickey_attribute;
+
+typedef struct _libssh2_publickey_list {
+    unsigned char *packet; /* For freeing */
+
+    const unsigned char *name;
+    unsigned long name_len;
+    const unsigned char *blob;
+    unsigned long blob_len;
+    unsigned long num_attrs;
+    libssh2_publickey_attribute *attrs; /* free me */
+} libssh2_publickey_list;
+
+/* Generally use the first macro here, but if both name and value are string
+   literals, you can use _fast() to take advantage of preprocessing */
+#define libssh2_publickey_attribute(name, value, mandatory) \
+  { (name), strlen(name), (value), strlen(value), (mandatory) },
+#define libssh2_publickey_attribute_fast(name, value, mandatory) \
+  { (name), sizeof(name) - 1, (value), sizeof(value) - 1, (mandatory) },
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Publickey Subsystem */
+LIBSSH2_API LIBSSH2_PUBLICKEY *
+libssh2_publickey_init(LIBSSH2_SESSION *session);
+
+LIBSSH2_API int
+libssh2_publickey_add_ex(LIBSSH2_PUBLICKEY *pkey,
+                         const unsigned char *name,
+                         unsigned long name_len,
+                         const unsigned char *blob,
+                         unsigned long blob_len, char overwrite,
+                         unsigned long num_attrs,
+                         const libssh2_publickey_attribute attrs[]);
+#define libssh2_publickey_add(pkey, name, blob, blob_len, overwrite,    \
+                              num_attrs, attrs)                         \
+  libssh2_publickey_add_ex((pkey), (name), strlen(name), (blob), (blob_len), \
+                           (overwrite), (num_attrs), (attrs))
+
+LIBSSH2_API int libssh2_publickey_remove_ex(LIBSSH2_PUBLICKEY *pkey,
+                                            const unsigned char *name,
+                                            unsigned long name_len,
+                                            const unsigned char *blob,
+                                            unsigned long blob_len);
+#define libssh2_publickey_remove(pkey, name, blob, blob_len) \
+  libssh2_publickey_remove_ex((pkey), (name), strlen(name), (blob), (blob_len))
+
+LIBSSH2_API int
+libssh2_publickey_list_fetch(LIBSSH2_PUBLICKEY *pkey,
+                             unsigned long *num_keys,
+                             libssh2_publickey_list **pkey_list);
+LIBSSH2_API void
+libssh2_publickey_list_free(LIBSSH2_PUBLICKEY *pkey,
+                            libssh2_publickey_list *pkey_list);
+
+LIBSSH2_API int libssh2_publickey_shutdown(LIBSSH2_PUBLICKEY *pkey);
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
+#endif /* ifndef: LIBSSH2_PUBLICKEY_H */

+ 351 - 0
libssh2/libssh2/include/libssh2_sftp.h

@@ -0,0 +1,351 @@
+/* Copyright (c) 2004-2008, Sara Golemon <sarag@libssh2.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms,
+ * with or without modification, are permitted provided
+ * that the following conditions are met:
+ *
+ *   Redistributions of source code must retain the above
+ *   copyright notice, this list of conditions and the
+ *   following disclaimer.
+ *
+ *   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.
+ *
+ *   Neither the name of the copyright holder nor the names
+ *   of any other contributors may be used to endorse or
+ *   promote products derived from this software without
+ *   specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+ * CONTRIBUTORS "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 COPYRIGHT OWNER OR
+ * CONTRIBUTORS 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 LIBSSH2_SFTP_H
+#define LIBSSH2_SFTP_H 1
+
+#include "libssh2.h"
+
+#ifndef WIN32
+#include <unistd.h>
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Note: Version 6 was documented at the time of writing
+ * However it was marked as "DO NOT IMPLEMENT" due to pending changes
+ *
+ * Let's start with Version 3 (The version found in OpenSSH) and go from there
+ */
+#define LIBSSH2_SFTP_VERSION        3
+
+typedef struct _LIBSSH2_SFTP                LIBSSH2_SFTP;
+typedef struct _LIBSSH2_SFTP_HANDLE         LIBSSH2_SFTP_HANDLE;
+typedef struct _LIBSSH2_SFTP_ATTRIBUTES     LIBSSH2_SFTP_ATTRIBUTES;
+typedef struct _LIBSSH2_SFTP_STATVFS        LIBSSH2_SFTP_STATVFS;
+
+/* Flags for open_ex() */
+#define LIBSSH2_SFTP_OPENFILE           0
+#define LIBSSH2_SFTP_OPENDIR            1
+
+/* Flags for rename_ex() */
+#define LIBSSH2_SFTP_RENAME_OVERWRITE   0x00000001
+#define LIBSSH2_SFTP_RENAME_ATOMIC      0x00000002
+#define LIBSSH2_SFTP_RENAME_NATIVE      0x00000004
+
+/* Flags for stat_ex() */
+#define LIBSSH2_SFTP_STAT               0
+#define LIBSSH2_SFTP_LSTAT              1
+#define LIBSSH2_SFTP_SETSTAT            2
+
+/* Flags for symlink_ex() */
+#define LIBSSH2_SFTP_SYMLINK            0
+#define LIBSSH2_SFTP_READLINK           1
+#define LIBSSH2_SFTP_REALPATH           2
+
+/* Flags for sftp_mkdir() */
+#define LIBSSH2_SFTP_DEFAULT_MODE      -1
+
+/* SFTP attribute flag bits */
+#define LIBSSH2_SFTP_ATTR_SIZE              0x00000001
+#define LIBSSH2_SFTP_ATTR_UIDGID            0x00000002
+#define LIBSSH2_SFTP_ATTR_PERMISSIONS       0x00000004
+#define LIBSSH2_SFTP_ATTR_ACMODTIME         0x00000008
+#define LIBSSH2_SFTP_ATTR_EXTENDED          0x80000000
+
+/* SFTP statvfs flag bits */
+#define LIBSSH2_SFTP_ST_RDONLY              0x00000001
+#define LIBSSH2_SFTP_ST_NOSUID              0x00000002
+
+struct _LIBSSH2_SFTP_ATTRIBUTES {
+    /* If flags & ATTR_* bit is set, then the value in this struct will be
+     * meaningful Otherwise it should be ignored
+     */
+    unsigned long flags;
+
+    libssh2_uint64_t filesize;
+    unsigned long uid, gid;
+    unsigned long permissions;
+    unsigned long atime, mtime;
+};
+
+struct _LIBSSH2_SFTP_STATVFS {
+    libssh2_uint64_t  f_bsize;    /* file system block size */
+    libssh2_uint64_t  f_frsize;   /* fragment size */
+    libssh2_uint64_t  f_blocks;   /* size of fs in f_frsize units */
+    libssh2_uint64_t  f_bfree;    /* # free blocks */
+    libssh2_uint64_t  f_bavail;   /* # free blocks for non-root */
+    libssh2_uint64_t  f_files;    /* # inodes */
+    libssh2_uint64_t  f_ffree;    /* # free inodes */
+    libssh2_uint64_t  f_favail;   /* # free inodes for non-root */
+    libssh2_uint64_t  f_fsid;     /* file system ID */
+    libssh2_uint64_t  f_flag;     /* mount flags */
+    libssh2_uint64_t  f_namemax;  /* maximum filename length */
+};
+
+/* SFTP filetypes */
+#define LIBSSH2_SFTP_TYPE_REGULAR           1
+#define LIBSSH2_SFTP_TYPE_DIRECTORY         2
+#define LIBSSH2_SFTP_TYPE_SYMLINK           3
+#define LIBSSH2_SFTP_TYPE_SPECIAL           4
+#define LIBSSH2_SFTP_TYPE_UNKNOWN           5
+#define LIBSSH2_SFTP_TYPE_SOCKET            6
+#define LIBSSH2_SFTP_TYPE_CHAR_DEVICE       7
+#define LIBSSH2_SFTP_TYPE_BLOCK_DEVICE      8
+#define LIBSSH2_SFTP_TYPE_FIFO              9
+
+/*
+ * Reproduce the POSIX file modes here for systems that are not POSIX
+ * compliant.
+ *
+ * These is used in "permissions" of "struct _LIBSSH2_SFTP_ATTRIBUTES"
+ */
+/* File type */
+#define LIBSSH2_SFTP_S_IFMT         0170000     /* type of file mask */
+#define LIBSSH2_SFTP_S_IFIFO        0010000     /* named pipe (fifo) */
+#define LIBSSH2_SFTP_S_IFCHR        0020000     /* character special */
+#define LIBSSH2_SFTP_S_IFDIR        0040000     /* directory */
+#define LIBSSH2_SFTP_S_IFBLK        0060000     /* block special */
+#define LIBSSH2_SFTP_S_IFREG        0100000     /* regular */
+#define LIBSSH2_SFTP_S_IFLNK        0120000     /* symbolic link */
+#define LIBSSH2_SFTP_S_IFSOCK       0140000     /* socket */
+
+/* File mode */
+/* Read, write, execute/search by owner */
+#define LIBSSH2_SFTP_S_IRWXU        0000700     /* RWX mask for owner */
+#define LIBSSH2_SFTP_S_IRUSR        0000400     /* R for owner */
+#define LIBSSH2_SFTP_S_IWUSR        0000200     /* W for owner */
+#define LIBSSH2_SFTP_S_IXUSR        0000100     /* X for owner */
+/* Read, write, execute/search by group */
+#define LIBSSH2_SFTP_S_IRWXG        0000070     /* RWX mask for group */
+#define LIBSSH2_SFTP_S_IRGRP        0000040     /* R for group */
+#define LIBSSH2_SFTP_S_IWGRP        0000020     /* W for group */
+#define LIBSSH2_SFTP_S_IXGRP        0000010     /* X for group */
+/* Read, write, execute/search by others */
+#define LIBSSH2_SFTP_S_IRWXO        0000007     /* RWX mask for other */
+#define LIBSSH2_SFTP_S_IROTH        0000004     /* R for other */
+#define LIBSSH2_SFTP_S_IWOTH        0000002     /* W for other */
+#define LIBSSH2_SFTP_S_IXOTH        0000001     /* X for other */
+
+/* macros to check for specific file types, added in 1.2.5 */
+#define LIBSSH2_SFTP_S_ISLNK(m) \
+  (((m) & LIBSSH2_SFTP_S_IFMT) == LIBSSH2_SFTP_S_IFLNK)
+#define LIBSSH2_SFTP_S_ISREG(m) \
+  (((m) & LIBSSH2_SFTP_S_IFMT) == LIBSSH2_SFTP_S_IFREG)
+#define LIBSSH2_SFTP_S_ISDIR(m) \
+  (((m) & LIBSSH2_SFTP_S_IFMT) == LIBSSH2_SFTP_S_IFDIR)
+#define LIBSSH2_SFTP_S_ISCHR(m) \
+  (((m) & LIBSSH2_SFTP_S_IFMT) == LIBSSH2_SFTP_S_IFCHR)
+#define LIBSSH2_SFTP_S_ISBLK(m) \
+  (((m) & LIBSSH2_SFTP_S_IFMT) == LIBSSH2_SFTP_S_IFBLK)
+#define LIBSSH2_SFTP_S_ISFIFO(m) \
+  (((m) & LIBSSH2_SFTP_S_IFMT) == LIBSSH2_SFTP_S_IFIFO)
+#define LIBSSH2_SFTP_S_ISSOCK(m) \
+  (((m) & LIBSSH2_SFTP_S_IFMT) == LIBSSH2_SFTP_S_IFSOCK)
+
+/* SFTP File Transfer Flags -- (e.g. flags parameter to sftp_open())
+ * Danger will robinson... APPEND doesn't have any effect on OpenSSH servers */
+#define LIBSSH2_FXF_READ                        0x00000001
+#define LIBSSH2_FXF_WRITE                       0x00000002
+#define LIBSSH2_FXF_APPEND                      0x00000004
+#define LIBSSH2_FXF_CREAT                       0x00000008
+#define LIBSSH2_FXF_TRUNC                       0x00000010
+#define LIBSSH2_FXF_EXCL                        0x00000020
+
+/* SFTP Status Codes (returned by libssh2_sftp_last_error() ) */
+#define LIBSSH2_FX_OK                       0
+#define LIBSSH2_FX_EOF                      1
+#define LIBSSH2_FX_NO_SUCH_FILE             2
+#define LIBSSH2_FX_PERMISSION_DENIED        3
+#define LIBSSH2_FX_FAILURE                  4
+#define LIBSSH2_FX_BAD_MESSAGE              5
+#define LIBSSH2_FX_NO_CONNECTION            6
+#define LIBSSH2_FX_CONNECTION_LOST          7
+#define LIBSSH2_FX_OP_UNSUPPORTED           8
+#define LIBSSH2_FX_INVALID_HANDLE           9
+#define LIBSSH2_FX_NO_SUCH_PATH             10
+#define LIBSSH2_FX_FILE_ALREADY_EXISTS      11
+#define LIBSSH2_FX_WRITE_PROTECT            12
+#define LIBSSH2_FX_NO_MEDIA                 13
+#define LIBSSH2_FX_NO_SPACE_ON_FILESYSTEM   14
+#define LIBSSH2_FX_QUOTA_EXCEEDED           15
+#define LIBSSH2_FX_UNKNOWN_PRINCIPLE        16 /* Initial mis-spelling */
+#define LIBSSH2_FX_UNKNOWN_PRINCIPAL        16
+#define LIBSSH2_FX_LOCK_CONFlICT            17 /* Initial mis-spelling */
+#define LIBSSH2_FX_LOCK_CONFLICT            17
+#define LIBSSH2_FX_DIR_NOT_EMPTY            18
+#define LIBSSH2_FX_NOT_A_DIRECTORY          19
+#define LIBSSH2_FX_INVALID_FILENAME         20
+#define LIBSSH2_FX_LINK_LOOP                21
+
+/* Returned by any function that would block during a read/write opperation */
+#define LIBSSH2SFTP_EAGAIN LIBSSH2_ERROR_EAGAIN
+
+/* SFTP API */
+LIBSSH2_API LIBSSH2_SFTP *libssh2_sftp_init(LIBSSH2_SESSION *session);
+LIBSSH2_API int libssh2_sftp_shutdown(LIBSSH2_SFTP *sftp);
+LIBSSH2_API unsigned long libssh2_sftp_last_error(LIBSSH2_SFTP *sftp);
+LIBSSH2_API LIBSSH2_CHANNEL *libssh2_sftp_get_channel(LIBSSH2_SFTP *sftp);
+
+/* File / Directory Ops */
+LIBSSH2_API LIBSSH2_SFTP_HANDLE *
+libssh2_sftp_open_ex(LIBSSH2_SFTP *sftp,
+                     const char *filename,
+                     unsigned int filename_len,
+                     unsigned long flags,
+                     long mode, int open_type);
+#define libssh2_sftp_open(sftp, filename, flags, mode)                  \
+    libssh2_sftp_open_ex((sftp), (filename), strlen(filename), (flags), \
+                         (mode), LIBSSH2_SFTP_OPENFILE)
+#define libssh2_sftp_opendir(sftp, path) \
+    libssh2_sftp_open_ex((sftp), (path), strlen(path), 0, 0, \
+                         LIBSSH2_SFTP_OPENDIR)
+
+LIBSSH2_API ssize_t libssh2_sftp_read(LIBSSH2_SFTP_HANDLE *handle,
+                                      char *buffer, size_t buffer_maxlen);
+
+LIBSSH2_API int libssh2_sftp_readdir_ex(LIBSSH2_SFTP_HANDLE *handle, \
+                                        char *buffer, size_t buffer_maxlen,
+                                        char *longentry,
+                                        size_t longentry_maxlen,
+                                        LIBSSH2_SFTP_ATTRIBUTES *attrs);
+#define libssh2_sftp_readdir(handle, buffer, buffer_maxlen, attrs)      \
+    libssh2_sftp_readdir_ex((handle), (buffer), (buffer_maxlen), NULL, 0, \
+                            (attrs))
+
+LIBSSH2_API ssize_t libssh2_sftp_write(LIBSSH2_SFTP_HANDLE *handle,
+                                       const char *buffer, size_t count);
+LIBSSH2_API int libssh2_sftp_fsync(LIBSSH2_SFTP_HANDLE *handle);
+
+LIBSSH2_API int libssh2_sftp_close_handle(LIBSSH2_SFTP_HANDLE *handle);
+#define libssh2_sftp_close(handle) libssh2_sftp_close_handle(handle)
+#define libssh2_sftp_closedir(handle) libssh2_sftp_close_handle(handle)
+
+LIBSSH2_API void libssh2_sftp_seek(LIBSSH2_SFTP_HANDLE *handle, size_t offset);
+LIBSSH2_API void libssh2_sftp_seek64(LIBSSH2_SFTP_HANDLE *handle,
+                                     libssh2_uint64_t offset);
+#define libssh2_sftp_rewind(handle) libssh2_sftp_seek64((handle), 0)
+
+LIBSSH2_API size_t libssh2_sftp_tell(LIBSSH2_SFTP_HANDLE *handle);
+LIBSSH2_API libssh2_uint64_t libssh2_sftp_tell64(LIBSSH2_SFTP_HANDLE *handle);
+
+LIBSSH2_API int libssh2_sftp_fstat_ex(LIBSSH2_SFTP_HANDLE *handle,
+                                      LIBSSH2_SFTP_ATTRIBUTES *attrs,
+                                      int setstat);
+#define libssh2_sftp_fstat(handle, attrs) \
+    libssh2_sftp_fstat_ex((handle), (attrs), 0)
+#define libssh2_sftp_fsetstat(handle, attrs) \
+    libssh2_sftp_fstat_ex((handle), (attrs), 1)
+
+/* Miscellaneous Ops */
+LIBSSH2_API int libssh2_sftp_rename_ex(LIBSSH2_SFTP *sftp,
+                                       const char *source_filename,
+                                       unsigned int srouce_filename_len,
+                                       const char *dest_filename,
+                                       unsigned int dest_filename_len,
+                                       long flags);
+#define libssh2_sftp_rename(sftp, sourcefile, destfile) \
+    libssh2_sftp_rename_ex((sftp), (sourcefile), strlen(sourcefile), \
+                           (destfile), strlen(destfile),                \
+                           LIBSSH2_SFTP_RENAME_OVERWRITE | \
+                           LIBSSH2_SFTP_RENAME_ATOMIC | \
+                           LIBSSH2_SFTP_RENAME_NATIVE)
+
+LIBSSH2_API int libssh2_sftp_unlink_ex(LIBSSH2_SFTP *sftp,
+                                       const char *filename,
+                                       unsigned int filename_len);
+#define libssh2_sftp_unlink(sftp, filename) \
+    libssh2_sftp_unlink_ex((sftp), (filename), strlen(filename))
+
+LIBSSH2_API int libssh2_sftp_fstatvfs(LIBSSH2_SFTP_HANDLE *handle,
+                                      LIBSSH2_SFTP_STATVFS *st);
+
+LIBSSH2_API int libssh2_sftp_statvfs(LIBSSH2_SFTP *sftp,
+                                     const char *path,
+                                     size_t path_len,
+                                     LIBSSH2_SFTP_STATVFS *st);
+
+LIBSSH2_API int libssh2_sftp_mkdir_ex(LIBSSH2_SFTP *sftp,
+                                      const char *path,
+                                      unsigned int path_len, long mode);
+#define libssh2_sftp_mkdir(sftp, path, mode) \
+    libssh2_sftp_mkdir_ex((sftp), (path), strlen(path), (mode))
+
+LIBSSH2_API int libssh2_sftp_rmdir_ex(LIBSSH2_SFTP *sftp,
+                                      const char *path,
+                                      unsigned int path_len);
+#define libssh2_sftp_rmdir(sftp, path) \
+    libssh2_sftp_rmdir_ex((sftp), (path), strlen(path))
+
+LIBSSH2_API int libssh2_sftp_stat_ex(LIBSSH2_SFTP *sftp,
+                                     const char *path,
+                                     unsigned int path_len,
+                                     int stat_type,
+                                     LIBSSH2_SFTP_ATTRIBUTES *attrs);
+#define libssh2_sftp_stat(sftp, path, attrs) \
+    libssh2_sftp_stat_ex((sftp), (path), strlen(path), LIBSSH2_SFTP_STAT, \
+                         (attrs))
+#define libssh2_sftp_lstat(sftp, path, attrs) \
+    libssh2_sftp_stat_ex((sftp), (path), strlen(path), LIBSSH2_SFTP_LSTAT, \
+                         (attrs))
+#define libssh2_sftp_setstat(sftp, path, attrs) \
+    libssh2_sftp_stat_ex((sftp), (path), strlen(path), LIBSSH2_SFTP_SETSTAT, \
+                         (attrs))
+
+LIBSSH2_API int libssh2_sftp_symlink_ex(LIBSSH2_SFTP *sftp,
+                                        const char *path,
+                                        unsigned int path_len,
+                                        char *target,
+                                        unsigned int target_len,
+                                        int link_type);
+#define libssh2_sftp_symlink(sftp, orig, linkpath) \
+    libssh2_sftp_symlink_ex((sftp), (orig), strlen(orig), (linkpath), \
+                            strlen(linkpath), LIBSSH2_SFTP_SYMLINK)
+#define libssh2_sftp_readlink(sftp, path, target, maxlen) \
+    libssh2_sftp_symlink_ex((sftp), (path), strlen(path), (target), (maxlen), \
+    LIBSSH2_SFTP_READLINK)
+#define libssh2_sftp_realpath(sftp, path, target, maxlen) \
+    libssh2_sftp_symlink_ex((sftp), (path), strlen(path), (target), (maxlen), \
+                            LIBSSH2_SFTP_REALPATH)
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
+#endif /* LIBSSH2_SFTP_H */

+ 45 - 0
libssh2/libssh2/libssh2.rc

@@ -0,0 +1,45 @@
+/***************************************************************************
+* libssh2 Win32 resource file                                              *
+***************************************************************************/
+#include <winver.h>
+#include "include/libssh2.h"
+
+LANGUAGE  0x09,0x01
+
+#define RC_VERSION  LIBSSH2_VERSION_MAJOR, LIBSSH2_VERSION_MINOR, LIBSSH2_VERSION_PATCH, 0
+
+VS_VERSION_INFO VERSIONINFO
+  FILEVERSION     RC_VERSION
+  PRODUCTVERSION  RC_VERSION
+  FILEFLAGSMASK   0x3fL
+#if defined(DEBUGBUILD) || defined(_DEBUG)
+  FILEFLAGS 1
+#else
+  FILEFLAGS 0
+#endif
+  FILEOS      VOS__WINDOWS32
+  FILETYPE    VFT_DLL
+  FILESUBTYPE 0x0L
+
+BEGIN
+  BLOCK "StringFileInfo"
+  BEGIN
+    BLOCK "040904b0"
+    BEGIN
+      VALUE "CompanyName",      "The libssh2 library, https://www.libssh2.org/\0"
+      VALUE "FileDescription",  "libssh2 Shared Library\0"
+      VALUE "FileVersion",      LIBSSH2_VERSION "\0"
+      VALUE "InternalName",     "libssh2\0"
+      VALUE "OriginalFilename", "libssh2.dll\0"
+      VALUE "ProductName",      "The libssh2 library\0"
+      VALUE "ProductVersion",   LIBSSH2_VERSION "\0"
+      VALUE "LegalCopyright",   "?" LIBSSH2_COPYRIGHT "\0"
+      VALUE "License",          "https://www.libssh2.org/license.html\0"
+    END
+  END
+
+  BLOCK "VarFileInfo"
+  BEGIN
+    VALUE "Translation", 0x409, 1200
+  END
+END

+ 877 - 0
libssh2/libssh2/libssh2.vcproj

@@ -0,0 +1,877 @@
+<?xml version="1.0" encoding="gb2312"?>
+<VisualStudioProject
+	ProjectType="Visual C++"
+	Version="9.00"
+	Name="libssh2"
+	ProjectGUID="{656EF6DD-759A-41F2-BB76-2107C27C910E}"
+	RootNamespace="libssh2"
+	TargetFrameworkVersion="0"
+	>
+	<Platforms>
+		<Platform
+			Name="Win32"
+		/>
+	</Platforms>
+	<ToolFiles>
+	</ToolFiles>
+	<Configurations>
+		<Configuration
+			Name="WinCNG LIB Debug|Win32"
+			OutputDirectory=".\Debug_lib"
+			IntermediateDirectory=".\Debug_lib"
+			ConfigurationType="4"
+			InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC60.vsprops"
+			UseOfMFC="0"
+			ATLMinimizesCRunTimeLibraryUsage="false"
+			CharacterSet="2"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="..\win32,..\include"
+				PreprocessorDefinitions="WIN32;NDEBUG;LIBSSH2_WIN32;LIBSSH2_WINCNG;_LIB;_DEBUG;LIBSSH2DEBUG"
+				MinimalRebuild="true"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="2"
+				PrecompiledHeaderFile=".\Debug_lib/libssh2.pch"
+				AssemblerListingLocation=".\Debug_lib/"
+				ObjectFile=".\Debug_lib/"
+				ProgramDataBaseFileName=".\Debug_lib/"
+				WarningLevel="3"
+				SuppressStartupBanner="true"
+				DebugInformationFormat="4"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="NDEBUG,_DEBUG"
+				Culture="1033"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLibrarianTool"
+				OutputFile="Debug_lib\libssh2d.lib"
+				SuppressStartupBanner="true"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+				SuppressStartupBanner="true"
+				OutputFile=".\Debug_lib/libssh2.bsc"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+		</Configuration>
+		<Configuration
+			Name="WinCNG DLL Debug|Win32"
+			OutputDirectory=".\Debug_dll"
+			IntermediateDirectory=".\Debug_dll"
+			ConfigurationType="2"
+			InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC60.vsprops"
+			UseOfMFC="0"
+			ATLMinimizesCRunTimeLibraryUsage="false"
+			CharacterSet="2"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+				PreprocessorDefinitions="_DEBUG"
+				MkTypLibCompatible="true"
+				SuppressStartupBanner="true"
+				TargetEnvironment="1"
+				TypeLibraryName=".\Debug_dll/libssh2.tlb"
+				HeaderFileName=""
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="..\win32,..\include"
+				PreprocessorDefinitions="WIN32;_DEBUG;LIBSSH2_WIN32;LIBSSH2_WINCNG;_LIB;LIBSSH2DEBUG"
+				MinimalRebuild="true"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="2"
+				PrecompiledHeaderFile=".\Debug_dll/libssh2.pch"
+				AssemblerListingLocation=".\Debug_dll/"
+				ObjectFile=".\Debug_dll/"
+				ProgramDataBaseFileName=".\Debug_dll/"
+				WarningLevel="3"
+				SuppressStartupBanner="true"
+				DebugInformationFormat="4"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="_DEBUG"
+				Culture="1033"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="ws2_32.lib crypt32.lib bcrypt.lib"
+				OutputFile=".\Debug_dll/libssh2.dll"
+				LinkIncremental="1"
+				SuppressStartupBanner="true"
+				GenerateDebugInformation="true"
+				ProgramDatabaseFile=".\Debug_dll/libssh2.pdb"
+				GenerateMapFile="true"
+				MapFileName=".\Debug_dll/libssh2.map"
+				RandomizedBaseAddress="1"
+				DataExecutionPrevention="0"
+				ImportLibrary=".\Debug_dll/libssh2.lib"
+				TargetMachine="1"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCManifestTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+				SuppressStartupBanner="true"
+				OutputFile=".\Debug_dll/libssh2.bsc"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCAppVerifierTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+		</Configuration>
+		<Configuration
+			Name="WinCNG LIB Release|Win32"
+			OutputDirectory=".\Release_lib"
+			IntermediateDirectory=".\Release_lib"
+			ConfigurationType="4"
+			InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC60.vsprops"
+			UseOfMFC="0"
+			ATLMinimizesCRunTimeLibraryUsage="false"
+			CharacterSet="2"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="2"
+				InlineFunctionExpansion="1"
+				AdditionalIncludeDirectories="..\win32,..\include"
+				PreprocessorDefinitions="WIN32;NDEBUG;LIBSSH2_WIN32;LIBSSH2_WINCNG;_LIB"
+				StringPooling="true"
+				RuntimeLibrary="2"
+				EnableFunctionLevelLinking="true"
+				PrecompiledHeaderFile=".\Release_lib/libssh2.pch"
+				AssemblerListingLocation=".\Release_lib/"
+				ObjectFile=".\Release_lib/"
+				ProgramDataBaseFileName=".\Release_lib/"
+				WarningLevel="3"
+				SuppressStartupBanner="true"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="NDEBUG"
+				Culture="1033"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLibrarianTool"
+				OutputFile="Release_lib\libssh2.lib"
+				SuppressStartupBanner="true"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+				SuppressStartupBanner="true"
+				OutputFile=".\Release_lib/libssh2.bsc"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+		</Configuration>
+		<Configuration
+			Name="OpenSSL LIB Release|Win32"
+			OutputDirectory="..\..\bin\$(SolutionName)"
+			IntermediateDirectory="$(OutDir)\$(ProjectName)\$(ConfigurationName)"
+			ConfigurationType="4"
+			InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC60.vsprops"
+			UseOfMFC="0"
+			ATLMinimizesCRunTimeLibraryUsage="false"
+			CharacterSet="2"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="2"
+				InlineFunctionExpansion="1"
+				AdditionalIncludeDirectories="include;..\openssl\include;..\zlib\include"
+				PreprocessorDefinitions="WIN32;NDEBUG;LIBSSH2_WIN32;LIBSSH2_OPENSSL;_LIB"
+				StringPooling="true"
+				RuntimeLibrary="2"
+				EnableFunctionLevelLinking="true"
+				PrecompiledHeaderFile=".\Release_lib/libssh2.pch"
+				AssemblerListingLocation=".\Release_lib/"
+				ObjectFile=".\Release_lib/"
+				ProgramDataBaseFileName=".\Release_lib/"
+				WarningLevel="3"
+				SuppressStartupBanner="true"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="NDEBUG"
+				Culture="1033"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLibrarianTool"
+				AdditionalDependencies="ws2_32.lib libeay32.lib zlibwapi.lib"
+				OutputFile="Release_lib\libssh2.lib"
+				AdditionalLibraryDirectories="..\openssl\lib;..\zlib\dll"
+				SuppressStartupBanner="true"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+				SuppressStartupBanner="true"
+				OutputFile=".\Release_lib/libssh2.bsc"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+		</Configuration>
+		<Configuration
+			Name="WinCNG DLL Release|Win32"
+			OutputDirectory="."
+			IntermediateDirectory="."
+			ConfigurationType="1"
+			InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC60.vsprops"
+			ATLMinimizesCRunTimeLibraryUsage="false"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+				TypeLibraryName="./libssh2.tlb"
+				HeaderFileName=""
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				PreprocessorDefinitions="_WINDLL"
+				RuntimeLibrary="0"
+				PrecompiledHeaderFile="./libssh2.pch"
+				AssemblerListingLocation="./"
+				ObjectFile="./"
+				ProgramDataBaseFileName="./"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				Culture="2052"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+				OutputFile="./libssh2.exe"
+				LinkIncremental="1"
+				ProgramDatabaseFile="./libssh2.pdb"
+				RandomizedBaseAddress="1"
+				DataExecutionPrevention="0"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCManifestTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+				OutputFile="./libssh2.bsc"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCAppVerifierTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+		</Configuration>
+		<Configuration
+			Name="OpenSSL LIB Debug|Win32"
+			OutputDirectory="..\..\bin\$(SolutionName)"
+			IntermediateDirectory="$(OutDir)\$(ProjectName)\$(ConfigurationName)"
+			ConfigurationType="4"
+			InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC60.vsprops"
+			UseOfMFC="0"
+			ATLMinimizesCRunTimeLibraryUsage="false"
+			CharacterSet="2"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="include;..\openssl\include;..\zlib\include"
+				PreprocessorDefinitions="WIN32;_DEBUG;LIBSSH2_WIN32;LIBSSH2_OPENSSL;_LIB;LIBSSH2DEBUG"
+				MinimalRebuild="true"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="2"
+				PrecompiledHeaderFile=".\Debug_lib/libssh2.pch"
+				AssemblerListingLocation=".\Debug_lib/"
+				ObjectFile=".\Debug_lib/"
+				ProgramDataBaseFileName=".\Debug_lib/"
+				WarningLevel="3"
+				SuppressStartupBanner="true"
+				DebugInformationFormat="4"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="_DEBUG"
+				Culture="1033"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLibrarianTool"
+				AdditionalDependencies="ws2_32.lib libeay32.lib zlibwapi.lib"
+				OutputFile="Debug_lib\libssh2d.lib"
+				AdditionalLibraryDirectories="..\openssl\lib;..\zlib\dll"
+				SuppressStartupBanner="true"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+				SuppressStartupBanner="true"
+				OutputFile=".\Debug_lib/libssh2.bsc"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+		</Configuration>
+		<Configuration
+			Name="OpenSSL DLL Release|Win32"
+			OutputDirectory="..\..\bin\$(SolutionName)"
+			IntermediateDirectory="$(OutDir)\$(ProjectName)\$(ConfigurationName)"
+			ConfigurationType="2"
+			InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC60.vsprops"
+			UseOfMFC="0"
+			ATLMinimizesCRunTimeLibraryUsage="false"
+			CharacterSet="2"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+				PreprocessorDefinitions="NDEBUG"
+				MkTypLibCompatible="true"
+				SuppressStartupBanner="true"
+				TargetEnvironment="1"
+				TypeLibraryName=".\Release_dll/libssh2.tlb"
+				HeaderFileName=""
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="2"
+				InlineFunctionExpansion="1"
+				AdditionalIncludeDirectories="include;..\openssl\include;..\zlib\include"
+				PreprocessorDefinitions="WIN32;NDEBUG;LIBSSH2_WIN32;LIBSSH2_OPENSSL;_LIB"
+				StringPooling="true"
+				RuntimeLibrary="2"
+				EnableFunctionLevelLinking="true"
+				WarningLevel="3"
+				SuppressStartupBanner="true"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="NDEBUG"
+				Culture="1033"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="ws2_32.lib libeay32.lib zlibwapi.lib"
+				LinkIncremental="1"
+				SuppressStartupBanner="true"
+				AdditionalLibraryDirectories="..\openssl\lib;..\zlib\dll"
+				GenerateDebugInformation="true"
+				GenerateMapFile="true"
+				RandomizedBaseAddress="1"
+				DataExecutionPrevention="0"
+				TargetMachine="1"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCManifestTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+				SuppressStartupBanner="true"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCAppVerifierTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+		</Configuration>
+		<Configuration
+			Name="OpenSSL DLL Debug|Win32"
+			OutputDirectory="..\..\bin\$(SolutionName)"
+			IntermediateDirectory="$(OutDir)\$(ProjectName)\$(ConfigurationName)"
+			ConfigurationType="2"
+			InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC60.vsprops"
+			UseOfMFC="0"
+			ATLMinimizesCRunTimeLibraryUsage="false"
+			CharacterSet="2"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+				PreprocessorDefinitions="_DEBUG"
+				MkTypLibCompatible="true"
+				SuppressStartupBanner="true"
+				TargetEnvironment="1"
+				TypeLibraryName=".\Debug_dll/libssh2.tlb"
+				HeaderFileName=""
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="include;..\openssl\include;..\zlib\include"
+				PreprocessorDefinitions="WIN32;_DEBUG;LIBSSH2_WIN32;LIBSSH2_OPENSSL;_LIB;LIBSSH2DEBUG"
+				MinimalRebuild="true"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="2"
+				WarningLevel="3"
+				SuppressStartupBanner="true"
+				DebugInformationFormat="4"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="_DEBUG"
+				Culture="1033"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="ws2_32.lib libeay32.lib zlibwapi.lib"
+				LinkIncremental="1"
+				SuppressStartupBanner="true"
+				AdditionalLibraryDirectories="..\openssl\lib;..\zlib\dll"
+				GenerateDebugInformation="true"
+				GenerateMapFile="true"
+				RandomizedBaseAddress="1"
+				DataExecutionPrevention="0"
+				TargetMachine="1"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCManifestTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+				SuppressStartupBanner="true"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCAppVerifierTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+		</Configuration>
+	</Configurations>
+	<References>
+	</References>
+	<Files>
+		<Filter
+			Name="Ô´Îļþ"
+			Filter="cpp;c;cxx"
+			>
+			<File
+				RelativePath=".\src\agent.c"
+				>
+			</File>
+			<File
+				RelativePath=".\src\bcrypt_pbkdf.c"
+				>
+			</File>
+			<File
+				RelativePath=".\src\blowfish.c"
+				>
+			</File>
+			<File
+				RelativePath=".\src\channel.c"
+				>
+			</File>
+			<File
+				RelativePath=".\src\comp.c"
+				>
+			</File>
+			<File
+				RelativePath=".\src\crypt.c"
+				>
+			</File>
+			<File
+				RelativePath=".\src\global.c"
+				>
+			</File>
+			<File
+				RelativePath=".\src\hostkey.c"
+				>
+			</File>
+			<File
+				RelativePath=".\src\keepalive.c"
+				>
+			</File>
+			<File
+				RelativePath=".\src\kex.c"
+				>
+			</File>
+			<File
+				RelativePath=".\src\knownhost.c"
+				>
+			</File>
+			<File
+				RelativePath=".\src\libgcrypt.c"
+				>
+			</File>
+			<File
+				RelativePath=".\src\mac.c"
+				>
+			</File>
+			<File
+				RelativePath=".\src\mbedtls.c"
+				>
+			</File>
+			<File
+				RelativePath=".\src\misc.c"
+				>
+			</File>
+			<File
+				RelativePath=".\src\openssl.c"
+				>
+			</File>
+			<File
+				RelativePath=".\src\os400qc3.c"
+				>
+			</File>
+			<File
+				RelativePath=".\src\packet.c"
+				>
+			</File>
+			<File
+				RelativePath=".\src\pem.c"
+				>
+			</File>
+			<File
+				RelativePath=".\src\publickey.c"
+				>
+			</File>
+			<File
+				RelativePath=".\src\scp.c"
+				>
+			</File>
+			<File
+				RelativePath=".\src\session.c"
+				>
+			</File>
+			<File
+				RelativePath=".\src\sftp.c"
+				>
+			</File>
+			<File
+				RelativePath=".\src\transport.c"
+				>
+			</File>
+			<File
+				RelativePath=".\src\userauth.c"
+				>
+			</File>
+			<File
+				RelativePath=".\src\version.c"
+				>
+			</File>
+			<File
+				RelativePath=".\src\wincng.c"
+				>
+			</File>
+		</Filter>
+		<Filter
+			Name="Í·Îļþ"
+			Filter="h;hpp;hxx"
+			>
+			<File
+				RelativePath=".\src\blf.h"
+				>
+			</File>
+			<File
+				RelativePath=".\src\channel.h"
+				>
+			</File>
+			<File
+				RelativePath=".\src\comp.h"
+				>
+			</File>
+			<File
+				RelativePath=".\src\crypto.h"
+				>
+			</File>
+			<File
+				RelativePath=".\src\libgcrypt.h"
+				>
+			</File>
+			<File
+				RelativePath=".\libssh2_config.h"
+				>
+			</File>
+			<File
+				RelativePath=".\src\libssh2_priv.h"
+				>
+			</File>
+			<File
+				RelativePath=".\src\mac.h"
+				>
+			</File>
+			<File
+				RelativePath=".\src\mbedtls.h"
+				>
+			</File>
+			<File
+				RelativePath=".\src\misc.h"
+				>
+			</File>
+			<File
+				RelativePath=".\src\openssl.h"
+				>
+			</File>
+			<File
+				RelativePath=".\src\os400qc3.h"
+				>
+			</File>
+			<File
+				RelativePath=".\src\packet.h"
+				>
+			</File>
+			<File
+				RelativePath=".\src\session.h"
+				>
+			</File>
+			<File
+				RelativePath=".\src\sftp.h"
+				>
+			</File>
+			<File
+				RelativePath=".\src\transport.h"
+				>
+			</File>
+			<File
+				RelativePath=".\src\userauth.h"
+				>
+			</File>
+			<File
+				RelativePath=".\src\wincng.h"
+				>
+			</File>
+		</Filter>
+		<Filter
+			Name="×ÊÔ´Îļþ"
+			>
+			<File
+				RelativePath=".\libssh2.rc"
+				>
+			</File>
+		</Filter>
+	</Files>
+	<Globals>
+	</Globals>
+</VisualStudioProject>

+ 860 - 0
libssh2/libssh2/src/agent.c

@@ -0,0 +1,860 @@
+/*
+ * Copyright (c) 2009 by Daiki Ueno
+ * Copyright (C) 2010-2014 by Daniel Stenberg
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms,
+ * with or without modification, are permitted provided
+ * that the following conditions are met:
+ *
+ *   Redistributions of source code must retain the above
+ *   copyright notice, this list of conditions and the
+ *   following disclaimer.
+ *
+ *   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.
+ *
+ *   Neither the name of the copyright holder nor the names
+ *   of any other contributors may be used to endorse or
+ *   promote products derived from this software without
+ *   specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+ * CONTRIBUTORS "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 COPYRIGHT OWNER OR
+ * CONTRIBUTORS 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 "libssh2_priv.h"
+#include "misc.h"
+#include <errno.h>
+#ifdef HAVE_SYS_UN_H
+#include <sys/un.h>
+#else
+/* Use the existence of sys/un.h as a test if Unix domain socket is
+   supported.  winsock*.h define PF_UNIX/AF_UNIX but do not actually
+   support them. */
+#undef PF_UNIX
+#endif
+#include "userauth.h"
+#include "session.h"
+
+/* Requests from client to agent for protocol 1 key operations */
+#define SSH_AGENTC_REQUEST_RSA_IDENTITIES 1
+#define SSH_AGENTC_RSA_CHALLENGE 3
+#define SSH_AGENTC_ADD_RSA_IDENTITY 7
+#define SSH_AGENTC_REMOVE_RSA_IDENTITY 8
+#define SSH_AGENTC_REMOVE_ALL_RSA_IDENTITIES 9
+#define SSH_AGENTC_ADD_RSA_ID_CONSTRAINED 24
+
+/* Requests from client to agent for protocol 2 key operations */
+#define SSH2_AGENTC_REQUEST_IDENTITIES 11
+#define SSH2_AGENTC_SIGN_REQUEST 13
+#define SSH2_AGENTC_ADD_IDENTITY 17
+#define SSH2_AGENTC_REMOVE_IDENTITY 18
+#define SSH2_AGENTC_REMOVE_ALL_IDENTITIES 19
+#define SSH2_AGENTC_ADD_ID_CONSTRAINED 25
+
+/* Key-type independent requests from client to agent */
+#define SSH_AGENTC_ADD_SMARTCARD_KEY 20
+#define SSH_AGENTC_REMOVE_SMARTCARD_KEY 21
+#define SSH_AGENTC_LOCK 22
+#define SSH_AGENTC_UNLOCK 23
+#define SSH_AGENTC_ADD_SMARTCARD_KEY_CONSTRAINED 26
+
+/* Generic replies from agent to client */
+#define SSH_AGENT_FAILURE 5
+#define SSH_AGENT_SUCCESS 6
+
+/* Replies from agent to client for protocol 1 key operations */
+#define SSH_AGENT_RSA_IDENTITIES_ANSWER 2
+#define SSH_AGENT_RSA_RESPONSE 4
+
+/* Replies from agent to client for protocol 2 key operations */
+#define SSH2_AGENT_IDENTITIES_ANSWER 12
+#define SSH2_AGENT_SIGN_RESPONSE 14
+
+/* Key constraint identifiers */
+#define SSH_AGENT_CONSTRAIN_LIFETIME 1
+#define SSH_AGENT_CONSTRAIN_CONFIRM 2
+
+/* non-blocking mode on agent connection is not yet implemented, but
+   for future use. */
+typedef enum {
+    agent_NB_state_init = 0,
+    agent_NB_state_request_created,
+    agent_NB_state_request_length_sent,
+    agent_NB_state_request_sent,
+    agent_NB_state_response_length_received,
+    agent_NB_state_response_received
+} agent_nonblocking_states;
+
+typedef struct agent_transaction_ctx {
+    unsigned char *request;
+    size_t request_len;
+    unsigned char *response;
+    size_t response_len;
+    agent_nonblocking_states state;
+} *agent_transaction_ctx_t;
+
+typedef int (*agent_connect_func)(LIBSSH2_AGENT *agent);
+typedef int (*agent_transact_func)(LIBSSH2_AGENT *agent,
+                                   agent_transaction_ctx_t transctx);
+typedef int (*agent_disconnect_func)(LIBSSH2_AGENT *agent);
+
+struct agent_publickey {
+    struct list_node node;
+
+    /* this is the struct we expose externally */
+    struct libssh2_agent_publickey external;
+};
+
+struct agent_ops {
+    agent_connect_func connect;
+    agent_transact_func transact;
+    agent_disconnect_func disconnect;
+};
+
+struct _LIBSSH2_AGENT
+{
+    LIBSSH2_SESSION *session;  /* the session this "belongs to" */
+
+    libssh2_socket_t fd;
+
+    struct agent_ops *ops;
+
+    struct agent_transaction_ctx transctx;
+    struct agent_publickey *identity;
+    struct list_head head;              /* list of public keys */
+
+    char *identity_agent_path; /* Path to a custom identity agent socket */
+};
+
+#ifdef PF_UNIX
+static int
+agent_connect_unix(LIBSSH2_AGENT *agent)
+{
+    const char *path;
+    struct sockaddr_un s_un;
+
+    path = agent->identity_agent_path;
+    if(!path) {
+        path = getenv("SSH_AUTH_SOCK");
+        if(!path)
+            return _libssh2_error(agent->session, LIBSSH2_ERROR_BAD_USE,
+                                  "no auth sock variable");
+    }
+
+    agent->fd = socket(PF_UNIX, SOCK_STREAM, 0);
+    if(agent->fd < 0)
+        return _libssh2_error(agent->session, LIBSSH2_ERROR_BAD_SOCKET,
+                              "failed creating socket");
+
+    s_un.sun_family = AF_UNIX;
+    strncpy(s_un.sun_path, path, sizeof s_un.sun_path);
+    s_un.sun_path[sizeof(s_un.sun_path)-1] = 0; /* make sure there's a trailing
+                                                   zero */
+    if(connect(agent->fd, (struct sockaddr*)(&s_un), sizeof s_un) != 0) {
+        close(agent->fd);
+        return _libssh2_error(agent->session, LIBSSH2_ERROR_AGENT_PROTOCOL,
+                              "failed connecting with agent");
+    }
+
+    return LIBSSH2_ERROR_NONE;
+}
+
+static int
+agent_transact_unix(LIBSSH2_AGENT *agent, agent_transaction_ctx_t transctx)
+{
+    unsigned char buf[4];
+    int rc;
+
+    /* Send the length of the request */
+    if(transctx->state == agent_NB_state_request_created) {
+        _libssh2_htonu32(buf, transctx->request_len);
+        rc = LIBSSH2_SEND_FD(agent->session, agent->fd, buf, sizeof buf, 0);
+        if(rc == -EAGAIN)
+            return LIBSSH2_ERROR_EAGAIN;
+        else if(rc < 0)
+            return _libssh2_error(agent->session, LIBSSH2_ERROR_SOCKET_SEND,
+                                  "agent send failed");
+        transctx->state = agent_NB_state_request_length_sent;
+    }
+
+    /* Send the request body */
+    if(transctx->state == agent_NB_state_request_length_sent) {
+        rc = LIBSSH2_SEND_FD(agent->session, agent->fd, transctx->request,
+                           transctx->request_len, 0);
+        if(rc == -EAGAIN)
+            return LIBSSH2_ERROR_EAGAIN;
+        else if(rc < 0)
+            return _libssh2_error(agent->session, LIBSSH2_ERROR_SOCKET_SEND,
+                                  "agent send failed");
+        transctx->state = agent_NB_state_request_sent;
+    }
+
+    /* Receive the length of a response */
+    if(transctx->state == agent_NB_state_request_sent) {
+        rc = LIBSSH2_RECV_FD(agent->session, agent->fd, buf, sizeof buf, 0);
+        if(rc < 0) {
+            if(rc == -EAGAIN)
+                return LIBSSH2_ERROR_EAGAIN;
+            return _libssh2_error(agent->session, LIBSSH2_ERROR_SOCKET_RECV,
+                                  "agent recv failed");
+        }
+        transctx->response_len = _libssh2_ntohu32(buf);
+        transctx->response = LIBSSH2_ALLOC(agent->session,
+                                           transctx->response_len);
+        if(!transctx->response)
+            return LIBSSH2_ERROR_ALLOC;
+
+        transctx->state = agent_NB_state_response_length_received;
+    }
+
+    /* Receive the response body */
+    if(transctx->state == agent_NB_state_response_length_received) {
+        rc = LIBSSH2_RECV_FD(agent->session, agent->fd, transctx->response,
+                           transctx->response_len, 0);
+        if(rc < 0) {
+            if(rc == -EAGAIN)
+                return LIBSSH2_ERROR_EAGAIN;
+            return _libssh2_error(agent->session, LIBSSH2_ERROR_SOCKET_SEND,
+                                  "agent recv failed");
+        }
+        transctx->state = agent_NB_state_response_received;
+    }
+
+    return 0;
+}
+
+static int
+agent_disconnect_unix(LIBSSH2_AGENT *agent)
+{
+    int ret;
+    ret = close(agent->fd);
+    if(ret != -1)
+        agent->fd = LIBSSH2_INVALID_SOCKET;
+    else
+        return _libssh2_error(agent->session, LIBSSH2_ERROR_SOCKET_DISCONNECT,
+                              "failed closing the agent socket");
+    return LIBSSH2_ERROR_NONE;
+}
+
+struct agent_ops agent_ops_unix = {
+    agent_connect_unix,
+    agent_transact_unix,
+    agent_disconnect_unix
+};
+#endif  /* PF_UNIX */
+
+#ifdef WIN32
+/* Code to talk to Pageant was taken from PuTTY.
+ *
+ * Portions copyright Robert de Bath, Joris van Rantwijk, Delian
+ * Delchev, Andreas Schultz, Jeroen Massar, Wez Furlong, Nicolas
+ * Barry, Justin Bradford, Ben Harris, Malcolm Smith, Ahmad Khalifa,
+ * Markus Kuhn, Colin Watson, and CORE SDI S.A.
+ */
+#define PAGEANT_COPYDATA_ID 0x804e50ba   /* random goop */
+#define PAGEANT_MAX_MSGLEN  8192
+
+static int
+agent_connect_pageant(LIBSSH2_AGENT *agent)
+{
+    HWND hwnd;
+    hwnd = FindWindow("Pageant", "Pageant");
+    if(!hwnd)
+        return _libssh2_error(agent->session, LIBSSH2_ERROR_AGENT_PROTOCOL,
+                              "failed connecting agent");
+    agent->fd = 0;         /* Mark as the connection has been established */
+    return LIBSSH2_ERROR_NONE;
+}
+
+static int
+agent_transact_pageant(LIBSSH2_AGENT *agent, agent_transaction_ctx_t transctx)
+{
+    HWND hwnd;
+    char mapname[23];
+    HANDLE filemap;
+    unsigned char *p;
+    unsigned char *p2;
+    int id;
+    COPYDATASTRUCT cds;
+
+    if(!transctx || 4 + transctx->request_len > PAGEANT_MAX_MSGLEN)
+        return _libssh2_error(agent->session, LIBSSH2_ERROR_INVAL,
+                              "illegal input");
+
+    hwnd = FindWindow("Pageant", "Pageant");
+    if(!hwnd)
+        return _libssh2_error(agent->session, LIBSSH2_ERROR_AGENT_PROTOCOL,
+                              "found no pageant");
+
+    snprintf(mapname, sizeof(mapname),
+             "PageantRequest%08x%c", (unsigned)GetCurrentThreadId(), '\0');
+    filemap = CreateFileMapping(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE,
+                                0, PAGEANT_MAX_MSGLEN, mapname);
+
+    if(filemap == NULL || filemap == INVALID_HANDLE_VALUE)
+        return _libssh2_error(agent->session, LIBSSH2_ERROR_AGENT_PROTOCOL,
+                              "failed setting up pageant filemap");
+
+    p2 = p = MapViewOfFile(filemap, FILE_MAP_WRITE, 0, 0, 0);
+    if(p == NULL || p2 == NULL) {
+        CloseHandle(filemap);
+        return _libssh2_error(agent->session, LIBSSH2_ERROR_AGENT_PROTOCOL,
+                              "failed to open pageant filemap for writing");
+    }
+
+    _libssh2_store_str(&p2, (const char *)transctx->request,
+                       transctx->request_len);
+
+    cds.dwData = PAGEANT_COPYDATA_ID;
+    cds.cbData = 1 + strlen(mapname);
+    cds.lpData = mapname;
+
+    id = SendMessage(hwnd, WM_COPYDATA, (WPARAM) NULL, (LPARAM) &cds);
+    if(id > 0) {
+        transctx->response_len = _libssh2_ntohu32(p);
+        if(transctx->response_len > PAGEANT_MAX_MSGLEN) {
+            UnmapViewOfFile(p);
+            CloseHandle(filemap);
+            return _libssh2_error(agent->session, LIBSSH2_ERROR_AGENT_PROTOCOL,
+                                  "agent setup fail");
+        }
+        transctx->response = LIBSSH2_ALLOC(agent->session,
+                                           transctx->response_len);
+        if(!transctx->response) {
+            UnmapViewOfFile(p);
+            CloseHandle(filemap);
+            return _libssh2_error(agent->session, LIBSSH2_ERROR_ALLOC,
+                                  "agent malloc");
+        }
+        memcpy(transctx->response, p + 4, transctx->response_len);
+    }
+
+    UnmapViewOfFile(p);
+    CloseHandle(filemap);
+    return 0;
+}
+
+static int
+agent_disconnect_pageant(LIBSSH2_AGENT *agent)
+{
+    agent->fd = LIBSSH2_INVALID_SOCKET;
+    return 0;
+}
+
+struct agent_ops agent_ops_pageant = {
+    agent_connect_pageant,
+    agent_transact_pageant,
+    agent_disconnect_pageant
+};
+#endif  /* WIN32 */
+
+static struct {
+    const char *name;
+    struct agent_ops *ops;
+} supported_backends[] = {
+#ifdef WIN32
+    {"Pageant", &agent_ops_pageant},
+#endif  /* WIN32 */
+#ifdef PF_UNIX
+    {"Unix", &agent_ops_unix},
+#endif  /* PF_UNIX */
+    {NULL, NULL}
+};
+
+static int
+agent_sign(LIBSSH2_SESSION *session, unsigned char **sig, size_t *sig_len,
+           const unsigned char *data, size_t data_len, void **abstract)
+{
+    LIBSSH2_AGENT *agent = (LIBSSH2_AGENT *) (*abstract);
+    agent_transaction_ctx_t transctx = &agent->transctx;
+    struct agent_publickey *identity = agent->identity;
+    ssize_t len = 1 + 4 + identity->external.blob_len + 4 + data_len + 4;
+    ssize_t method_len;
+    unsigned char *s;
+    int rc;
+
+    /* Create a request to sign the data */
+    if(transctx->state == agent_NB_state_init) {
+        s = transctx->request = LIBSSH2_ALLOC(session, len);
+        if(!transctx->request)
+            return _libssh2_error(session, LIBSSH2_ERROR_ALLOC,
+                                  "out of memory");
+
+        *s++ = SSH2_AGENTC_SIGN_REQUEST;
+        /* key blob */
+        _libssh2_store_str(&s, (const char *)identity->external.blob,
+                           identity->external.blob_len);
+        /* data */
+        _libssh2_store_str(&s, (const char *)data, data_len);
+
+        /* flags */
+        _libssh2_store_u32(&s, 0);
+
+        transctx->request_len = s - transctx->request;
+        transctx->state = agent_NB_state_request_created;
+    }
+
+    /* Make sure to be re-called as a result of EAGAIN. */
+    if(*transctx->request != SSH2_AGENTC_SIGN_REQUEST)
+        return _libssh2_error(session, LIBSSH2_ERROR_BAD_USE,
+                              "illegal request");
+
+    if(!agent->ops)
+        /* if no agent has been connected, bail out */
+        return _libssh2_error(session, LIBSSH2_ERROR_BAD_USE,
+                              "agent not connected");
+
+    rc = agent->ops->transact(agent, transctx);
+    if(rc) {
+        goto error;
+    }
+    LIBSSH2_FREE(session, transctx->request);
+    transctx->request = NULL;
+
+    len = transctx->response_len;
+    s = transctx->response;
+    len--;
+    if(len < 0) {
+        rc = LIBSSH2_ERROR_AGENT_PROTOCOL;
+        goto error;
+    }
+    if(*s != SSH2_AGENT_SIGN_RESPONSE) {
+        rc = LIBSSH2_ERROR_AGENT_PROTOCOL;
+        goto error;
+    }
+    s++;
+
+    /* Skip the entire length of the signature */
+    len -= 4;
+    if(len < 0) {
+        rc = LIBSSH2_ERROR_AGENT_PROTOCOL;
+        goto error;
+    }
+    s += 4;
+
+    /* Skip signing method */
+    len -= 4;
+    if(len < 0) {
+        rc = LIBSSH2_ERROR_AGENT_PROTOCOL;
+        goto error;
+    }
+    method_len = _libssh2_ntohu32(s);
+    s += 4;
+    len -= method_len;
+    if(len < 0) {
+        rc = LIBSSH2_ERROR_AGENT_PROTOCOL;
+        goto error;
+    }
+    s += method_len;
+
+    /* Read the signature */
+    len -= 4;
+    if(len < 0) {
+        rc = LIBSSH2_ERROR_AGENT_PROTOCOL;
+        goto error;
+    }
+    *sig_len = _libssh2_ntohu32(s);
+    s += 4;
+    len -= *sig_len;
+    if(len < 0) {
+        rc = LIBSSH2_ERROR_AGENT_PROTOCOL;
+        goto error;
+    }
+
+    *sig = LIBSSH2_ALLOC(session, *sig_len);
+    if(!*sig) {
+        rc = LIBSSH2_ERROR_ALLOC;
+        goto error;
+    }
+    memcpy(*sig, s, *sig_len);
+
+  error:
+    LIBSSH2_FREE(session, transctx->request);
+    transctx->request = NULL;
+
+    LIBSSH2_FREE(session, transctx->response);
+    transctx->response = NULL;
+
+    return _libssh2_error(session, rc, "agent sign failure");
+}
+
+static int
+agent_list_identities(LIBSSH2_AGENT *agent)
+{
+    agent_transaction_ctx_t transctx = &agent->transctx;
+    ssize_t len, num_identities;
+    unsigned char *s;
+    int rc;
+    unsigned char c = SSH2_AGENTC_REQUEST_IDENTITIES;
+
+    /* Create a request to list identities */
+    if(transctx->state == agent_NB_state_init) {
+        transctx->request = &c;
+        transctx->request_len = 1;
+        transctx->state = agent_NB_state_request_created;
+    }
+
+    /* Make sure to be re-called as a result of EAGAIN. */
+    if(*transctx->request != SSH2_AGENTC_REQUEST_IDENTITIES)
+        return _libssh2_error(agent->session, LIBSSH2_ERROR_BAD_USE,
+                              "illegal agent request");
+
+    if(!agent->ops)
+        /* if no agent has been connected, bail out */
+        return _libssh2_error(agent->session, LIBSSH2_ERROR_BAD_USE,
+                              "agent not connected");
+
+    rc = agent->ops->transact(agent, transctx);
+    if(rc) {
+        goto error;
+    }
+    transctx->request = NULL;
+
+    len = transctx->response_len;
+    s = transctx->response;
+    len--;
+    if(len < 0) {
+        rc = LIBSSH2_ERROR_AGENT_PROTOCOL;
+        goto error;
+    }
+    if(*s != SSH2_AGENT_IDENTITIES_ANSWER) {
+        rc = LIBSSH2_ERROR_AGENT_PROTOCOL;
+        goto error;
+    }
+    s++;
+
+    /* Read the length of identities */
+    len -= 4;
+    if(len < 0) {
+        rc = LIBSSH2_ERROR_AGENT_PROTOCOL;
+        goto error;
+    }
+    num_identities = _libssh2_ntohu32(s);
+    s += 4;
+
+    while(num_identities--) {
+        struct agent_publickey *identity;
+        ssize_t comment_len;
+
+        /* Read the length of the blob */
+        len -= 4;
+        if(len < 0) {
+            rc = LIBSSH2_ERROR_AGENT_PROTOCOL;
+            goto error;
+        }
+        identity = LIBSSH2_ALLOC(agent->session, sizeof *identity);
+        if(!identity) {
+            rc = LIBSSH2_ERROR_ALLOC;
+            goto error;
+        }
+        identity->external.blob_len = _libssh2_ntohu32(s);
+        s += 4;
+
+        /* Read the blob */
+        len -= identity->external.blob_len;
+        if(len < 0) {
+            rc = LIBSSH2_ERROR_AGENT_PROTOCOL;
+            LIBSSH2_FREE(agent->session, identity);
+            goto error;
+        }
+
+        identity->external.blob = LIBSSH2_ALLOC(agent->session,
+                                                identity->external.blob_len);
+        if(!identity->external.blob) {
+            rc = LIBSSH2_ERROR_ALLOC;
+            LIBSSH2_FREE(agent->session, identity);
+            goto error;
+        }
+        memcpy(identity->external.blob, s, identity->external.blob_len);
+        s += identity->external.blob_len;
+
+        /* Read the length of the comment */
+        len -= 4;
+        if(len < 0) {
+            rc = LIBSSH2_ERROR_AGENT_PROTOCOL;
+            LIBSSH2_FREE(agent->session, identity->external.blob);
+            LIBSSH2_FREE(agent->session, identity);
+            goto error;
+        }
+        comment_len = _libssh2_ntohu32(s);
+        s += 4;
+
+        /* Read the comment */
+        len -= comment_len;
+        if(len < 0) {
+            rc = LIBSSH2_ERROR_AGENT_PROTOCOL;
+            LIBSSH2_FREE(agent->session, identity->external.blob);
+            LIBSSH2_FREE(agent->session, identity);
+            goto error;
+        }
+
+        identity->external.comment = LIBSSH2_ALLOC(agent->session,
+                                                   comment_len + 1);
+        if(!identity->external.comment) {
+            rc = LIBSSH2_ERROR_ALLOC;
+            LIBSSH2_FREE(agent->session, identity->external.blob);
+            LIBSSH2_FREE(agent->session, identity);
+            goto error;
+        }
+        identity->external.comment[comment_len] = '\0';
+        memcpy(identity->external.comment, s, comment_len);
+        s += comment_len;
+
+        _libssh2_list_add(&agent->head, &identity->node);
+    }
+ error:
+    LIBSSH2_FREE(agent->session, transctx->response);
+    transctx->response = NULL;
+
+    return _libssh2_error(agent->session, rc,
+                          "agent list id failed");
+}
+
+static void
+agent_free_identities(LIBSSH2_AGENT *agent)
+{
+    struct agent_publickey *node;
+    struct agent_publickey *next;
+
+    for(node = _libssh2_list_first(&agent->head); node; node = next) {
+        next = _libssh2_list_next(&node->node);
+        LIBSSH2_FREE(agent->session, node->external.blob);
+        LIBSSH2_FREE(agent->session, node->external.comment);
+        LIBSSH2_FREE(agent->session, node);
+    }
+    _libssh2_list_init(&agent->head);
+}
+
+#define AGENT_PUBLICKEY_MAGIC 0x3bdefed2
+/*
+ * agent_publickey_to_external()
+ *
+ * Copies data from the internal to the external representation struct.
+ *
+ */
+static struct libssh2_agent_publickey *
+agent_publickey_to_external(struct agent_publickey *node)
+{
+    struct libssh2_agent_publickey *ext = &node->external;
+
+    ext->magic = AGENT_PUBLICKEY_MAGIC;
+    ext->node = node;
+
+    return ext;
+}
+
+/*
+ * libssh2_agent_init
+ *
+ * Init an ssh-agent handle. Returns the pointer to the handle.
+ *
+ */
+LIBSSH2_API LIBSSH2_AGENT *
+libssh2_agent_init(LIBSSH2_SESSION *session)
+{
+    LIBSSH2_AGENT *agent;
+
+    agent = LIBSSH2_CALLOC(session, sizeof *agent);
+    if(!agent) {
+        _libssh2_error(session, LIBSSH2_ERROR_ALLOC,
+                       "Unable to allocate space for agent connection");
+        return NULL;
+    }
+    agent->fd = LIBSSH2_INVALID_SOCKET;
+    agent->session = session;
+    agent->identity_agent_path = NULL;
+    _libssh2_list_init(&agent->head);
+
+    return agent;
+}
+
+/*
+ * libssh2_agent_connect()
+ *
+ * Connect to an ssh-agent.
+ *
+ * Returns 0 if succeeded, or a negative value for error.
+ */
+LIBSSH2_API int
+libssh2_agent_connect(LIBSSH2_AGENT *agent)
+{
+    int i, rc = -1;
+    for(i = 0; supported_backends[i].name; i++) {
+        agent->ops = supported_backends[i].ops;
+        rc = (agent->ops->connect)(agent);
+        if(!rc)
+            return 0;
+    }
+    return rc;
+}
+
+/*
+ * libssh2_agent_list_identities()
+ *
+ * Request ssh-agent to list identities.
+ *
+ * Returns 0 if succeeded, or a negative value for error.
+ */
+LIBSSH2_API int
+libssh2_agent_list_identities(LIBSSH2_AGENT *agent)
+{
+    memset(&agent->transctx, 0, sizeof agent->transctx);
+    /* Abandon the last fetched identities */
+    agent_free_identities(agent);
+    return agent_list_identities(agent);
+}
+
+/*
+ * libssh2_agent_get_identity()
+ *
+ * Traverse the internal list of public keys. Pass NULL to 'prev' to get
+ * the first one. Or pass a pointer to the previously returned one to get the
+ * next.
+ *
+ * Returns:
+ * 0 if a fine public key was stored in 'store'
+ * 1 if end of public keys
+ * [negative] on errors
+ */
+LIBSSH2_API int
+libssh2_agent_get_identity(LIBSSH2_AGENT *agent,
+                           struct libssh2_agent_publickey **ext,
+                           struct libssh2_agent_publickey *oprev)
+{
+    struct agent_publickey *node;
+    if(oprev && oprev->node) {
+        /* we have a starting point */
+        struct agent_publickey *prev = oprev->node;
+
+        /* get the next node in the list */
+        node = _libssh2_list_next(&prev->node);
+    }
+    else
+        node = _libssh2_list_first(&agent->head);
+
+    if(!node)
+        /* no (more) node */
+        return 1;
+
+    *ext = agent_publickey_to_external(node);
+
+    return 0;
+}
+
+/*
+ * libssh2_agent_userauth()
+ *
+ * Do publickey user authentication with the help of ssh-agent.
+ *
+ * Returns 0 if succeeded, or a negative value for error.
+ */
+LIBSSH2_API int
+libssh2_agent_userauth(LIBSSH2_AGENT *agent,
+                       const char *username,
+                       struct libssh2_agent_publickey *identity)
+{
+    void *abstract = agent;
+    int rc;
+
+    if(agent->session->userauth_pblc_state == libssh2_NB_state_idle) {
+        memset(&agent->transctx, 0, sizeof agent->transctx);
+        agent->identity = identity->node;
+    }
+
+    BLOCK_ADJUST(rc, agent->session,
+                 _libssh2_userauth_publickey(agent->session, username,
+                                             strlen(username),
+                                             identity->blob,
+                                             identity->blob_len,
+                                             agent_sign,
+                                             &abstract));
+    return rc;
+}
+
+/*
+ * libssh2_agent_disconnect()
+ *
+ * Close a connection to an ssh-agent.
+ *
+ * Returns 0 if succeeded, or a negative value for error.
+ */
+LIBSSH2_API int
+libssh2_agent_disconnect(LIBSSH2_AGENT *agent)
+{
+    if(agent->ops && agent->fd != LIBSSH2_INVALID_SOCKET)
+        return agent->ops->disconnect(agent);
+    return 0;
+}
+
+/*
+ * libssh2_agent_free()
+ *
+ * Free an ssh-agent handle.  This function also frees the internal
+ * collection of public keys.
+ */
+LIBSSH2_API void
+libssh2_agent_free(LIBSSH2_AGENT *agent)
+{
+    /* Allow connection freeing when the socket has lost its connection */
+    if(agent->fd != LIBSSH2_INVALID_SOCKET) {
+        libssh2_agent_disconnect(agent);
+    }
+
+    if(agent->identity_agent_path != NULL)
+        LIBSSH2_FREE(agent->session, agent->identity_agent_path);
+
+    agent_free_identities(agent);
+    LIBSSH2_FREE(agent->session, agent);
+}
+
+/*
+ * libssh2_agent_set_identity_path()
+ *
+ * Allows a custom agent socket path beyond SSH_AUTH_SOCK env
+ *
+ */
+LIBSSH2_API void
+libssh2_agent_set_identity_path(LIBSSH2_AGENT *agent, const char *path)
+{
+    if(agent->identity_agent_path) {
+        LIBSSH2_FREE(agent->session, agent->identity_agent_path);
+        agent->identity_agent_path = NULL;
+    }
+
+    if(path) {
+        size_t path_len = strlen(path);
+        if(path_len < SIZE_MAX - 1) {
+            char *path_buf = LIBSSH2_ALLOC(agent->session, path_len + 1);
+            memcpy(path_buf, path, path_len);
+            path_buf[path_len] = '\0';
+            agent->identity_agent_path = path_buf;
+        }
+    }
+}
+
+/*
+ * libssh2_agent_get_identity_path()
+ *
+ * Returns the custom agent socket path if set
+ *
+ */
+LIBSSH2_API const char *libssh2_agent_get_identity_path(LIBSSH2_AGENT *agent)
+{
+    return agent->identity_agent_path;
+}

+ 180 - 0
libssh2/libssh2/src/bcrypt_pbkdf.c

@@ -0,0 +1,180 @@
+/* $OpenBSD: bcrypt_pbkdf.c,v 1.4 2013/07/29 00:55:53 tedu Exp $ */
+/*
+ * Copyright (c) 2013 Ted Unangst <tedu@openbsd.org>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+
+#ifndef HAVE_BCRYPT_PBKDF
+
+#include "libssh2_priv.h"
+#include <stdlib.h>
+#include <sys/types.h>
+#ifdef HAVE_SYS_PARAM_H
+#include <sys/param.h>
+#endif
+
+#include "blf.h"
+
+#define MINIMUM(a,b) (((a) < (b)) ? (a) : (b))
+
+/*
+ * pkcs #5 pbkdf2 implementation using the "bcrypt" hash
+ *
+ * The bcrypt hash function is derived from the bcrypt password hashing
+ * function with the following modifications:
+ * 1. The input password and salt are preprocessed with SHA512.
+ * 2. The output length is expanded to 256 bits.
+ * 3. Subsequently the magic string to be encrypted is lengthened and modifed
+ *    to "OxychromaticBlowfishSwatDynamite"
+ * 4. The hash function is defined to perform 64 rounds of initial state
+ *    expansion. (More rounds are performed by iterating the hash.)
+ *
+ * Note that this implementation pulls the SHA512 operations into the caller
+ * as a performance optimization.
+ *
+ * One modification from official pbkdf2. Instead of outputting key material
+ * linearly, we mix it. pbkdf2 has a known weakness where if one uses it to
+ * generate (i.e.) 512 bits of key material for use as two 256 bit keys, an
+ * attacker can merely run once through the outer loop below, but the user
+ * always runs it twice. Shuffling output bytes requires computing the
+ * entirety of the key material to assemble any subkey. This is something a
+ * wise caller could do; we just do it for you.
+ */
+
+#define BCRYPT_BLOCKS 8
+#define BCRYPT_HASHSIZE (BCRYPT_BLOCKS * 4)
+
+static void
+bcrypt_hash(uint8_t *sha2pass, uint8_t *sha2salt, uint8_t *out)
+{
+    blf_ctx state;
+    uint8_t ciphertext[BCRYPT_HASHSIZE] =
+        "OxychromaticBlowfishSwatDynamite";
+    uint32_t cdata[BCRYPT_BLOCKS];
+    int i;
+    uint16_t j;
+    size_t shalen = SHA512_DIGEST_LENGTH;
+
+    /* key expansion */
+    Blowfish_initstate(&state);
+    Blowfish_expandstate(&state, sha2salt, shalen, sha2pass, shalen);
+    for(i = 0; i < 64; i++) {
+        Blowfish_expand0state(&state, sha2salt, shalen);
+        Blowfish_expand0state(&state, sha2pass, shalen);
+    }
+
+    /* encryption */
+    j = 0;
+    for(i = 0; i < BCRYPT_BLOCKS; i++)
+        cdata[i] = Blowfish_stream2word(ciphertext, sizeof(ciphertext),
+                                        &j);
+    for(i = 0; i < 64; i++)
+        blf_enc(&state, cdata, sizeof(cdata) / sizeof(uint64_t));
+
+    /* copy out */
+    for(i = 0; i < BCRYPT_BLOCKS; i++) {
+        out[4 * i + 3] = (cdata[i] >> 24) & 0xff;
+        out[4 * i + 2] = (cdata[i] >> 16) & 0xff;
+        out[4 * i + 1] = (cdata[i] >> 8) & 0xff;
+        out[4 * i + 0] = cdata[i] & 0xff;
+    }
+
+    /* zap */
+    _libssh2_explicit_zero(ciphertext, sizeof(ciphertext));
+    _libssh2_explicit_zero(cdata, sizeof(cdata));
+    _libssh2_explicit_zero(&state, sizeof(state));
+}
+
+int
+bcrypt_pbkdf(const char *pass, size_t passlen, const uint8_t *salt,
+             size_t saltlen,
+             uint8_t *key, size_t keylen, unsigned int rounds)
+{
+    uint8_t sha2pass[SHA512_DIGEST_LENGTH];
+    uint8_t sha2salt[SHA512_DIGEST_LENGTH];
+    uint8_t out[BCRYPT_HASHSIZE];
+    uint8_t tmpout[BCRYPT_HASHSIZE];
+    uint8_t *countsalt;
+    size_t i, j, amt, stride;
+    uint32_t count;
+    size_t origkeylen = keylen;
+    libssh2_sha512_ctx ctx;
+
+    /* nothing crazy */
+    if(rounds < 1)
+        return -1;
+    if(passlen == 0 || saltlen == 0 || keylen == 0 ||
+       keylen > sizeof(out) * sizeof(out) || saltlen > 1<<20)
+        return -1;
+    countsalt = calloc(1, saltlen + 4);
+    if(countsalt == NULL)
+        return -1;
+    stride = (keylen + sizeof(out) - 1) / sizeof(out);
+    amt = (keylen + stride - 1) / stride;
+
+    memcpy(countsalt, salt, saltlen);
+
+    /* collapse password */
+    libssh2_sha512_init(&ctx);
+    libssh2_sha512_update(ctx, pass, passlen);
+    libssh2_sha512_final(ctx, sha2pass);
+
+    /* generate key, sizeof(out) at a time */
+    for(count = 1; keylen > 0; count++) {
+        countsalt[saltlen + 0] = (count >> 24) & 0xff;
+        countsalt[saltlen + 1] = (count >> 16) & 0xff;
+        countsalt[saltlen + 2] = (count >> 8) & 0xff;
+        countsalt[saltlen + 3] = count & 0xff;
+
+        /* first round, salt is salt */
+        libssh2_sha512_init(&ctx);
+        libssh2_sha512_update(ctx, countsalt, saltlen + 4);
+        libssh2_sha512_final(ctx, sha2salt);
+
+        bcrypt_hash(sha2pass, sha2salt, tmpout);
+        memcpy(out, tmpout, sizeof(out));
+
+        for(i = 1; i < rounds; i++) {
+            /* subsequent rounds, salt is previous output */
+            libssh2_sha512_init(&ctx);
+            libssh2_sha512_update(ctx, tmpout, sizeof(tmpout));
+            libssh2_sha512_final(ctx, sha2salt);
+
+            bcrypt_hash(sha2pass, sha2salt, tmpout);
+            for(j = 0; j < sizeof(out); j++)
+                out[j] ^= tmpout[j];
+        }
+
+        /*
+         * pbkdf2 deviation: ouput the key material non-linearly.
+         */
+        amt = MINIMUM(amt, keylen);
+        for(i = 0; i < amt; i++) {
+            size_t dest = i * stride + (count - 1);
+            if(dest >= origkeylen) {
+                break;
+            }
+            key[dest] = out[i];
+        }
+        keylen -= i;
+    }
+
+    /* zap */
+    _libssh2_explicit_zero(out, sizeof(out));
+    free(countsalt);
+
+    return 0;
+}
+#endif /* HAVE_BCRYPT_PBKDF */

+ 90 - 0
libssh2/libssh2/src/blf.h

@@ -0,0 +1,90 @@
+/* $OpenBSD: blf.h,v 1.7 2007/03/14 17:59:41 grunk Exp $ */
+/*
+ * Blowfish - a fast block cipher designed by Bruce Schneier
+ *
+ * Copyright 1997 Niels Provos <provos@physnet.uni-hamburg.de>
+ * 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. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *      This product includes software developed by Niels Provos.
+ * 4. 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 AUTHOR ``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 AUTHOR 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 _BLF_H_
+#define _BLF_H_
+
+#if !defined(HAVE_BCRYPT_PBKDF) && !defined(HAVE_BLH_H)
+
+/* Schneier specifies a maximum key length of 56 bytes.
+ * This ensures that every key bit affects every cipher
+ * bit.  However, the subkeys can hold up to 72 bytes.
+ * Warning: For normal blowfish encryption only 56 bytes
+ * of the key affect all cipherbits.
+ */
+
+#define BLF_N   16                      /* Number of Subkeys */
+#define BLF_MAXKEYLEN ((BLF_N-2)*4)     /* 448 bits */
+#define BLF_MAXUTILIZED ((BLF_N + 2)*4)   /* 576 bits */
+
+/* Blowfish context */
+typedef struct BlowfishContext {
+        uint32_t S[4][256];     /* S-Boxes */
+        uint32_t P[BLF_N + 2];  /* Subkeys */
+} blf_ctx;
+
+/* Raw access to customized Blowfish
+ *      blf_key is just:
+ *      Blowfish_initstate( state )
+ *      Blowfish_expand0state( state, key, keylen )
+ */
+
+void Blowfish_encipher(blf_ctx *, uint32_t *, uint32_t *);
+void Blowfish_decipher(blf_ctx *, uint32_t *, uint32_t *);
+void Blowfish_initstate(blf_ctx *);
+void Blowfish_expand0state(blf_ctx *, const uint8_t *, uint16_t);
+void Blowfish_expandstate
+(blf_ctx *, const uint8_t *, uint16_t, const uint8_t *, uint16_t);
+
+/* Standard Blowfish */
+
+void blf_key(blf_ctx *, const uint8_t *, uint16_t);
+void blf_enc(blf_ctx *, uint32_t *, uint16_t);
+void blf_dec(blf_ctx *, uint32_t *, uint16_t);
+
+void blf_ecb_encrypt(blf_ctx *, uint8_t *, uint32_t);
+void blf_ecb_decrypt(blf_ctx *, uint8_t *, uint32_t);
+
+void blf_cbc_encrypt(blf_ctx *, uint8_t *, uint8_t *, uint32_t);
+void blf_cbc_decrypt(blf_ctx *, uint8_t *, uint8_t *, uint32_t);
+
+/* Converts uint8_t to uint32_t */
+uint32_t Blowfish_stream2word(const uint8_t *, uint16_t, uint16_t *);
+
+/* bcrypt with pbkd */
+int bcrypt_pbkdf(const char *pass, size_t passlen, const uint8_t *salt,
+                 size_t saltlen,
+                 uint8_t *key, size_t keylen, unsigned int rounds);
+
+#endif /* !defined(HAVE_BCRYPT_PBKDF) && !defined(HAVE_BLH_H) */
+#endif /* _BLF_H */

+ 697 - 0
libssh2/libssh2/src/blowfish.c

@@ -0,0 +1,697 @@
+/* $OpenBSD: blowfish.c,v 1.18 2004/11/02 17:23:26 hshoexer Exp $ */
+/*
+ * Blowfish block cipher for OpenBSD
+ * Copyright 1997 Niels Provos <provos@physnet.uni-hamburg.de>
+ * All rights reserved.
+ *
+ * Implementation advice by David Mazieres <dm@lcs.mit.edu>.
+ *
+ * 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. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *      This product includes software developed by Niels Provos.
+ * 4. 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 AUTHOR ``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 AUTHOR 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.
+ */
+
+/*
+ * This code is derived from section 14.3 and the given source
+ * in section V of Applied Cryptography, second edition.
+ * Blowfish is an unpatented fast block cipher designed by
+ * Bruce Schneier.
+ */
+
+
+#if !defined(HAVE_BCRYPT_PBKDF) && (!defined(HAVE_BLOWFISH_INITSTATE) || \
+                                    !defined(HAVE_BLOWFISH_EXPAND0STATE) || \
+                                    !defined(HAVE_BLF_ENC))
+
+#if 0
+#include <stdio.h>              /* used for debugging */
+#include <string.h>
+#endif
+
+#include <sys/types.h>
+
+#include "libssh2.h"
+#include "blf.h"
+
+#undef inline
+#ifdef __GNUC__
+#define inline __inline
+#else                           /* !__GNUC__ */
+#define inline
+#endif                          /* !__GNUC__ */
+
+/* Function for Feistel Networks */
+
+#define F(s, x) ((((s)[        (((x)>>24)&0xFF)]        \
+                   + (s)[0x100 + (((x)>>16)&0xFF)])     \
+                  ^ (s)[0x200 + (((x)>> 8)&0xFF)])      \
+                 + (s)[0x300 + ( (x)     &0xFF)])
+
+#define BLFRND(s,p,i,j,n) (i ^= F(s,j) ^ (p)[n])
+
+void
+Blowfish_encipher(blf_ctx *c, uint32_t *xl, uint32_t *xr)
+{
+    uint32_t Xl;
+    uint32_t Xr;
+    uint32_t *s = c->S[0];
+    uint32_t *p = c->P;
+
+    Xl = *xl;
+    Xr = *xr;
+
+    Xl ^= p[0];
+    BLFRND(s, p, Xr, Xl, 1); BLFRND(s, p, Xl, Xr, 2);
+    BLFRND(s, p, Xr, Xl, 3); BLFRND(s, p, Xl, Xr, 4);
+    BLFRND(s, p, Xr, Xl, 5); BLFRND(s, p, Xl, Xr, 6);
+    BLFRND(s, p, Xr, Xl, 7); BLFRND(s, p, Xl, Xr, 8);
+    BLFRND(s, p, Xr, Xl, 9); BLFRND(s, p, Xl, Xr, 10);
+    BLFRND(s, p, Xr, Xl, 11); BLFRND(s, p, Xl, Xr, 12);
+    BLFRND(s, p, Xr, Xl, 13); BLFRND(s, p, Xl, Xr, 14);
+    BLFRND(s, p, Xr, Xl, 15); BLFRND(s, p, Xl, Xr, 16);
+
+    *xl = Xr ^ p[17];
+    *xr = Xl;
+}
+
+void
+Blowfish_decipher(blf_ctx *c, uint32_t *xl, uint32_t *xr)
+{
+    uint32_t Xl;
+    uint32_t Xr;
+    uint32_t *s = c->S[0];
+    uint32_t *p = c->P;
+
+    Xl = *xl;
+    Xr = *xr;
+
+    Xl ^= p[17];
+    BLFRND(s, p, Xr, Xl, 16); BLFRND(s, p, Xl, Xr, 15);
+    BLFRND(s, p, Xr, Xl, 14); BLFRND(s, p, Xl, Xr, 13);
+    BLFRND(s, p, Xr, Xl, 12); BLFRND(s, p, Xl, Xr, 11);
+    BLFRND(s, p, Xr, Xl, 10); BLFRND(s, p, Xl, Xr, 9);
+    BLFRND(s, p, Xr, Xl, 8); BLFRND(s, p, Xl, Xr, 7);
+    BLFRND(s, p, Xr, Xl, 6); BLFRND(s, p, Xl, Xr, 5);
+    BLFRND(s, p, Xr, Xl, 4); BLFRND(s, p, Xl, Xr, 3);
+    BLFRND(s, p, Xr, Xl, 2); BLFRND(s, p, Xl, Xr, 1);
+
+    *xl = Xr ^ p[0];
+    *xr = Xl;
+}
+
+void
+Blowfish_initstate(blf_ctx *c)
+{
+    /* P-box and S-box tables initialized with digits of Pi */
+
+    static const blf_ctx initstate =
+        { {
+                {
+                    0xd1310ba6, 0x98dfb5ac, 0x2ffd72db, 0xd01adfb7,
+                    0xb8e1afed, 0x6a267e96, 0xba7c9045, 0xf12c7f99,
+                    0x24a19947, 0xb3916cf7, 0x0801f2e2, 0x858efc16,
+                    0x636920d8, 0x71574e69, 0xa458fea3, 0xf4933d7e,
+                    0x0d95748f, 0x728eb658, 0x718bcd58, 0x82154aee,
+                    0x7b54a41d, 0xc25a59b5, 0x9c30d539, 0x2af26013,
+                    0xc5d1b023, 0x286085f0, 0xca417918, 0xb8db38ef,
+                    0x8e79dcb0, 0x603a180e, 0x6c9e0e8b, 0xb01e8a3e,
+                    0xd71577c1, 0xbd314b27, 0x78af2fda, 0x55605c60,
+                    0xe65525f3, 0xaa55ab94, 0x57489862, 0x63e81440,
+                    0x55ca396a, 0x2aab10b6, 0xb4cc5c34, 0x1141e8ce,
+                    0xa15486af, 0x7c72e993, 0xb3ee1411, 0x636fbc2a,
+                    0x2ba9c55d, 0x741831f6, 0xce5c3e16, 0x9b87931e,
+                    0xafd6ba33, 0x6c24cf5c, 0x7a325381, 0x28958677,
+                    0x3b8f4898, 0x6b4bb9af, 0xc4bfe81b, 0x66282193,
+                    0x61d809cc, 0xfb21a991, 0x487cac60, 0x5dec8032,
+                    0xef845d5d, 0xe98575b1, 0xdc262302, 0xeb651b88,
+                    0x23893e81, 0xd396acc5, 0x0f6d6ff3, 0x83f44239,
+                    0x2e0b4482, 0xa4842004, 0x69c8f04a, 0x9e1f9b5e,
+                    0x21c66842, 0xf6e96c9a, 0x670c9c61, 0xabd388f0,
+                    0x6a51a0d2, 0xd8542f68, 0x960fa728, 0xab5133a3,
+                    0x6eef0b6c, 0x137a3be4, 0xba3bf050, 0x7efb2a98,
+                    0xa1f1651d, 0x39af0176, 0x66ca593e, 0x82430e88,
+                    0x8cee8619, 0x456f9fb4, 0x7d84a5c3, 0x3b8b5ebe,
+                    0xe06f75d8, 0x85c12073, 0x401a449f, 0x56c16aa6,
+                    0x4ed3aa62, 0x363f7706, 0x1bfedf72, 0x429b023d,
+                    0x37d0d724, 0xd00a1248, 0xdb0fead3, 0x49f1c09b,
+                    0x075372c9, 0x80991b7b, 0x25d479d8, 0xf6e8def7,
+                    0xe3fe501a, 0xb6794c3b, 0x976ce0bd, 0x04c006ba,
+                    0xc1a94fb6, 0x409f60c4, 0x5e5c9ec2, 0x196a2463,
+                    0x68fb6faf, 0x3e6c53b5, 0x1339b2eb, 0x3b52ec6f,
+                    0x6dfc511f, 0x9b30952c, 0xcc814544, 0xaf5ebd09,
+                    0xbee3d004, 0xde334afd, 0x660f2807, 0x192e4bb3,
+                    0xc0cba857, 0x45c8740f, 0xd20b5f39, 0xb9d3fbdb,
+                    0x5579c0bd, 0x1a60320a, 0xd6a100c6, 0x402c7279,
+                    0x679f25fe, 0xfb1fa3cc, 0x8ea5e9f8, 0xdb3222f8,
+                    0x3c7516df, 0xfd616b15, 0x2f501ec8, 0xad0552ab,
+                    0x323db5fa, 0xfd238760, 0x53317b48, 0x3e00df82,
+                    0x9e5c57bb, 0xca6f8ca0, 0x1a87562e, 0xdf1769db,
+                    0xd542a8f6, 0x287effc3, 0xac6732c6, 0x8c4f5573,
+                    0x695b27b0, 0xbbca58c8, 0xe1ffa35d, 0xb8f011a0,
+                    0x10fa3d98, 0xfd2183b8, 0x4afcb56c, 0x2dd1d35b,
+                    0x9a53e479, 0xb6f84565, 0xd28e49bc, 0x4bfb9790,
+                    0xe1ddf2da, 0xa4cb7e33, 0x62fb1341, 0xcee4c6e8,
+                    0xef20cada, 0x36774c01, 0xd07e9efe, 0x2bf11fb4,
+                    0x95dbda4d, 0xae909198, 0xeaad8e71, 0x6b93d5a0,
+                    0xd08ed1d0, 0xafc725e0, 0x8e3c5b2f, 0x8e7594b7,
+                    0x8ff6e2fb, 0xf2122b64, 0x8888b812, 0x900df01c,
+                    0x4fad5ea0, 0x688fc31c, 0xd1cff191, 0xb3a8c1ad,
+                    0x2f2f2218, 0xbe0e1777, 0xea752dfe, 0x8b021fa1,
+                    0xe5a0cc0f, 0xb56f74e8, 0x18acf3d6, 0xce89e299,
+                    0xb4a84fe0, 0xfd13e0b7, 0x7cc43b81, 0xd2ada8d9,
+                    0x165fa266, 0x80957705, 0x93cc7314, 0x211a1477,
+                    0xe6ad2065, 0x77b5fa86, 0xc75442f5, 0xfb9d35cf,
+                    0xebcdaf0c, 0x7b3e89a0, 0xd6411bd3, 0xae1e7e49,
+                    0x00250e2d, 0x2071b35e, 0x226800bb, 0x57b8e0af,
+                    0x2464369b, 0xf009b91e, 0x5563911d, 0x59dfa6aa,
+                    0x78c14389, 0xd95a537f, 0x207d5ba2, 0x02e5b9c5,
+                    0x83260376, 0x6295cfa9, 0x11c81968, 0x4e734a41,
+                    0xb3472dca, 0x7b14a94a, 0x1b510052, 0x9a532915,
+                    0xd60f573f, 0xbc9bc6e4, 0x2b60a476, 0x81e67400,
+                    0x08ba6fb5, 0x571be91f, 0xf296ec6b, 0x2a0dd915,
+                    0xb6636521, 0xe7b9f9b6, 0xff34052e, 0xc5855664,
+                    0x53b02d5d, 0xa99f8fa1, 0x08ba4799, 0x6e85076a},
+                {
+                    0x4b7a70e9, 0xb5b32944, 0xdb75092e, 0xc4192623,
+                    0xad6ea6b0, 0x49a7df7d, 0x9cee60b8, 0x8fedb266,
+                    0xecaa8c71, 0x699a17ff, 0x5664526c, 0xc2b19ee1,
+                    0x193602a5, 0x75094c29, 0xa0591340, 0xe4183a3e,
+                    0x3f54989a, 0x5b429d65, 0x6b8fe4d6, 0x99f73fd6,
+                    0xa1d29c07, 0xefe830f5, 0x4d2d38e6, 0xf0255dc1,
+                    0x4cdd2086, 0x8470eb26, 0x6382e9c6, 0x021ecc5e,
+                    0x09686b3f, 0x3ebaefc9, 0x3c971814, 0x6b6a70a1,
+                    0x687f3584, 0x52a0e286, 0xb79c5305, 0xaa500737,
+                    0x3e07841c, 0x7fdeae5c, 0x8e7d44ec, 0x5716f2b8,
+                    0xb03ada37, 0xf0500c0d, 0xf01c1f04, 0x0200b3ff,
+                    0xae0cf51a, 0x3cb574b2, 0x25837a58, 0xdc0921bd,
+                    0xd19113f9, 0x7ca92ff6, 0x94324773, 0x22f54701,
+                    0x3ae5e581, 0x37c2dadc, 0xc8b57634, 0x9af3dda7,
+                    0xa9446146, 0x0fd0030e, 0xecc8c73e, 0xa4751e41,
+                    0xe238cd99, 0x3bea0e2f, 0x3280bba1, 0x183eb331,
+                    0x4e548b38, 0x4f6db908, 0x6f420d03, 0xf60a04bf,
+                    0x2cb81290, 0x24977c79, 0x5679b072, 0xbcaf89af,
+                    0xde9a771f, 0xd9930810, 0xb38bae12, 0xdccf3f2e,
+                    0x5512721f, 0x2e6b7124, 0x501adde6, 0x9f84cd87,
+                    0x7a584718, 0x7408da17, 0xbc9f9abc, 0xe94b7d8c,
+                    0xec7aec3a, 0xdb851dfa, 0x63094366, 0xc464c3d2,
+                    0xef1c1847, 0x3215d908, 0xdd433b37, 0x24c2ba16,
+                    0x12a14d43, 0x2a65c451, 0x50940002, 0x133ae4dd,
+                    0x71dff89e, 0x10314e55, 0x81ac77d6, 0x5f11199b,
+                    0x043556f1, 0xd7a3c76b, 0x3c11183b, 0x5924a509,
+                    0xf28fe6ed, 0x97f1fbfa, 0x9ebabf2c, 0x1e153c6e,
+                    0x86e34570, 0xeae96fb1, 0x860e5e0a, 0x5a3e2ab3,
+                    0x771fe71c, 0x4e3d06fa, 0x2965dcb9, 0x99e71d0f,
+                    0x803e89d6, 0x5266c825, 0x2e4cc978, 0x9c10b36a,
+                    0xc6150eba, 0x94e2ea78, 0xa5fc3c53, 0x1e0a2df4,
+                    0xf2f74ea7, 0x361d2b3d, 0x1939260f, 0x19c27960,
+                    0x5223a708, 0xf71312b6, 0xebadfe6e, 0xeac31f66,
+                    0xe3bc4595, 0xa67bc883, 0xb17f37d1, 0x018cff28,
+                    0xc332ddef, 0xbe6c5aa5, 0x65582185, 0x68ab9802,
+                    0xeecea50f, 0xdb2f953b, 0x2aef7dad, 0x5b6e2f84,
+                    0x1521b628, 0x29076170, 0xecdd4775, 0x619f1510,
+                    0x13cca830, 0xeb61bd96, 0x0334fe1e, 0xaa0363cf,
+                    0xb5735c90, 0x4c70a239, 0xd59e9e0b, 0xcbaade14,
+                    0xeecc86bc, 0x60622ca7, 0x9cab5cab, 0xb2f3846e,
+                    0x648b1eaf, 0x19bdf0ca, 0xa02369b9, 0x655abb50,
+                    0x40685a32, 0x3c2ab4b3, 0x319ee9d5, 0xc021b8f7,
+                    0x9b540b19, 0x875fa099, 0x95f7997e, 0x623d7da8,
+                    0xf837889a, 0x97e32d77, 0x11ed935f, 0x16681281,
+                    0x0e358829, 0xc7e61fd6, 0x96dedfa1, 0x7858ba99,
+                    0x57f584a5, 0x1b227263, 0x9b83c3ff, 0x1ac24696,
+                    0xcdb30aeb, 0x532e3054, 0x8fd948e4, 0x6dbc3128,
+                    0x58ebf2ef, 0x34c6ffea, 0xfe28ed61, 0xee7c3c73,
+                    0x5d4a14d9, 0xe864b7e3, 0x42105d14, 0x203e13e0,
+                    0x45eee2b6, 0xa3aaabea, 0xdb6c4f15, 0xfacb4fd0,
+                    0xc742f442, 0xef6abbb5, 0x654f3b1d, 0x41cd2105,
+                    0xd81e799e, 0x86854dc7, 0xe44b476a, 0x3d816250,
+                    0xcf62a1f2, 0x5b8d2646, 0xfc8883a0, 0xc1c7b6a3,
+                    0x7f1524c3, 0x69cb7492, 0x47848a0b, 0x5692b285,
+                    0x095bbf00, 0xad19489d, 0x1462b174, 0x23820e00,
+                    0x58428d2a, 0x0c55f5ea, 0x1dadf43e, 0x233f7061,
+                    0x3372f092, 0x8d937e41, 0xd65fecf1, 0x6c223bdb,
+                    0x7cde3759, 0xcbee7460, 0x4085f2a7, 0xce77326e,
+                    0xa6078084, 0x19f8509e, 0xe8efd855, 0x61d99735,
+                    0xa969a7aa, 0xc50c06c2, 0x5a04abfc, 0x800bcadc,
+                    0x9e447a2e, 0xc3453484, 0xfdd56705, 0x0e1e9ec9,
+                    0xdb73dbd3, 0x105588cd, 0x675fda79, 0xe3674340,
+                    0xc5c43465, 0x713e38d8, 0x3d28f89e, 0xf16dff20,
+                    0x153e21e7, 0x8fb03d4a, 0xe6e39f2b, 0xdb83adf7},
+                {
+                    0xe93d5a68, 0x948140f7, 0xf64c261c, 0x94692934,
+                    0x411520f7, 0x7602d4f7, 0xbcf46b2e, 0xd4a20068,
+                    0xd4082471, 0x3320f46a, 0x43b7d4b7, 0x500061af,
+                    0x1e39f62e, 0x97244546, 0x14214f74, 0xbf8b8840,
+                    0x4d95fc1d, 0x96b591af, 0x70f4ddd3, 0x66a02f45,
+                    0xbfbc09ec, 0x03bd9785, 0x7fac6dd0, 0x31cb8504,
+                    0x96eb27b3, 0x55fd3941, 0xda2547e6, 0xabca0a9a,
+                    0x28507825, 0x530429f4, 0x0a2c86da, 0xe9b66dfb,
+                    0x68dc1462, 0xd7486900, 0x680ec0a4, 0x27a18dee,
+                    0x4f3ffea2, 0xe887ad8c, 0xb58ce006, 0x7af4d6b6,
+                    0xaace1e7c, 0xd3375fec, 0xce78a399, 0x406b2a42,
+                    0x20fe9e35, 0xd9f385b9, 0xee39d7ab, 0x3b124e8b,
+                    0x1dc9faf7, 0x4b6d1856, 0x26a36631, 0xeae397b2,
+                    0x3a6efa74, 0xdd5b4332, 0x6841e7f7, 0xca7820fb,
+                    0xfb0af54e, 0xd8feb397, 0x454056ac, 0xba489527,
+                    0x55533a3a, 0x20838d87, 0xfe6ba9b7, 0xd096954b,
+                    0x55a867bc, 0xa1159a58, 0xcca92963, 0x99e1db33,
+                    0xa62a4a56, 0x3f3125f9, 0x5ef47e1c, 0x9029317c,
+                    0xfdf8e802, 0x04272f70, 0x80bb155c, 0x05282ce3,
+                    0x95c11548, 0xe4c66d22, 0x48c1133f, 0xc70f86dc,
+                    0x07f9c9ee, 0x41041f0f, 0x404779a4, 0x5d886e17,
+                    0x325f51eb, 0xd59bc0d1, 0xf2bcc18f, 0x41113564,
+                    0x257b7834, 0x602a9c60, 0xdff8e8a3, 0x1f636c1b,
+                    0x0e12b4c2, 0x02e1329e, 0xaf664fd1, 0xcad18115,
+                    0x6b2395e0, 0x333e92e1, 0x3b240b62, 0xeebeb922,
+                    0x85b2a20e, 0xe6ba0d99, 0xde720c8c, 0x2da2f728,
+                    0xd0127845, 0x95b794fd, 0x647d0862, 0xe7ccf5f0,
+                    0x5449a36f, 0x877d48fa, 0xc39dfd27, 0xf33e8d1e,
+                    0x0a476341, 0x992eff74, 0x3a6f6eab, 0xf4f8fd37,
+                    0xa812dc60, 0xa1ebddf8, 0x991be14c, 0xdb6e6b0d,
+                    0xc67b5510, 0x6d672c37, 0x2765d43b, 0xdcd0e804,
+                    0xf1290dc7, 0xcc00ffa3, 0xb5390f92, 0x690fed0b,
+                    0x667b9ffb, 0xcedb7d9c, 0xa091cf0b, 0xd9155ea3,
+                    0xbb132f88, 0x515bad24, 0x7b9479bf, 0x763bd6eb,
+                    0x37392eb3, 0xcc115979, 0x8026e297, 0xf42e312d,
+                    0x6842ada7, 0xc66a2b3b, 0x12754ccc, 0x782ef11c,
+                    0x6a124237, 0xb79251e7, 0x06a1bbe6, 0x4bfb6350,
+                    0x1a6b1018, 0x11caedfa, 0x3d25bdd8, 0xe2e1c3c9,
+                    0x44421659, 0x0a121386, 0xd90cec6e, 0xd5abea2a,
+                    0x64af674e, 0xda86a85f, 0xbebfe988, 0x64e4c3fe,
+                    0x9dbc8057, 0xf0f7c086, 0x60787bf8, 0x6003604d,
+                    0xd1fd8346, 0xf6381fb0, 0x7745ae04, 0xd736fccc,
+                    0x83426b33, 0xf01eab71, 0xb0804187, 0x3c005e5f,
+                    0x77a057be, 0xbde8ae24, 0x55464299, 0xbf582e61,
+                    0x4e58f48f, 0xf2ddfda2, 0xf474ef38, 0x8789bdc2,
+                    0x5366f9c3, 0xc8b38e74, 0xb475f255, 0x46fcd9b9,
+                    0x7aeb2661, 0x8b1ddf84, 0x846a0e79, 0x915f95e2,
+                    0x466e598e, 0x20b45770, 0x8cd55591, 0xc902de4c,
+                    0xb90bace1, 0xbb8205d0, 0x11a86248, 0x7574a99e,
+                    0xb77f19b6, 0xe0a9dc09, 0x662d09a1, 0xc4324633,
+                    0xe85a1f02, 0x09f0be8c, 0x4a99a025, 0x1d6efe10,
+                    0x1ab93d1d, 0x0ba5a4df, 0xa186f20f, 0x2868f169,
+                    0xdcb7da83, 0x573906fe, 0xa1e2ce9b, 0x4fcd7f52,
+                    0x50115e01, 0xa70683fa, 0xa002b5c4, 0x0de6d027,
+                    0x9af88c27, 0x773f8641, 0xc3604c06, 0x61a806b5,
+                    0xf0177a28, 0xc0f586e0, 0x006058aa, 0x30dc7d62,
+                    0x11e69ed7, 0x2338ea63, 0x53c2dd94, 0xc2c21634,
+                    0xbbcbee56, 0x90bcb6de, 0xebfc7da1, 0xce591d76,
+                    0x6f05e409, 0x4b7c0188, 0x39720a3d, 0x7c927c24,
+                    0x86e3725f, 0x724d9db9, 0x1ac15bb4, 0xd39eb8fc,
+                    0xed545578, 0x08fca5b5, 0xd83d7cd3, 0x4dad0fc4,
+                    0x1e50ef5e, 0xb161e6f8, 0xa28514d9, 0x6c51133c,
+                    0x6fd5c7e7, 0x56e14ec4, 0x362abfce, 0xddc6c837,
+                    0xd79a3234, 0x92638212, 0x670efa8e, 0x406000e0},
+                {
+                    0x3a39ce37, 0xd3faf5cf, 0xabc27737, 0x5ac52d1b,
+                    0x5cb0679e, 0x4fa33742, 0xd3822740, 0x99bc9bbe,
+                    0xd5118e9d, 0xbf0f7315, 0xd62d1c7e, 0xc700c47b,
+                    0xb78c1b6b, 0x21a19045, 0xb26eb1be, 0x6a366eb4,
+                    0x5748ab2f, 0xbc946e79, 0xc6a376d2, 0x6549c2c8,
+                    0x530ff8ee, 0x468dde7d, 0xd5730a1d, 0x4cd04dc6,
+                    0x2939bbdb, 0xa9ba4650, 0xac9526e8, 0xbe5ee304,
+                    0xa1fad5f0, 0x6a2d519a, 0x63ef8ce2, 0x9a86ee22,
+                    0xc089c2b8, 0x43242ef6, 0xa51e03aa, 0x9cf2d0a4,
+                    0x83c061ba, 0x9be96a4d, 0x8fe51550, 0xba645bd6,
+                    0x2826a2f9, 0xa73a3ae1, 0x4ba99586, 0xef5562e9,
+                    0xc72fefd3, 0xf752f7da, 0x3f046f69, 0x77fa0a59,
+                    0x80e4a915, 0x87b08601, 0x9b09e6ad, 0x3b3ee593,
+                    0xe990fd5a, 0x9e34d797, 0x2cf0b7d9, 0x022b8b51,
+                    0x96d5ac3a, 0x017da67d, 0xd1cf3ed6, 0x7c7d2d28,
+                    0x1f9f25cf, 0xadf2b89b, 0x5ad6b472, 0x5a88f54c,
+                    0xe029ac71, 0xe019a5e6, 0x47b0acfd, 0xed93fa9b,
+                    0xe8d3c48d, 0x283b57cc, 0xf8d56629, 0x79132e28,
+                    0x785f0191, 0xed756055, 0xf7960e44, 0xe3d35e8c,
+                    0x15056dd4, 0x88f46dba, 0x03a16125, 0x0564f0bd,
+                    0xc3eb9e15, 0x3c9057a2, 0x97271aec, 0xa93a072a,
+                    0x1b3f6d9b, 0x1e6321f5, 0xf59c66fb, 0x26dcf319,
+                    0x7533d928, 0xb155fdf5, 0x03563482, 0x8aba3cbb,
+                    0x28517711, 0xc20ad9f8, 0xabcc5167, 0xccad925f,
+                    0x4de81751, 0x3830dc8e, 0x379d5862, 0x9320f991,
+                    0xea7a90c2, 0xfb3e7bce, 0x5121ce64, 0x774fbe32,
+                    0xa8b6e37e, 0xc3293d46, 0x48de5369, 0x6413e680,
+                    0xa2ae0810, 0xdd6db224, 0x69852dfd, 0x09072166,
+                    0xb39a460a, 0x6445c0dd, 0x586cdecf, 0x1c20c8ae,
+                    0x5bbef7dd, 0x1b588d40, 0xccd2017f, 0x6bb4e3bb,
+                    0xdda26a7e, 0x3a59ff45, 0x3e350a44, 0xbcb4cdd5,
+                    0x72eacea8, 0xfa6484bb, 0x8d6612ae, 0xbf3c6f47,
+                    0xd29be463, 0x542f5d9e, 0xaec2771b, 0xf64e6370,
+                    0x740e0d8d, 0xe75b1357, 0xf8721671, 0xaf537d5d,
+                    0x4040cb08, 0x4eb4e2cc, 0x34d2466a, 0x0115af84,
+                    0xe1b00428, 0x95983a1d, 0x06b89fb4, 0xce6ea048,
+                    0x6f3f3b82, 0x3520ab82, 0x011a1d4b, 0x277227f8,
+                    0x611560b1, 0xe7933fdc, 0xbb3a792b, 0x344525bd,
+                    0xa08839e1, 0x51ce794b, 0x2f32c9b7, 0xa01fbac9,
+                    0xe01cc87e, 0xbcc7d1f6, 0xcf0111c3, 0xa1e8aac7,
+                    0x1a908749, 0xd44fbd9a, 0xd0dadecb, 0xd50ada38,
+                    0x0339c32a, 0xc6913667, 0x8df9317c, 0xe0b12b4f,
+                    0xf79e59b7, 0x43f5bb3a, 0xf2d519ff, 0x27d9459c,
+                    0xbf97222c, 0x15e6fc2a, 0x0f91fc71, 0x9b941525,
+                    0xfae59361, 0xceb69ceb, 0xc2a86459, 0x12baa8d1,
+                    0xb6c1075e, 0xe3056a0c, 0x10d25065, 0xcb03a442,
+                    0xe0ec6e0e, 0x1698db3b, 0x4c98a0be, 0x3278e964,
+                    0x9f1f9532, 0xe0d392df, 0xd3a0342b, 0x8971f21e,
+                    0x1b0a7441, 0x4ba3348c, 0xc5be7120, 0xc37632d8,
+                    0xdf359f8d, 0x9b992f2e, 0xe60b6f47, 0x0fe3f11d,
+                    0xe54cda54, 0x1edad891, 0xce6279cf, 0xcd3e7e6f,
+                    0x1618b166, 0xfd2c1d05, 0x848fd2c5, 0xf6fb2299,
+                    0xf523f357, 0xa6327623, 0x93a83531, 0x56cccd02,
+                    0xacf08162, 0x5a75ebb5, 0x6e163697, 0x88d273cc,
+                    0xde966292, 0x81b949d0, 0x4c50901b, 0x71c65614,
+                    0xe6c6c7bd, 0x327a140a, 0x45e1d006, 0xc3f27b9a,
+                    0xc9aa53fd, 0x62a80f00, 0xbb25bfe2, 0x35bdd2f6,
+                    0x71126905, 0xb2040222, 0xb6cbcf7c, 0xcd769c2b,
+                    0x53113ec0, 0x1640e3d3, 0x38abbd60, 0x2547adf0,
+                    0xba38209c, 0xf746ce76, 0x77afa1c5, 0x20756060,
+                    0x85cbfe4e, 0x8ae88dd8, 0x7aaaf9b0, 0x4cf9aa7e,
+                    0x1948c25c, 0x02fb8a8c, 0x01c36ae4, 0xd6ebe1f9,
+                    0x90d4f869, 0xa65cdea0, 0x3f09252d, 0xc208e69f,
+                    0xb74e6132, 0xce77e25b, 0x578fdfe3, 0x3ac372e6}
+            },
+          {
+              0x243f6a88, 0x85a308d3, 0x13198a2e, 0x03707344,
+              0xa4093822, 0x299f31d0, 0x082efa98, 0xec4e6c89,
+              0x452821e6, 0x38d01377, 0xbe5466cf, 0x34e90c6c,
+              0xc0ac29b7, 0xc97c50dd, 0x3f84d5b5, 0xb5470917,
+              0x9216d5d9, 0x8979fb1b
+          } };
+
+    *c = initstate;
+}
+
+uint32_t
+Blowfish_stream2word(const uint8_t *data, uint16_t databytes,
+                     uint16_t *current)
+{
+    uint8_t i;
+    uint16_t j;
+    uint32_t temp;
+
+    temp = 0x00000000;
+    j = *current;
+
+    for(i = 0; i < 4; i++, j++) {
+        if(j >= databytes)
+            j = 0;
+        temp = (temp << 8) | data[j];
+    }
+
+    *current = j;
+    return temp;
+}
+
+void
+Blowfish_expand0state(blf_ctx *c, const uint8_t *key, uint16_t keybytes)
+{
+    uint16_t i;
+    uint16_t j;
+    uint16_t k;
+    uint32_t temp;
+    uint32_t datal;
+    uint32_t datar;
+
+    j = 0;
+    for(i = 0; i < BLF_N + 2; i++) {
+        /* Extract 4 int8 to 1 int32 from keystream */
+        temp = Blowfish_stream2word(key, keybytes, &j);
+        c->P[i] = c->P[i] ^ temp;
+    }
+
+    j = 0;
+    datal = 0x00000000;
+    datar = 0x00000000;
+    for(i = 0; i < BLF_N + 2; i += 2) {
+        Blowfish_encipher(c, &datal, &datar);
+
+        c->P[i] = datal;
+        c->P[i + 1] = datar;
+    }
+
+    for(i = 0; i < 4; i++) {
+        for(k = 0; k < 256; k += 2) {
+            Blowfish_encipher(c, &datal, &datar);
+
+            c->S[i][k] = datal;
+            c->S[i][k + 1] = datar;
+        }
+    }
+}
+
+
+void
+Blowfish_expandstate(blf_ctx *c, const uint8_t *data, uint16_t databytes,
+                     const uint8_t *key, uint16_t keybytes)
+{
+    uint16_t i;
+    uint16_t j;
+    uint16_t k;
+    uint32_t temp;
+    uint32_t datal;
+    uint32_t datar;
+
+    j = 0;
+    for(i = 0; i < BLF_N + 2; i++) {
+        /* Extract 4 int8 to 1 int32 from keystream */
+        temp = Blowfish_stream2word(key, keybytes, &j);
+        c->P[i] = c->P[i] ^ temp;
+    }
+
+    j = 0;
+    datal = 0x00000000;
+    datar = 0x00000000;
+    for(i = 0; i < BLF_N + 2; i += 2) {
+        datal ^= Blowfish_stream2word(data, databytes, &j);
+        datar ^= Blowfish_stream2word(data, databytes, &j);
+        Blowfish_encipher(c, &datal, &datar);
+
+        c->P[i] = datal;
+        c->P[i + 1] = datar;
+    }
+
+    for(i = 0; i < 4; i++) {
+        for(k = 0; k < 256; k += 2) {
+            datal ^= Blowfish_stream2word(data, databytes, &j);
+            datar ^= Blowfish_stream2word(data, databytes, &j);
+            Blowfish_encipher(c, &datal, &datar);
+
+            c->S[i][k] = datal;
+            c->S[i][k + 1] = datar;
+        }
+    }
+
+}
+
+void
+blf_key(blf_ctx *c, const uint8_t *k, uint16_t len)
+{
+    /* Initialize S-boxes and subkeys with Pi */
+    Blowfish_initstate(c);
+
+    /* Transform S-boxes and subkeys with key */
+    Blowfish_expand0state(c, k, len);
+}
+
+void
+blf_enc(blf_ctx *c, uint32_t *data, uint16_t blocks)
+{
+    uint32_t *d;
+    uint16_t i;
+
+    d = data;
+    for(i = 0; i < blocks; i++) {
+        Blowfish_encipher(c, d, d + 1);
+        d += 2;
+    }
+}
+
+void
+blf_dec(blf_ctx *c, uint32_t *data, uint16_t blocks)
+{
+    uint32_t *d;
+    uint16_t i;
+
+    d = data;
+    for(i = 0; i < blocks; i++) {
+        Blowfish_decipher(c, d, d + 1);
+        d += 2;
+    }
+}
+
+void
+blf_ecb_encrypt(blf_ctx *c, uint8_t *data, uint32_t len)
+{
+    uint32_t l, r;
+    uint32_t i;
+
+    for(i = 0; i < len; i += 8) {
+        l = data[0] << 24 | data[1] << 16 | data[2] << 8 | data[3];
+        r = data[4] << 24 | data[5] << 16 | data[6] << 8 | data[7];
+        Blowfish_encipher(c, &l, &r);
+        data[0] = l >> 24 & 0xff;
+        data[1] = l >> 16 & 0xff;
+        data[2] = l >> 8 & 0xff;
+        data[3] = l & 0xff;
+        data[4] = r >> 24 & 0xff;
+        data[5] = r >> 16 & 0xff;
+        data[6] = r >> 8 & 0xff;
+        data[7] = r & 0xff;
+        data += 8;
+    }
+}
+
+void
+blf_ecb_decrypt(blf_ctx *c, uint8_t *data, uint32_t len)
+{
+    uint32_t l, r;
+    uint32_t i;
+
+    for(i = 0; i < len; i += 8) {
+        l = data[0] << 24 | data[1] << 16 | data[2] << 8 | data[3];
+        r = data[4] << 24 | data[5] << 16 | data[6] << 8 | data[7];
+        Blowfish_decipher(c, &l, &r);
+        data[0] = l >> 24 & 0xff;
+        data[1] = l >> 16 & 0xff;
+        data[2] = l >> 8 & 0xff;
+        data[3] = l & 0xff;
+        data[4] = r >> 24 & 0xff;
+        data[5] = r >> 16 & 0xff;
+        data[6] = r >> 8 & 0xff;
+        data[7] = r & 0xff;
+        data += 8;
+    }
+}
+
+void
+blf_cbc_encrypt(blf_ctx *c, uint8_t *iv, uint8_t *data, uint32_t len)
+{
+    uint32_t l, r;
+    uint32_t i, j;
+
+    for(i = 0; i < len; i += 8) {
+        for(j = 0; j < 8; j++)
+            data[j] ^= iv[j];
+        l = data[0] << 24 | data[1] << 16 | data[2] << 8 | data[3];
+        r = data[4] << 24 | data[5] << 16 | data[6] << 8 | data[7];
+        Blowfish_encipher(c, &l, &r);
+        data[0] = l >> 24 & 0xff;
+        data[1] = l >> 16 & 0xff;
+        data[2] = l >> 8 & 0xff;
+        data[3] = l & 0xff;
+        data[4] = r >> 24 & 0xff;
+        data[5] = r >> 16 & 0xff;
+        data[6] = r >> 8 & 0xff;
+        data[7] = r & 0xff;
+        iv = data;
+        data += 8;
+    }
+}
+
+void
+blf_cbc_decrypt(blf_ctx *c, uint8_t *iva, uint8_t *data, uint32_t len)
+{
+    uint32_t l, r;
+    uint8_t *iv;
+    uint32_t i, j;
+
+    iv = data + len - 16;
+    data = data + len - 8;
+    for(i = len - 8; i >= 8; i -= 8) {
+        l = data[0] << 24 | data[1] << 16 | data[2] << 8 | data[3];
+        r = data[4] << 24 | data[5] << 16 | data[6] << 8 | data[7];
+        Blowfish_decipher(c, &l, &r);
+        data[0] = l >> 24 & 0xff;
+        data[1] = l >> 16 & 0xff;
+        data[2] = l >> 8 & 0xff;
+        data[3] = l & 0xff;
+        data[4] = r >> 24 & 0xff;
+        data[5] = r >> 16 & 0xff;
+        data[6] = r >> 8 & 0xff;
+        data[7] = r & 0xff;
+        for(j = 0; j < 8; j++)
+            data[j] ^= iv[j];
+        iv -= 8;
+        data -= 8;
+    }
+    l = data[0] << 24 | data[1] << 16 | data[2] << 8 | data[3];
+    r = data[4] << 24 | data[5] << 16 | data[6] << 8 | data[7];
+    Blowfish_decipher(c, &l, &r);
+    data[0] = l >> 24 & 0xff;
+    data[1] = l >> 16 & 0xff;
+    data[2] = l >> 8 & 0xff;
+    data[3] = l & 0xff;
+    data[4] = r >> 24 & 0xff;
+    data[5] = r >> 16 & 0xff;
+    data[6] = r >> 8 & 0xff;
+    data[7] = r & 0xff;
+    for(j = 0; j < 8; j++)
+        data[j] ^= iva[j];
+}
+
+#if 0
+void
+report(uint32_t data[], uint16_t len)
+{
+    uint16_t i;
+    for(i = 0; i < len; i += 2)
+        printf("Block %0hd: %08lx %08lx.\n",
+               i / 2, data[i], data[i + 1]);
+}
+void
+main(void)
+{
+
+    blf_ctx c;
+    char    key[] = "AAAAA";
+    char    key2[] = "abcdefghijklmnopqrstuvwxyz";
+
+    uint32_t data[10];
+    uint32_t data2[] =
+        {0x424c4f57l, 0x46495348l};
+
+    uint16_t i;
+
+    /* First test */
+    for(i = 0; i < 10; i++)
+        data[i] = i;
+
+    blf_key(&c, (uint8_t *) key, 5);
+    blf_enc(&c, data, 5);
+    blf_dec(&c, data, 1);
+    blf_dec(&c, data + 2, 4);
+    printf("Should read as 0 - 9.\n");
+    report(data, 10);
+
+    /* Second test */
+    blf_key(&c, (uint8_t *) key2, strlen(key2));
+    blf_enc(&c, data2, 1);
+    printf("\nShould read as: 0x324ed0fe 0xf413a203.\n");
+    report(data2, 2);
+    blf_dec(&c, data2, 1);
+    report(data2, 2);
+}
+#endif
+
+#endif /* !defined(HAVE_BCRYPT_PBKDF) && \
+          (!defined(HAVE_BLOWFISH_INITSTATE) ||   \
+          !defined(HAVE_BLOWFISH_EXPAND0STATE) || \
+          '!defined(HAVE_BLF_ENC)) */

+ 2738 - 0
libssh2/libssh2/src/channel.c

@@ -0,0 +1,2738 @@
+/* Copyright (c) 2004-2007 Sara Golemon <sarag@libssh2.org>
+ * Copyright (c) 2005 Mikhail Gusarov <dottedmag@dottedmag.net>
+ * Copyright (c) 2008-2019 by Daniel Stenberg
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms,
+ * with or without modification, are permitted provided
+ * that the following conditions are met:
+ *
+ *   Redistributions of source code must retain the above
+ *   copyright notice, this list of conditions and the
+ *   following disclaimer.
+ *
+ *   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.
+ *
+ *   Neither the name of the copyright holder nor the names
+ *   of any other contributors may be used to endorse or
+ *   promote products derived from this software without
+ *   specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+ * CONTRIBUTORS "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 COPYRIGHT OWNER OR
+ * CONTRIBUTORS 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 "libssh2_priv.h"
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#include <fcntl.h>
+#ifdef HAVE_INTTYPES_H
+#include <inttypes.h>
+#endif
+#include <assert.h>
+
+#include "channel.h"
+#include "transport.h"
+#include "packet.h"
+#include "session.h"
+
+/*
+ *  _libssh2_channel_nextid
+ *
+ * Determine the next channel ID we can use at our end
+ */
+uint32_t
+_libssh2_channel_nextid(LIBSSH2_SESSION * session)
+{
+    uint32_t id = session->next_channel;
+    LIBSSH2_CHANNEL *channel;
+
+    channel = _libssh2_list_first(&session->channels);
+
+    while(channel) {
+        if(channel->local.id > id) {
+            id = channel->local.id;
+        }
+        channel = _libssh2_list_next(&channel->node);
+    }
+
+    /* This is a shortcut to avoid waiting for close packets on channels we've
+     * forgotten about, This *could* be a problem if we request and close 4
+     * billion or so channels in too rapid succession for the remote end to
+     * respond, but the worst case scenario is that some data meant for
+     * another channel Gets picked up by the new one.... Pretty unlikely all
+     * told...
+     */
+    session->next_channel = id + 1;
+    _libssh2_debug(session, LIBSSH2_TRACE_CONN, "Allocated new channel ID#%lu",
+                   id);
+    return id;
+}
+
+/*
+ * _libssh2_channel_locate
+ *
+ * Locate a channel pointer by number
+ */
+LIBSSH2_CHANNEL *
+_libssh2_channel_locate(LIBSSH2_SESSION *session, uint32_t channel_id)
+{
+    LIBSSH2_CHANNEL *channel;
+    LIBSSH2_LISTENER *l;
+
+    for(channel = _libssh2_list_first(&session->channels);
+        channel;
+        channel = _libssh2_list_next(&channel->node)) {
+        if(channel->local.id == channel_id)
+            return channel;
+    }
+
+    /* We didn't find the channel in the session, let's then check its
+       listeners since each listener may have its own set of pending channels
+    */
+    for(l = _libssh2_list_first(&session->listeners); l;
+        l = _libssh2_list_next(&l->node)) {
+        for(channel = _libssh2_list_first(&l->queue);
+            channel;
+            channel = _libssh2_list_next(&channel->node)) {
+            if(channel->local.id == channel_id)
+                return channel;
+        }
+    }
+
+    return NULL;
+}
+
+/*
+ * _libssh2_channel_open
+ *
+ * Establish a generic session channel
+ */
+LIBSSH2_CHANNEL *
+_libssh2_channel_open(LIBSSH2_SESSION * session, const char *channel_type,
+                      uint32_t channel_type_len,
+                      uint32_t window_size,
+                      uint32_t packet_size,
+                      const unsigned char *message,
+                      size_t message_len)
+{
+    static const unsigned char reply_codes[3] = {
+        SSH_MSG_CHANNEL_OPEN_CONFIRMATION,
+        SSH_MSG_CHANNEL_OPEN_FAILURE,
+        0
+    };
+    unsigned char *s;
+    int rc;
+
+    if(session->open_state == libssh2_NB_state_idle) {
+        session->open_channel = NULL;
+        session->open_packet = NULL;
+        session->open_data = NULL;
+        /* 17 = packet_type(1) + channel_type_len(4) + sender_channel(4) +
+         * window_size(4) + packet_size(4) */
+        session->open_packet_len = channel_type_len + 17;
+        session->open_local_channel = _libssh2_channel_nextid(session);
+
+        /* Zero the whole thing out */
+        memset(&session->open_packet_requirev_state, 0,
+               sizeof(session->open_packet_requirev_state));
+
+        _libssh2_debug(session, LIBSSH2_TRACE_CONN,
+                       "Opening Channel - win %d pack %d", window_size,
+                       packet_size);
+        session->open_channel =
+            LIBSSH2_CALLOC(session, sizeof(LIBSSH2_CHANNEL));
+        if(!session->open_channel) {
+            _libssh2_error(session, LIBSSH2_ERROR_ALLOC,
+                           "Unable to allocate space for channel data");
+            return NULL;
+        }
+        session->open_channel->channel_type_len = channel_type_len;
+        session->open_channel->channel_type =
+            LIBSSH2_ALLOC(session, channel_type_len);
+        if(!session->open_channel->channel_type) {
+            _libssh2_error(session, LIBSSH2_ERROR_ALLOC,
+                           "Failed allocating memory for channel type name");
+            LIBSSH2_FREE(session, session->open_channel);
+            session->open_channel = NULL;
+            return NULL;
+        }
+        memcpy(session->open_channel->channel_type, channel_type,
+               channel_type_len);
+
+        /* REMEMBER: local as in locally sourced */
+        session->open_channel->local.id = session->open_local_channel;
+        session->open_channel->remote.window_size = window_size;
+        session->open_channel->remote.window_size_initial = window_size;
+        session->open_channel->remote.packet_size = packet_size;
+        session->open_channel->session = session;
+
+        _libssh2_list_add(&session->channels,
+                          &session->open_channel->node);
+
+        s = session->open_packet =
+            LIBSSH2_ALLOC(session, session->open_packet_len);
+        if(!session->open_packet) {
+            _libssh2_error(session, LIBSSH2_ERROR_ALLOC,
+                           "Unable to allocate temporary space for packet");
+            goto channel_error;
+        }
+        *(s++) = SSH_MSG_CHANNEL_OPEN;
+        _libssh2_store_str(&s, channel_type, channel_type_len);
+        _libssh2_store_u32(&s, session->open_local_channel);
+        _libssh2_store_u32(&s, window_size);
+        _libssh2_store_u32(&s, packet_size);
+
+        /* Do not copy the message */
+
+        session->open_state = libssh2_NB_state_created;
+    }
+
+    if(session->open_state == libssh2_NB_state_created) {
+        rc = _libssh2_transport_send(session,
+                                     session->open_packet,
+                                     session->open_packet_len,
+                                     message, message_len);
+        if(rc == LIBSSH2_ERROR_EAGAIN) {
+            _libssh2_error(session, rc,
+                           "Would block sending channel-open request");
+            return NULL;
+        }
+        else if(rc) {
+            _libssh2_error(session, rc,
+                           "Unable to send channel-open request");
+            goto channel_error;
+        }
+
+        session->open_state = libssh2_NB_state_sent;
+    }
+
+    if(session->open_state == libssh2_NB_state_sent) {
+        rc = _libssh2_packet_requirev(session, reply_codes,
+                                      &session->open_data,
+                                      &session->open_data_len, 1,
+                                      session->open_packet + 5 +
+                                      channel_type_len, 4,
+                                      &session->open_packet_requirev_state);
+        if(rc == LIBSSH2_ERROR_EAGAIN) {
+            _libssh2_error(session, LIBSSH2_ERROR_EAGAIN, "Would block");
+            return NULL;
+        }
+        else if(rc) {
+            goto channel_error;
+        }
+
+        if(session->open_data_len < 1) {
+            _libssh2_error(session, LIBSSH2_ERROR_PROTO,
+                           "Unexpected packet size");
+            goto channel_error;
+        }
+
+        if(session->open_data[0] == SSH_MSG_CHANNEL_OPEN_CONFIRMATION) {
+
+            if(session->open_data_len < 17) {
+                _libssh2_error(session, LIBSSH2_ERROR_PROTO,
+                               "Unexpected packet size");
+                goto channel_error;
+            }
+
+            session->open_channel->remote.id =
+                _libssh2_ntohu32(session->open_data + 5);
+            session->open_channel->local.window_size =
+                _libssh2_ntohu32(session->open_data + 9);
+            session->open_channel->local.window_size_initial =
+                _libssh2_ntohu32(session->open_data + 9);
+            session->open_channel->local.packet_size =
+                _libssh2_ntohu32(session->open_data + 13);
+            _libssh2_debug(session, LIBSSH2_TRACE_CONN,
+                           "Connection Established - ID: %lu/%lu win: %lu/%lu"
+                           " pack: %lu/%lu",
+                           session->open_channel->local.id,
+                           session->open_channel->remote.id,
+                           session->open_channel->local.window_size,
+                           session->open_channel->remote.window_size,
+                           session->open_channel->local.packet_size,
+                           session->open_channel->remote.packet_size);
+            LIBSSH2_FREE(session, session->open_packet);
+            session->open_packet = NULL;
+            LIBSSH2_FREE(session, session->open_data);
+            session->open_data = NULL;
+
+            session->open_state = libssh2_NB_state_idle;
+            return session->open_channel;
+        }
+
+        if(session->open_data[0] == SSH_MSG_CHANNEL_OPEN_FAILURE) {
+            unsigned int reason_code =
+                _libssh2_ntohu32(session->open_data + 5);
+            switch(reason_code) {
+            case SSH_OPEN_ADMINISTRATIVELY_PROHIBITED:
+                _libssh2_error(session, LIBSSH2_ERROR_CHANNEL_FAILURE,
+                               "Channel open failure "
+                               "(administratively prohibited)");
+                break;
+            case SSH_OPEN_CONNECT_FAILED:
+                _libssh2_error(session, LIBSSH2_ERROR_CHANNEL_FAILURE,
+                               "Channel open failure (connect failed)");
+                break;
+            case SSH_OPEN_UNKNOWN_CHANNELTYPE:
+                _libssh2_error(session, LIBSSH2_ERROR_CHANNEL_FAILURE,
+                               "Channel open failure (unknown channel type)");
+                break;
+            case SSH_OPEN_RESOURCE_SHORTAGE:
+                _libssh2_error(session, LIBSSH2_ERROR_CHANNEL_FAILURE,
+                               "Channel open failure (resource shortage)");
+                break;
+            default:
+                _libssh2_error(session, LIBSSH2_ERROR_CHANNEL_FAILURE,
+                               "Channel open failure");
+            }
+        }
+    }
+
+  channel_error:
+
+    if(session->open_data) {
+        LIBSSH2_FREE(session, session->open_data);
+        session->open_data = NULL;
+    }
+    if(session->open_packet) {
+        LIBSSH2_FREE(session, session->open_packet);
+        session->open_packet = NULL;
+    }
+    if(session->open_channel) {
+        unsigned char channel_id[4];
+        LIBSSH2_FREE(session, session->open_channel->channel_type);
+
+        _libssh2_list_remove(&session->open_channel->node);
+
+        /* Clear out packets meant for this channel */
+        _libssh2_htonu32(channel_id, session->open_channel->local.id);
+        while((_libssh2_packet_ask(session, SSH_MSG_CHANNEL_DATA,
+                                    &session->open_data,
+                                    &session->open_data_len, 1,
+                                    channel_id, 4) >= 0)
+               ||
+               (_libssh2_packet_ask(session, SSH_MSG_CHANNEL_EXTENDED_DATA,
+                                    &session->open_data,
+                                    &session->open_data_len, 1,
+                                    channel_id, 4) >= 0)) {
+            LIBSSH2_FREE(session, session->open_data);
+            session->open_data = NULL;
+        }
+
+        LIBSSH2_FREE(session, session->open_channel);
+        session->open_channel = NULL;
+    }
+
+    session->open_state = libssh2_NB_state_idle;
+    return NULL;
+}
+
+/*
+ * libssh2_channel_open_ex
+ *
+ * Establish a generic session channel
+ */
+LIBSSH2_API LIBSSH2_CHANNEL *
+libssh2_channel_open_ex(LIBSSH2_SESSION *session, const char *type,
+                        unsigned int type_len,
+                        unsigned int window_size, unsigned int packet_size,
+                        const char *msg, unsigned int msg_len)
+{
+    LIBSSH2_CHANNEL *ptr;
+
+    if(!session)
+        return NULL;
+
+    BLOCK_ADJUST_ERRNO(ptr, session,
+                       _libssh2_channel_open(session, type, type_len,
+                                             window_size, packet_size,
+                                             (unsigned char *)msg,
+                                             msg_len));
+    return ptr;
+}
+
+/*
+ * libssh2_channel_direct_tcpip_ex
+ *
+ * Tunnel TCP/IP connect through the SSH session to direct host/port
+ */
+static LIBSSH2_CHANNEL *
+channel_direct_tcpip(LIBSSH2_SESSION * session, const char *host,
+                     int port, const char *shost, int sport)
+{
+    LIBSSH2_CHANNEL *channel;
+    unsigned char *s;
+
+    if(session->direct_state == libssh2_NB_state_idle) {
+        session->direct_host_len = strlen(host);
+        session->direct_shost_len = strlen(shost);
+        /* host_len(4) + port(4) + shost_len(4) + sport(4) */
+        session->direct_message_len =
+            session->direct_host_len + session->direct_shost_len + 16;
+
+        _libssh2_debug(session, LIBSSH2_TRACE_CONN,
+                       "Requesting direct-tcpip session from %s:%d to %s:%d",
+                       shost, sport, host, port);
+
+        s = session->direct_message =
+            LIBSSH2_ALLOC(session, session->direct_message_len);
+        if(!session->direct_message) {
+            _libssh2_error(session, LIBSSH2_ERROR_ALLOC,
+                           "Unable to allocate memory for "
+                           "direct-tcpip connection");
+            return NULL;
+        }
+        _libssh2_store_str(&s, host, session->direct_host_len);
+        _libssh2_store_u32(&s, port);
+        _libssh2_store_str(&s, shost, session->direct_shost_len);
+        _libssh2_store_u32(&s, sport);
+    }
+
+    channel =
+        _libssh2_channel_open(session, "direct-tcpip",
+                              sizeof("direct-tcpip") - 1,
+                              LIBSSH2_CHANNEL_WINDOW_DEFAULT,
+                              LIBSSH2_CHANNEL_PACKET_DEFAULT,
+                              session->direct_message,
+                              session->direct_message_len);
+
+    if(!channel &&
+        libssh2_session_last_errno(session) == LIBSSH2_ERROR_EAGAIN) {
+        /* The error code is still set to LIBSSH2_ERROR_EAGAIN, set our state
+           to created to avoid re-creating the package on next invoke */
+        session->direct_state = libssh2_NB_state_created;
+        return NULL;
+    }
+    /* by default we set (keep?) idle state... */
+    session->direct_state = libssh2_NB_state_idle;
+
+    LIBSSH2_FREE(session, session->direct_message);
+    session->direct_message = NULL;
+
+    return channel;
+}
+
+/*
+ * libssh2_channel_direct_tcpip_ex
+ *
+ * Tunnel TCP/IP connect through the SSH session to direct host/port
+ */
+LIBSSH2_API LIBSSH2_CHANNEL *
+libssh2_channel_direct_tcpip_ex(LIBSSH2_SESSION *session, const char *host,
+                                int port, const char *shost, int sport)
+{
+    LIBSSH2_CHANNEL *ptr;
+
+    if(!session)
+        return NULL;
+
+    BLOCK_ADJUST_ERRNO(ptr, session,
+                       channel_direct_tcpip(session, host, port,
+                                            shost, sport));
+    return ptr;
+}
+
+/*
+ * channel_forward_listen
+ *
+ * Bind a port on the remote host and listen for connections
+ */
+static LIBSSH2_LISTENER *
+channel_forward_listen(LIBSSH2_SESSION * session, const char *host,
+                       int port, int *bound_port, int queue_maxsize)
+{
+    unsigned char *s;
+    static const unsigned char reply_codes[3] =
+        { SSH_MSG_REQUEST_SUCCESS, SSH_MSG_REQUEST_FAILURE, 0 };
+    int rc;
+
+    if(!host)
+        host = "0.0.0.0";
+
+    if(session->fwdLstn_state == libssh2_NB_state_idle) {
+        session->fwdLstn_host_len = strlen(host);
+        /* 14 = packet_type(1) + request_len(4) + want_replay(1) + host_len(4)
+           + port(4) */
+        session->fwdLstn_packet_len =
+            session->fwdLstn_host_len + (sizeof("tcpip-forward") - 1) + 14;
+
+        /* Zero the whole thing out */
+        memset(&session->fwdLstn_packet_requirev_state, 0,
+               sizeof(session->fwdLstn_packet_requirev_state));
+
+        _libssh2_debug(session, LIBSSH2_TRACE_CONN,
+                       "Requesting tcpip-forward session for %s:%d", host,
+                       port);
+
+        s = session->fwdLstn_packet =
+            LIBSSH2_ALLOC(session, session->fwdLstn_packet_len);
+        if(!session->fwdLstn_packet) {
+            _libssh2_error(session, LIBSSH2_ERROR_ALLOC,
+                           "Unable to allocate memory for setenv packet");
+            return NULL;
+        }
+
+        *(s++) = SSH_MSG_GLOBAL_REQUEST;
+        _libssh2_store_str(&s, "tcpip-forward", sizeof("tcpip-forward") - 1);
+        *(s++) = 0x01;          /* want_reply */
+
+        _libssh2_store_str(&s, host, session->fwdLstn_host_len);
+        _libssh2_store_u32(&s, port);
+
+        session->fwdLstn_state = libssh2_NB_state_created;
+    }
+
+    if(session->fwdLstn_state == libssh2_NB_state_created) {
+        rc = _libssh2_transport_send(session,
+                                     session->fwdLstn_packet,
+                                     session->fwdLstn_packet_len,
+                                     NULL, 0);
+        if(rc == LIBSSH2_ERROR_EAGAIN) {
+            _libssh2_error(session, LIBSSH2_ERROR_EAGAIN,
+                           "Would block sending global-request packet for "
+                           "forward listen request");
+            return NULL;
+        }
+        else if(rc) {
+            _libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND,
+                           "Unable to send global-request packet for forward "
+                           "listen request");
+            LIBSSH2_FREE(session, session->fwdLstn_packet);
+            session->fwdLstn_packet = NULL;
+            session->fwdLstn_state = libssh2_NB_state_idle;
+            return NULL;
+        }
+        LIBSSH2_FREE(session, session->fwdLstn_packet);
+        session->fwdLstn_packet = NULL;
+
+        session->fwdLstn_state = libssh2_NB_state_sent;
+    }
+
+    if(session->fwdLstn_state == libssh2_NB_state_sent) {
+        unsigned char *data;
+        size_t data_len;
+        rc = _libssh2_packet_requirev(session, reply_codes, &data, &data_len,
+                                      0, NULL, 0,
+                                      &session->fwdLstn_packet_requirev_state);
+        if(rc == LIBSSH2_ERROR_EAGAIN) {
+            _libssh2_error(session, LIBSSH2_ERROR_EAGAIN, "Would block");
+            return NULL;
+        }
+        else if(rc || (data_len < 1)) {
+            _libssh2_error(session, LIBSSH2_ERROR_PROTO, "Unknown");
+            session->fwdLstn_state = libssh2_NB_state_idle;
+            return NULL;
+        }
+
+        if(data[0] == SSH_MSG_REQUEST_SUCCESS) {
+            LIBSSH2_LISTENER *listener;
+
+            listener = LIBSSH2_CALLOC(session, sizeof(LIBSSH2_LISTENER));
+            if(!listener)
+                _libssh2_error(session, LIBSSH2_ERROR_ALLOC,
+                               "Unable to allocate memory for listener queue");
+            else {
+                listener->host =
+                    LIBSSH2_ALLOC(session, session->fwdLstn_host_len + 1);
+                if(!listener->host) {
+                    _libssh2_error(session, LIBSSH2_ERROR_ALLOC,
+                                   "Unable to allocate memory "
+                                   "for listener queue");
+                    LIBSSH2_FREE(session, listener);
+                    listener = NULL;
+                }
+                else {
+                    listener->session = session;
+                    memcpy(listener->host, host, session->fwdLstn_host_len);
+                    listener->host[session->fwdLstn_host_len] = 0;
+                    if(data_len >= 5 && !port) {
+                        listener->port = _libssh2_ntohu32(data + 1);
+                        _libssh2_debug(session, LIBSSH2_TRACE_CONN,
+                                       "Dynamic tcpip-forward port "
+                                       "allocated: %d",
+                                       listener->port);
+                    }
+                    else
+                        listener->port = port;
+
+                    listener->queue_size = 0;
+                    listener->queue_maxsize = queue_maxsize;
+
+                    /* append this to the parent's list of listeners */
+                    _libssh2_list_add(&session->listeners, &listener->node);
+
+                    if(bound_port) {
+                        *bound_port = listener->port;
+                    }
+                }
+            }
+
+            LIBSSH2_FREE(session, data);
+            session->fwdLstn_state = libssh2_NB_state_idle;
+            return listener;
+        }
+        else if(data[0] == SSH_MSG_REQUEST_FAILURE) {
+            LIBSSH2_FREE(session, data);
+            _libssh2_error(session, LIBSSH2_ERROR_REQUEST_DENIED,
+                           "Unable to complete request for forward-listen");
+            session->fwdLstn_state = libssh2_NB_state_idle;
+            return NULL;
+        }
+    }
+
+    session->fwdLstn_state = libssh2_NB_state_idle;
+
+    return NULL;
+}
+
+/*
+ * libssh2_channel_forward_listen_ex
+ *
+ * Bind a port on the remote host and listen for connections
+ */
+LIBSSH2_API LIBSSH2_LISTENER *
+libssh2_channel_forward_listen_ex(LIBSSH2_SESSION *session, const char *host,
+                                  int port, int *bound_port, int queue_maxsize)
+{
+    LIBSSH2_LISTENER *ptr;
+
+    if(!session)
+        return NULL;
+
+    BLOCK_ADJUST_ERRNO(ptr, session,
+                       channel_forward_listen(session, host, port, bound_port,
+                                              queue_maxsize));
+    return ptr;
+}
+
+/*
+ * _libssh2_channel_forward_cancel
+ *
+ * Stop listening on a remote port and free the listener
+ * Toss out any pending (un-accept()ed) connections
+ *
+ * Return 0 on success, LIBSSH2_ERROR_EAGAIN if would block, -1 on error
+ */
+int _libssh2_channel_forward_cancel(LIBSSH2_LISTENER *listener)
+{
+    LIBSSH2_SESSION *session = listener->session;
+    LIBSSH2_CHANNEL *queued;
+    unsigned char *packet, *s;
+    size_t host_len = strlen(listener->host);
+    /* 14 = packet_type(1) + request_len(4) + want_replay(1) + host_len(4) +
+       port(4) */
+    size_t packet_len =
+        host_len + 14 + sizeof("cancel-tcpip-forward") - 1;
+    int rc;
+    int retcode = 0;
+
+    if(listener->chanFwdCncl_state == libssh2_NB_state_idle) {
+        _libssh2_debug(session, LIBSSH2_TRACE_CONN,
+                       "Cancelling tcpip-forward session for %s:%d",
+                       listener->host, listener->port);
+
+        s = packet = LIBSSH2_ALLOC(session, packet_len);
+        if(!packet) {
+            _libssh2_error(session, LIBSSH2_ERROR_ALLOC,
+                           "Unable to allocate memory for setenv packet");
+            return LIBSSH2_ERROR_ALLOC;
+        }
+
+        *(s++) = SSH_MSG_GLOBAL_REQUEST;
+        _libssh2_store_str(&s, "cancel-tcpip-forward",
+                           sizeof("cancel-tcpip-forward") - 1);
+        *(s++) = 0x00;          /* want_reply */
+
+        _libssh2_store_str(&s, listener->host, host_len);
+        _libssh2_store_u32(&s, listener->port);
+
+        listener->chanFwdCncl_state = libssh2_NB_state_created;
+    }
+    else {
+        packet = listener->chanFwdCncl_data;
+    }
+
+    if(listener->chanFwdCncl_state == libssh2_NB_state_created) {
+        rc = _libssh2_transport_send(session, packet, packet_len, NULL, 0);
+        if(rc == LIBSSH2_ERROR_EAGAIN) {
+            _libssh2_error(session, rc,
+                           "Would block sending forward request");
+            listener->chanFwdCncl_data = packet;
+            return rc;
+        }
+        else if(rc) {
+            _libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND,
+                           "Unable to send global-request packet for forward "
+                           "listen request");
+            /* set the state to something we don't check for, for the
+               unfortunate situation where we get an EAGAIN further down
+               when trying to bail out due to errors! */
+            listener->chanFwdCncl_state = libssh2_NB_state_sent;
+            retcode = LIBSSH2_ERROR_SOCKET_SEND;
+        }
+        LIBSSH2_FREE(session, packet);
+
+        listener->chanFwdCncl_state = libssh2_NB_state_sent;
+    }
+
+    queued = _libssh2_list_first(&listener->queue);
+    while(queued) {
+        LIBSSH2_CHANNEL *next = _libssh2_list_next(&queued->node);
+
+        rc = _libssh2_channel_free(queued);
+        if(rc == LIBSSH2_ERROR_EAGAIN) {
+            return rc;
+        }
+        queued = next;
+    }
+    LIBSSH2_FREE(session, listener->host);
+
+    /* remove this entry from the parent's list of listeners */
+    _libssh2_list_remove(&listener->node);
+
+    LIBSSH2_FREE(session, listener);
+
+    return retcode;
+}
+
+/*
+ * libssh2_channel_forward_cancel
+ *
+ * Stop listening on a remote port and free the listener
+ * Toss out any pending (un-accept()ed) connections
+ *
+ * Return 0 on success, LIBSSH2_ERROR_EAGAIN if would block, -1 on error
+ */
+LIBSSH2_API int
+libssh2_channel_forward_cancel(LIBSSH2_LISTENER *listener)
+{
+    int rc;
+
+    if(!listener)
+        return LIBSSH2_ERROR_BAD_USE;
+
+    BLOCK_ADJUST(rc, listener->session,
+                 _libssh2_channel_forward_cancel(listener));
+    return rc;
+}
+
+/*
+ * channel_forward_accept
+ *
+ * Accept a connection
+ */
+static LIBSSH2_CHANNEL *
+channel_forward_accept(LIBSSH2_LISTENER *listener)
+{
+    int rc;
+
+    do {
+        rc = _libssh2_transport_read(listener->session);
+    } while(rc > 0);
+
+    if(_libssh2_list_first(&listener->queue)) {
+        LIBSSH2_CHANNEL *channel = _libssh2_list_first(&listener->queue);
+
+        /* detach channel from listener's queue */
+        _libssh2_list_remove(&channel->node);
+
+        listener->queue_size--;
+
+        /* add channel to session's channel list */
+        _libssh2_list_add(&channel->session->channels, &channel->node);
+
+        return channel;
+    }
+
+    if(rc == LIBSSH2_ERROR_EAGAIN) {
+        _libssh2_error(listener->session, LIBSSH2_ERROR_EAGAIN,
+                       "Would block waiting for packet");
+    }
+    else
+        _libssh2_error(listener->session, LIBSSH2_ERROR_CHANNEL_UNKNOWN,
+                       "Channel not found");
+    return NULL;
+}
+
+/*
+ * libssh2_channel_forward_accept
+ *
+ * Accept a connection
+ */
+LIBSSH2_API LIBSSH2_CHANNEL *
+libssh2_channel_forward_accept(LIBSSH2_LISTENER *listener)
+{
+    LIBSSH2_CHANNEL *ptr;
+
+    if(!listener)
+        return NULL;
+
+    BLOCK_ADJUST_ERRNO(ptr, listener->session,
+                       channel_forward_accept(listener));
+    return ptr;
+
+}
+
+/*
+ * channel_setenv
+ *
+ * Set an environment variable prior to requesting a shell/program/subsystem
+ */
+static int channel_setenv(LIBSSH2_CHANNEL *channel,
+                          const char *varname, unsigned int varname_len,
+                          const char *value, unsigned int value_len)
+{
+    LIBSSH2_SESSION *session = channel->session;
+    unsigned char *s, *data;
+    static const unsigned char reply_codes[3] =
+        { SSH_MSG_CHANNEL_SUCCESS, SSH_MSG_CHANNEL_FAILURE, 0 };
+    size_t data_len;
+    int rc;
+
+    if(channel->setenv_state == libssh2_NB_state_idle) {
+        /* 21 = packet_type(1) + channel_id(4) + request_len(4) +
+         * request(3)"env" + want_reply(1) + varname_len(4) + value_len(4) */
+        channel->setenv_packet_len = varname_len + value_len + 21;
+
+        /* Zero the whole thing out */
+        memset(&channel->setenv_packet_requirev_state, 0,
+               sizeof(channel->setenv_packet_requirev_state));
+
+        _libssh2_debug(session, LIBSSH2_TRACE_CONN,
+                       "Setting remote environment variable: %s=%s on "
+                       "channel %lu/%lu",
+                       varname, value, channel->local.id, channel->remote.id);
+
+        s = channel->setenv_packet =
+            LIBSSH2_ALLOC(session, channel->setenv_packet_len);
+        if(!channel->setenv_packet) {
+            return _libssh2_error(session, LIBSSH2_ERROR_ALLOC,
+                                  "Unable to allocate memory "
+                                  "for setenv packet");
+        }
+
+        *(s++) = SSH_MSG_CHANNEL_REQUEST;
+        _libssh2_store_u32(&s, channel->remote.id);
+        _libssh2_store_str(&s, "env", sizeof("env") - 1);
+        *(s++) = 0x01;
+        _libssh2_store_str(&s, varname, varname_len);
+        _libssh2_store_str(&s, value, value_len);
+
+        channel->setenv_state = libssh2_NB_state_created;
+    }
+
+    if(channel->setenv_state == libssh2_NB_state_created) {
+        rc = _libssh2_transport_send(session,
+                                     channel->setenv_packet,
+                                     channel->setenv_packet_len,
+                                     NULL, 0);
+        if(rc == LIBSSH2_ERROR_EAGAIN) {
+            _libssh2_error(session, rc,
+                           "Would block sending setenv request");
+            return rc;
+        }
+        else if(rc) {
+            LIBSSH2_FREE(session, channel->setenv_packet);
+            channel->setenv_packet = NULL;
+            channel->setenv_state = libssh2_NB_state_idle;
+            return _libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND,
+                                  "Unable to send channel-request packet for "
+                                  "setenv request");
+        }
+        LIBSSH2_FREE(session, channel->setenv_packet);
+        channel->setenv_packet = NULL;
+
+        _libssh2_htonu32(channel->setenv_local_channel, channel->local.id);
+
+        channel->setenv_state = libssh2_NB_state_sent;
+    }
+
+    if(channel->setenv_state == libssh2_NB_state_sent) {
+        rc = _libssh2_packet_requirev(session, reply_codes, &data, &data_len,
+                                      1, channel->setenv_local_channel, 4,
+                                      &channel->
+                                      setenv_packet_requirev_state);
+        if(rc == LIBSSH2_ERROR_EAGAIN) {
+            return rc;
+        }
+        if(rc) {
+            channel->setenv_state = libssh2_NB_state_idle;
+            return rc;
+        }
+        else if(data_len < 1) {
+            channel->setenv_state = libssh2_NB_state_idle;
+            return _libssh2_error(session, LIBSSH2_ERROR_PROTO,
+                                  "Unexpected packet size");
+        }
+
+        if(data[0] == SSH_MSG_CHANNEL_SUCCESS) {
+            LIBSSH2_FREE(session, data);
+            channel->setenv_state = libssh2_NB_state_idle;
+            return 0;
+        }
+
+        LIBSSH2_FREE(session, data);
+    }
+
+    channel->setenv_state = libssh2_NB_state_idle;
+    return _libssh2_error(session, LIBSSH2_ERROR_CHANNEL_REQUEST_DENIED,
+                          "Unable to complete request for channel-setenv");
+}
+
+/*
+ * libssh2_channel_setenv_ex
+ *
+ * Set an environment variable prior to requesting a shell/program/subsystem
+ */
+LIBSSH2_API int
+libssh2_channel_setenv_ex(LIBSSH2_CHANNEL *channel,
+                          const char *varname, unsigned int varname_len,
+                          const char *value, unsigned int value_len)
+{
+    int rc;
+
+    if(!channel)
+        return LIBSSH2_ERROR_BAD_USE;
+
+    BLOCK_ADJUST(rc, channel->session,
+                 channel_setenv(channel, varname, varname_len,
+                                value, value_len));
+    return rc;
+}
+
+/*
+ * channel_request_pty
+ * Duh... Request a PTY
+ */
+static int channel_request_pty(LIBSSH2_CHANNEL *channel,
+                               const char *term, unsigned int term_len,
+                               const char *modes, unsigned int modes_len,
+                               int width, int height,
+                               int width_px, int height_px)
+{
+    LIBSSH2_SESSION *session = channel->session;
+    unsigned char *s;
+    static const unsigned char reply_codes[3] =
+        { SSH_MSG_CHANNEL_SUCCESS, SSH_MSG_CHANNEL_FAILURE, 0 };
+    int rc;
+
+    if(channel->reqPTY_state == libssh2_NB_state_idle) {
+        /* 41 = packet_type(1) + channel(4) + pty_req_len(4) + "pty_req"(7) +
+         * want_reply(1) + term_len(4) + width(4) + height(4) + width_px(4) +
+         * height_px(4) + modes_len(4) */
+        if(term_len + modes_len > 256) {
+            return _libssh2_error(session, LIBSSH2_ERROR_INVAL,
+                                  "term + mode lengths too large");
+        }
+
+        channel->reqPTY_packet_len = term_len + modes_len + 41;
+
+        /* Zero the whole thing out */
+        memset(&channel->reqPTY_packet_requirev_state, 0,
+               sizeof(channel->reqPTY_packet_requirev_state));
+
+        _libssh2_debug(session, LIBSSH2_TRACE_CONN,
+                       "Allocating tty on channel %lu/%lu", channel->local.id,
+                       channel->remote.id);
+
+        s = channel->reqPTY_packet;
+
+        *(s++) = SSH_MSG_CHANNEL_REQUEST;
+        _libssh2_store_u32(&s, channel->remote.id);
+        _libssh2_store_str(&s, (char *)"pty-req", sizeof("pty-req") - 1);
+
+        *(s++) = 0x01;
+
+        _libssh2_store_str(&s, term, term_len);
+        _libssh2_store_u32(&s, width);
+        _libssh2_store_u32(&s, height);
+        _libssh2_store_u32(&s, width_px);
+        _libssh2_store_u32(&s, height_px);
+        _libssh2_store_str(&s, modes, modes_len);
+
+        channel->reqPTY_state = libssh2_NB_state_created;
+    }
+
+    if(channel->reqPTY_state == libssh2_NB_state_created) {
+        rc = _libssh2_transport_send(session, channel->reqPTY_packet,
+                                     channel->reqPTY_packet_len,
+                                     NULL, 0);
+        if(rc == LIBSSH2_ERROR_EAGAIN) {
+            _libssh2_error(session, rc,
+                           "Would block sending pty request");
+            return rc;
+        }
+        else if(rc) {
+            channel->reqPTY_state = libssh2_NB_state_idle;
+            return _libssh2_error(session, rc,
+                                  "Unable to send pty-request packet");
+        }
+        _libssh2_htonu32(channel->reqPTY_local_channel, channel->local.id);
+
+        channel->reqPTY_state = libssh2_NB_state_sent;
+    }
+
+    if(channel->reqPTY_state == libssh2_NB_state_sent) {
+        unsigned char *data;
+        size_t data_len;
+        unsigned char code;
+        rc = _libssh2_packet_requirev(session, reply_codes, &data, &data_len,
+                                      1, channel->reqPTY_local_channel, 4,
+                                      &channel->reqPTY_packet_requirev_state);
+        if(rc == LIBSSH2_ERROR_EAGAIN) {
+            return rc;
+        }
+        else if(rc || data_len < 1) {
+            channel->reqPTY_state = libssh2_NB_state_idle;
+            return _libssh2_error(session, LIBSSH2_ERROR_PROTO,
+                                  "Failed to require the PTY package");
+        }
+
+        code = data[0];
+
+        LIBSSH2_FREE(session, data);
+        channel->reqPTY_state = libssh2_NB_state_idle;
+
+        if(code == SSH_MSG_CHANNEL_SUCCESS)
+            return 0;
+    }
+
+    return _libssh2_error(session, LIBSSH2_ERROR_CHANNEL_REQUEST_DENIED,
+                          "Unable to complete request for "
+                          "channel request-pty");
+}
+
+/*
+ * libssh2_channel_request_pty_ex
+ * Duh... Request a PTY
+ */
+LIBSSH2_API int
+libssh2_channel_request_pty_ex(LIBSSH2_CHANNEL *channel, const char *term,
+                               unsigned int term_len, const char *modes,
+                               unsigned int modes_len, int width, int height,
+                               int width_px, int height_px)
+{
+    int rc;
+
+    if(!channel)
+        return LIBSSH2_ERROR_BAD_USE;
+
+    BLOCK_ADJUST(rc, channel->session,
+                 channel_request_pty(channel, term, term_len, modes,
+                                     modes_len, width, height,
+                                     width_px, height_px));
+    return rc;
+}
+
+static int
+channel_request_pty_size(LIBSSH2_CHANNEL * channel, int width,
+                         int height, int width_px, int height_px)
+{
+    LIBSSH2_SESSION *session = channel->session;
+    unsigned char *s;
+    int rc;
+    int retcode = LIBSSH2_ERROR_PROTO;
+
+    if(channel->reqPTY_state == libssh2_NB_state_idle) {
+        channel->reqPTY_packet_len = 39;
+
+        /* Zero the whole thing out */
+        memset(&channel->reqPTY_packet_requirev_state, 0,
+               sizeof(channel->reqPTY_packet_requirev_state));
+
+        _libssh2_debug(session, LIBSSH2_TRACE_CONN,
+            "changing tty size on channel %lu/%lu",
+            channel->local.id,
+            channel->remote.id);
+
+        s = channel->reqPTY_packet;
+
+        *(s++) = SSH_MSG_CHANNEL_REQUEST;
+        _libssh2_store_u32(&s, channel->remote.id);
+        _libssh2_store_str(&s, (char *)"window-change",
+                           sizeof("window-change") - 1);
+        *(s++) = 0x00; /* Don't reply */
+        _libssh2_store_u32(&s, width);
+        _libssh2_store_u32(&s, height);
+        _libssh2_store_u32(&s, width_px);
+        _libssh2_store_u32(&s, height_px);
+
+        channel->reqPTY_state = libssh2_NB_state_created;
+    }
+
+    if(channel->reqPTY_state == libssh2_NB_state_created) {
+        rc = _libssh2_transport_send(session, channel->reqPTY_packet,
+                                     channel->reqPTY_packet_len,
+                                     NULL, 0);
+        if(rc == LIBSSH2_ERROR_EAGAIN) {
+            _libssh2_error(session, rc,
+                           "Would block sending window-change request");
+            return rc;
+        }
+        else if(rc) {
+            channel->reqPTY_state = libssh2_NB_state_idle;
+            return _libssh2_error(session, rc,
+                                  "Unable to send window-change packet");
+        }
+        _libssh2_htonu32(channel->reqPTY_local_channel, channel->local.id);
+        retcode = LIBSSH2_ERROR_NONE;
+    }
+
+    channel->reqPTY_state = libssh2_NB_state_idle;
+    return retcode;
+}
+
+LIBSSH2_API int
+libssh2_channel_request_pty_size_ex(LIBSSH2_CHANNEL *channel, int width,
+                                    int height, int width_px, int height_px)
+{
+    int rc;
+
+    if(!channel)
+        return LIBSSH2_ERROR_BAD_USE;
+
+    BLOCK_ADJUST(rc, channel->session,
+                 channel_request_pty_size(channel, width, height, width_px,
+                                          height_px));
+    return rc;
+}
+
+/* Keep this an even number */
+#define LIBSSH2_X11_RANDOM_COOKIE_LEN       32
+
+/*
+ * channel_x11_req
+ * Request X11 forwarding
+ */
+static int
+channel_x11_req(LIBSSH2_CHANNEL *channel, int single_connection,
+                const char *auth_proto, const char *auth_cookie,
+                int screen_number)
+{
+    LIBSSH2_SESSION *session = channel->session;
+    unsigned char *s;
+    static const unsigned char reply_codes[3] =
+        { SSH_MSG_CHANNEL_SUCCESS, SSH_MSG_CHANNEL_FAILURE, 0 };
+    size_t proto_len =
+        auth_proto ? strlen(auth_proto) : (sizeof("MIT-MAGIC-COOKIE-1") - 1);
+    size_t cookie_len =
+        auth_cookie ? strlen(auth_cookie) : LIBSSH2_X11_RANDOM_COOKIE_LEN;
+    int rc;
+
+    if(channel->reqX11_state == libssh2_NB_state_idle) {
+        /* 30 = packet_type(1) + channel(4) + x11_req_len(4) + "x11-req"(7) +
+         * want_reply(1) + single_cnx(1) + proto_len(4) + cookie_len(4) +
+         * screen_num(4) */
+        channel->reqX11_packet_len = proto_len + cookie_len + 30;
+
+        /* Zero the whole thing out */
+        memset(&channel->reqX11_packet_requirev_state, 0,
+               sizeof(channel->reqX11_packet_requirev_state));
+
+        _libssh2_debug(session, LIBSSH2_TRACE_CONN,
+                       "Requesting x11-req for channel %lu/%lu: single=%d "
+                       "proto=%s cookie=%s screen=%d",
+                       channel->local.id, channel->remote.id,
+                       single_connection,
+                       auth_proto ? auth_proto : "MIT-MAGIC-COOKIE-1",
+                       auth_cookie ? auth_cookie : "<random>", screen_number);
+
+        s = channel->reqX11_packet =
+            LIBSSH2_ALLOC(session, channel->reqX11_packet_len);
+        if(!channel->reqX11_packet) {
+            return _libssh2_error(session, LIBSSH2_ERROR_ALLOC,
+                                  "Unable to allocate memory for pty-request");
+        }
+
+        *(s++) = SSH_MSG_CHANNEL_REQUEST;
+        _libssh2_store_u32(&s, channel->remote.id);
+        _libssh2_store_str(&s, "x11-req", sizeof("x11-req") - 1);
+
+        *(s++) = 0x01;          /* want_reply */
+        *(s++) = single_connection ? 0x01 : 0x00;
+
+        _libssh2_store_str(&s, auth_proto ? auth_proto : "MIT-MAGIC-COOKIE-1",
+                           proto_len);
+
+        _libssh2_store_u32(&s, cookie_len);
+        if(auth_cookie) {
+            memcpy(s, auth_cookie, cookie_len);
+        }
+        else {
+            int i;
+            /* note: the extra +1 below is necessary since the sprintf()
+               loop will always write 3 bytes so the last one will write
+               the trailing zero at the LIBSSH2_X11_RANDOM_COOKIE_LEN/2
+               border */
+            unsigned char buffer[(LIBSSH2_X11_RANDOM_COOKIE_LEN / 2) + 1];
+
+            _libssh2_random(buffer, LIBSSH2_X11_RANDOM_COOKIE_LEN / 2);
+            for(i = 0; i < (LIBSSH2_X11_RANDOM_COOKIE_LEN / 2); i++) {
+                snprintf((char *)&s[i*2], 3, "%02X", buffer[i]);
+            }
+        }
+        s += cookie_len;
+
+        _libssh2_store_u32(&s, screen_number);
+        channel->reqX11_state = libssh2_NB_state_created;
+    }
+
+    if(channel->reqX11_state == libssh2_NB_state_created) {
+        rc = _libssh2_transport_send(session, channel->reqX11_packet,
+                                     channel->reqX11_packet_len,
+                                     NULL, 0);
+        if(rc == LIBSSH2_ERROR_EAGAIN) {
+            _libssh2_error(session, rc,
+                           "Would block sending X11-req packet");
+            return rc;
+        }
+        if(rc) {
+            LIBSSH2_FREE(session, channel->reqX11_packet);
+            channel->reqX11_packet = NULL;
+            channel->reqX11_state = libssh2_NB_state_idle;
+            return _libssh2_error(session, rc,
+                                  "Unable to send x11-req packet");
+        }
+        LIBSSH2_FREE(session, channel->reqX11_packet);
+        channel->reqX11_packet = NULL;
+
+        _libssh2_htonu32(channel->reqX11_local_channel, channel->local.id);
+
+        channel->reqX11_state = libssh2_NB_state_sent;
+    }
+
+    if(channel->reqX11_state == libssh2_NB_state_sent) {
+        size_t data_len;
+        unsigned char *data;
+        unsigned char code;
+
+        rc = _libssh2_packet_requirev(session, reply_codes, &data, &data_len,
+                                      1, channel->reqX11_local_channel, 4,
+                                      &channel->reqX11_packet_requirev_state);
+        if(rc == LIBSSH2_ERROR_EAGAIN) {
+            return rc;
+        }
+        else if(rc || data_len < 1) {
+            channel->reqX11_state = libssh2_NB_state_idle;
+            return _libssh2_error(session, rc,
+                                  "waiting for x11-req response packet");
+        }
+
+        code = data[0];
+        LIBSSH2_FREE(session, data);
+        channel->reqX11_state = libssh2_NB_state_idle;
+
+        if(code == SSH_MSG_CHANNEL_SUCCESS)
+            return 0;
+    }
+
+    return _libssh2_error(session, LIBSSH2_ERROR_CHANNEL_REQUEST_DENIED,
+                          "Unable to complete request for channel x11-req");
+}
+
+/*
+ * libssh2_channel_x11_req_ex
+ * Request X11 forwarding
+ */
+LIBSSH2_API int
+libssh2_channel_x11_req_ex(LIBSSH2_CHANNEL *channel, int single_connection,
+                           const char *auth_proto, const char *auth_cookie,
+                           int screen_number)
+{
+    int rc;
+
+    if(!channel)
+        return LIBSSH2_ERROR_BAD_USE;
+
+    BLOCK_ADJUST(rc, channel->session,
+                 channel_x11_req(channel, single_connection, auth_proto,
+                                 auth_cookie, screen_number));
+    return rc;
+}
+
+
+/*
+ * _libssh2_channel_process_startup
+ *
+ * Primitive for libssh2_channel_(shell|exec|subsystem)
+ */
+int
+_libssh2_channel_process_startup(LIBSSH2_CHANNEL *channel,
+                                 const char *request, size_t request_len,
+                                 const char *message, size_t message_len)
+{
+    LIBSSH2_SESSION *session = channel->session;
+    unsigned char *s;
+    static const unsigned char reply_codes[3] =
+        { SSH_MSG_CHANNEL_SUCCESS, SSH_MSG_CHANNEL_FAILURE, 0 };
+    int rc;
+
+    if(channel->process_state == libssh2_NB_state_end) {
+        return _libssh2_error(session, LIBSSH2_ERROR_BAD_USE,
+                              "Channel can not be reused");
+    }
+
+    if(channel->process_state == libssh2_NB_state_idle) {
+        /* 10 = packet_type(1) + channel(4) + request_len(4) + want_reply(1) */
+        channel->process_packet_len = request_len + 10;
+
+        /* Zero the whole thing out */
+        memset(&channel->process_packet_requirev_state, 0,
+               sizeof(channel->process_packet_requirev_state));
+
+        if(message)
+            channel->process_packet_len += + 4;
+
+        _libssh2_debug(session, LIBSSH2_TRACE_CONN,
+                       "starting request(%s) on channel %lu/%lu, message=%s",
+                       request, channel->local.id, channel->remote.id,
+                       message ? message : "<null>");
+        s = channel->process_packet =
+            LIBSSH2_ALLOC(session, channel->process_packet_len);
+        if(!channel->process_packet)
+            return _libssh2_error(session, LIBSSH2_ERROR_ALLOC,
+                                  "Unable to allocate memory "
+                                  "for channel-process request");
+
+        *(s++) = SSH_MSG_CHANNEL_REQUEST;
+        _libssh2_store_u32(&s, channel->remote.id);
+        _libssh2_store_str(&s, request, request_len);
+        *(s++) = 0x01;
+
+        if(message)
+            _libssh2_store_u32(&s, message_len);
+
+        channel->process_state = libssh2_NB_state_created;
+    }
+
+    if(channel->process_state == libssh2_NB_state_created) {
+        rc = _libssh2_transport_send(session,
+                                     channel->process_packet,
+                                     channel->process_packet_len,
+                                     (unsigned char *)message, message_len);
+        if(rc == LIBSSH2_ERROR_EAGAIN) {
+            _libssh2_error(session, rc,
+                           "Would block sending channel request");
+            return rc;
+        }
+        else if(rc) {
+            LIBSSH2_FREE(session, channel->process_packet);
+            channel->process_packet = NULL;
+            channel->process_state = libssh2_NB_state_end;
+            return _libssh2_error(session, rc,
+                                  "Unable to send channel request");
+        }
+        LIBSSH2_FREE(session, channel->process_packet);
+        channel->process_packet = NULL;
+
+        _libssh2_htonu32(channel->process_local_channel, channel->local.id);
+
+        channel->process_state = libssh2_NB_state_sent;
+    }
+
+    if(channel->process_state == libssh2_NB_state_sent) {
+        unsigned char *data;
+        size_t data_len;
+        unsigned char code;
+        rc = _libssh2_packet_requirev(session, reply_codes, &data, &data_len,
+                                      1, channel->process_local_channel, 4,
+                                      &channel->process_packet_requirev_state);
+        if(rc == LIBSSH2_ERROR_EAGAIN) {
+            return rc;
+        }
+        else if(rc || data_len < 1) {
+            channel->process_state = libssh2_NB_state_end;
+            return _libssh2_error(session, rc,
+                                  "Failed waiting for channel success");
+        }
+
+        code = data[0];
+        LIBSSH2_FREE(session, data);
+        channel->process_state = libssh2_NB_state_end;
+
+        if(code == SSH_MSG_CHANNEL_SUCCESS)
+            return 0;
+    }
+
+    return _libssh2_error(session, LIBSSH2_ERROR_CHANNEL_REQUEST_DENIED,
+                          "Unable to complete request for "
+                          "channel-process-startup");
+}
+
+/*
+ * libssh2_channel_process_startup
+ *
+ * Primitive for libssh2_channel_(shell|exec|subsystem)
+ */
+LIBSSH2_API int
+libssh2_channel_process_startup(LIBSSH2_CHANNEL *channel,
+                                const char *req, unsigned int req_len,
+                                const char *msg, unsigned int msg_len)
+{
+    int rc;
+
+    if(!channel)
+        return LIBSSH2_ERROR_BAD_USE;
+
+    BLOCK_ADJUST(rc, channel->session,
+                 _libssh2_channel_process_startup(channel, req, req_len,
+                                                  msg, msg_len));
+    return rc;
+}
+
+
+/*
+ * libssh2_channel_set_blocking
+ *
+ * Set a channel's BEHAVIOR blocking on or off. The socket will remain non-
+ * blocking.
+ */
+LIBSSH2_API void
+libssh2_channel_set_blocking(LIBSSH2_CHANNEL * channel, int blocking)
+{
+    if(channel)
+        (void) _libssh2_session_set_blocking(channel->session, blocking);
+}
+
+/*
+ * _libssh2_channel_flush
+ *
+ * Flush data from one (or all) stream
+ * Returns number of bytes flushed, or negative on failure
+ */
+int
+_libssh2_channel_flush(LIBSSH2_CHANNEL *channel, int streamid)
+{
+    if(channel->flush_state == libssh2_NB_state_idle) {
+        LIBSSH2_PACKET *packet =
+            _libssh2_list_first(&channel->session->packets);
+        channel->flush_refund_bytes = 0;
+        channel->flush_flush_bytes = 0;
+
+        while(packet) {
+            unsigned char packet_type;
+            LIBSSH2_PACKET *next = _libssh2_list_next(&packet->node);
+
+            if(packet->data_len < 1) {
+                packet = next;
+                _libssh2_debug(channel->session, LIBSSH2_TRACE_ERROR,
+                               "Unexpected packet length");
+                continue;
+            }
+
+            packet_type = packet->data[0];
+
+            if(((packet_type == SSH_MSG_CHANNEL_DATA)
+                || (packet_type == SSH_MSG_CHANNEL_EXTENDED_DATA))
+               && ((packet->data_len >= 5)
+                   && (_libssh2_ntohu32(packet->data + 1)
+                       == channel->local.id))) {
+                /* It's our channel at least */
+                int packet_stream_id;
+
+                if(packet_type == SSH_MSG_CHANNEL_DATA) {
+                    packet_stream_id = 0;
+                }
+                else if(packet->data_len >= 9) {
+                    packet_stream_id = _libssh2_ntohu32(packet->data + 5);
+                }
+                else {
+                    channel->flush_state = libssh2_NB_state_idle;
+                    return _libssh2_error(channel->session,
+                                          LIBSSH2_ERROR_PROTO,
+                                          "Unexpected packet length");
+                }
+
+                if((streamid == LIBSSH2_CHANNEL_FLUSH_ALL)
+                    || ((packet_type == SSH_MSG_CHANNEL_EXTENDED_DATA)
+                        && ((streamid == LIBSSH2_CHANNEL_FLUSH_EXTENDED_DATA)
+                            || (streamid == packet_stream_id)))
+                    || ((packet_type == SSH_MSG_CHANNEL_DATA)
+                        && (streamid == 0))) {
+                    size_t bytes_to_flush = packet->data_len -
+                        packet->data_head;
+
+                    _libssh2_debug(channel->session, LIBSSH2_TRACE_CONN,
+                                   "Flushing %d bytes of data from stream "
+                                   "%lu on channel %lu/%lu",
+                                   bytes_to_flush, packet_stream_id,
+                                   channel->local.id, channel->remote.id);
+
+                    /* It's one of the streams we wanted to flush */
+                    channel->flush_refund_bytes += packet->data_len - 13;
+                    channel->flush_flush_bytes += bytes_to_flush;
+
+                    LIBSSH2_FREE(channel->session, packet->data);
+
+                    /* remove this packet from the parent's list */
+                    _libssh2_list_remove(&packet->node);
+                    LIBSSH2_FREE(channel->session, packet);
+                }
+            }
+            packet = next;
+        }
+
+        channel->flush_state = libssh2_NB_state_created;
+    }
+
+    channel->read_avail -= channel->flush_flush_bytes;
+    channel->remote.window_size -= channel->flush_flush_bytes;
+
+    if(channel->flush_refund_bytes) {
+        int rc =
+            _libssh2_channel_receive_window_adjust(channel,
+                                                   channel->flush_refund_bytes,
+                                                   1, NULL);
+        if(rc == LIBSSH2_ERROR_EAGAIN)
+            return rc;
+    }
+
+    channel->flush_state = libssh2_NB_state_idle;
+
+    return channel->flush_flush_bytes;
+}
+
+/*
+ * libssh2_channel_flush_ex
+ *
+ * Flush data from one (or all) stream
+ * Returns number of bytes flushed, or negative on failure
+ */
+LIBSSH2_API int
+libssh2_channel_flush_ex(LIBSSH2_CHANNEL *channel, int stream)
+{
+    int rc;
+
+    if(!channel)
+        return LIBSSH2_ERROR_BAD_USE;
+
+    BLOCK_ADJUST(rc, channel->session,
+                 _libssh2_channel_flush(channel, stream));
+    return rc;
+}
+
+/*
+ * libssh2_channel_get_exit_status
+ *
+ * Return the channel's program exit status. Note that the actual protocol
+ * provides the full 32bit this function returns.  We cannot abuse it to
+ * return error values in case of errors so we return a zero if channel is
+ * NULL.
+ */
+LIBSSH2_API int
+libssh2_channel_get_exit_status(LIBSSH2_CHANNEL *channel)
+{
+    if(!channel)
+        return 0;
+
+    return channel->exit_status;
+}
+
+/*
+ * libssh2_channel_get_exit_signal
+ *
+ * Get exit signal (without leading "SIG"), error message, and language
+ * tag into newly allocated buffers of indicated length.  Caller can
+ * use NULL pointers to indicate that the value should not be set.  The
+ * *_len variables are set if they are non-NULL even if the
+ * corresponding string parameter is NULL.  Returns LIBSSH2_ERROR_NONE
+ * on success, or an API error code.
+ */
+LIBSSH2_API int
+libssh2_channel_get_exit_signal(LIBSSH2_CHANNEL *channel,
+                                char **exitsignal,
+                                size_t *exitsignal_len,
+                                char **errmsg,
+                                size_t *errmsg_len,
+                                char **langtag,
+                                size_t *langtag_len)
+{
+    size_t namelen = 0;
+
+    if(channel) {
+        LIBSSH2_SESSION *session = channel->session;
+
+        if(channel->exit_signal) {
+            namelen = strlen(channel->exit_signal);
+            if(exitsignal) {
+                *exitsignal = LIBSSH2_ALLOC(session, namelen + 1);
+                if(!*exitsignal) {
+                    return _libssh2_error(session, LIBSSH2_ERROR_ALLOC,
+                        "Unable to allocate memory for signal name");
+                }
+                memcpy(*exitsignal, channel->exit_signal, namelen);
+                (*exitsignal)[namelen] = '\0';
+            }
+            if(exitsignal_len)
+                *exitsignal_len = namelen;
+        }
+        else {
+            if(exitsignal)
+                *exitsignal = NULL;
+            if(exitsignal_len)
+                *exitsignal_len = 0;
+        }
+
+        /* TODO: set error message and language tag */
+
+        if(errmsg)
+            *errmsg = NULL;
+
+        if(errmsg_len)
+            *errmsg_len = 0;
+
+        if(langtag)
+            *langtag = NULL;
+
+        if(langtag_len)
+            *langtag_len = 0;
+    }
+
+    return LIBSSH2_ERROR_NONE;
+}
+
+/*
+ * _libssh2_channel_receive_window_adjust
+ *
+ * Adjust the receive window for a channel by adjustment bytes. If the amount
+ * to be adjusted is less than LIBSSH2_CHANNEL_MINADJUST and force is 0 the
+ * adjustment amount will be queued for a later packet.
+ *
+ * Calls _libssh2_error() !
+ */
+int
+_libssh2_channel_receive_window_adjust(LIBSSH2_CHANNEL * channel,
+                                       uint32_t adjustment,
+                                       unsigned char force,
+                                       unsigned int *store)
+{
+    int rc;
+
+    if(store)
+        *store = channel->remote.window_size;
+
+    if(channel->adjust_state == libssh2_NB_state_idle) {
+        if(!force
+            && (adjustment + channel->adjust_queue <
+                LIBSSH2_CHANNEL_MINADJUST)) {
+            _libssh2_debug(channel->session, LIBSSH2_TRACE_CONN,
+                           "Queueing %lu bytes for receive window adjustment "
+                           "for channel %lu/%lu",
+                           adjustment, channel->local.id, channel->remote.id);
+            channel->adjust_queue += adjustment;
+            return 0;
+        }
+
+        if(!adjustment && !channel->adjust_queue) {
+            return 0;
+        }
+
+        adjustment += channel->adjust_queue;
+        channel->adjust_queue = 0;
+
+        /* Adjust the window based on the block we just freed */
+        channel->adjust_adjust[0] = SSH_MSG_CHANNEL_WINDOW_ADJUST;
+        _libssh2_htonu32(&channel->adjust_adjust[1], channel->remote.id);
+        _libssh2_htonu32(&channel->adjust_adjust[5], adjustment);
+        _libssh2_debug(channel->session, LIBSSH2_TRACE_CONN,
+                       "Adjusting window %lu bytes for data on "
+                       "channel %lu/%lu",
+                       adjustment, channel->local.id, channel->remote.id);
+
+        channel->adjust_state = libssh2_NB_state_created;
+    }
+
+    rc = _libssh2_transport_send(channel->session, channel->adjust_adjust, 9,
+                                 NULL, 0);
+    if(rc == LIBSSH2_ERROR_EAGAIN) {
+        _libssh2_error(channel->session, rc,
+                       "Would block sending window adjust");
+        return rc;
+    }
+    else if(rc) {
+        channel->adjust_queue = adjustment;
+        return _libssh2_error(channel->session, LIBSSH2_ERROR_SOCKET_SEND,
+                              "Unable to send transfer-window adjustment "
+                              "packet, deferring");
+    }
+    else {
+        channel->remote.window_size += adjustment;
+    }
+
+    channel->adjust_state = libssh2_NB_state_idle;
+
+    return 0;
+}
+
+/*
+ * libssh2_channel_receive_window_adjust
+ *
+ * DEPRECATED
+ *
+ * Adjust the receive window for a channel by adjustment bytes. If the amount
+ * to be adjusted is less than LIBSSH2_CHANNEL_MINADJUST and force is 0 the
+ * adjustment amount will be queued for a later packet.
+ *
+ * Returns the new size of the receive window (as understood by remote end).
+ * Note that it might return EAGAIN too which is highly stupid.
+ *
+ */
+LIBSSH2_API unsigned long
+libssh2_channel_receive_window_adjust(LIBSSH2_CHANNEL *channel,
+                                      unsigned long adj,
+                                      unsigned char force)
+{
+    unsigned int window;
+    int rc;
+
+    if(!channel)
+        return (unsigned long)LIBSSH2_ERROR_BAD_USE;
+
+    BLOCK_ADJUST(rc, channel->session,
+                 _libssh2_channel_receive_window_adjust(channel, adj,
+                                                        force, &window));
+
+    /* stupid - but this is how it was made to work before and this is just
+       kept for backwards compatibility */
+    return rc ? (unsigned long)rc : window;
+}
+
+/*
+ * libssh2_channel_receive_window_adjust2
+ *
+ * Adjust the receive window for a channel by adjustment bytes. If the amount
+ * to be adjusted is less than LIBSSH2_CHANNEL_MINADJUST and force is 0 the
+ * adjustment amount will be queued for a later packet.
+ *
+ * Stores the new size of the receive window in the data 'window' points to.
+ *
+ * Returns the "normal" error code: 0 for success, negative for failure.
+ */
+LIBSSH2_API int
+libssh2_channel_receive_window_adjust2(LIBSSH2_CHANNEL *channel,
+                                       unsigned long adj,
+                                       unsigned char force,
+                                       unsigned int *window)
+{
+    int rc;
+
+    if(!channel)
+        return LIBSSH2_ERROR_BAD_USE;
+
+    BLOCK_ADJUST(rc, channel->session,
+                 _libssh2_channel_receive_window_adjust(channel, adj, force,
+                                                        window));
+    return rc;
+}
+
+int
+_libssh2_channel_extended_data(LIBSSH2_CHANNEL *channel, int ignore_mode)
+{
+    if(channel->extData2_state == libssh2_NB_state_idle) {
+        _libssh2_debug(channel->session, LIBSSH2_TRACE_CONN,
+                       "Setting channel %lu/%lu handle_extended_data"
+                       " mode to %d",
+                       channel->local.id, channel->remote.id, ignore_mode);
+        channel->remote.extended_data_ignore_mode = (char)ignore_mode;
+
+        channel->extData2_state = libssh2_NB_state_created;
+    }
+
+    if(channel->extData2_state == libssh2_NB_state_idle) {
+        if(ignore_mode == LIBSSH2_CHANNEL_EXTENDED_DATA_IGNORE) {
+            int rc =
+                _libssh2_channel_flush(channel,
+                                       LIBSSH2_CHANNEL_FLUSH_EXTENDED_DATA);
+            if(LIBSSH2_ERROR_EAGAIN == rc)
+                return rc;
+        }
+    }
+
+    channel->extData2_state = libssh2_NB_state_idle;
+    return 0;
+}
+
+/*
+ * libssh2_channel_handle_extended_data2()
+ *
+ */
+LIBSSH2_API int
+libssh2_channel_handle_extended_data2(LIBSSH2_CHANNEL *channel,
+                                      int mode)
+{
+    int rc;
+
+    if(!channel)
+        return LIBSSH2_ERROR_BAD_USE;
+
+    BLOCK_ADJUST(rc, channel->session, _libssh2_channel_extended_data(channel,
+                                                                      mode));
+    return rc;
+}
+
+/*
+ * libssh2_channel_handle_extended_data
+ *
+ * DEPRECATED DO NOTE USE!
+ *
+ * How should extended data look to the calling app?  Keep it in separate
+ * channels[_read() _read_stdder()]? (NORMAL) Merge the extended data to the
+ * standard data? [everything via _read()]? (MERGE) Ignore it entirely [toss
+ * out packets as they come in]? (IGNORE)
+ */
+LIBSSH2_API void
+libssh2_channel_handle_extended_data(LIBSSH2_CHANNEL *channel,
+                                     int ignore_mode)
+{
+    (void)libssh2_channel_handle_extended_data2(channel, ignore_mode);
+}
+
+
+
+/*
+ * _libssh2_channel_read
+ *
+ * Read data from a channel
+ *
+ * It is important to not return 0 until the currently read channel is
+ * complete. If we read stuff from the wire but it was no payload data to fill
+ * in the buffer with, we MUST make sure to return LIBSSH2_ERROR_EAGAIN.
+ *
+ * The receive window must be maintained (enlarged) by the user of this
+ * function.
+ */
+ssize_t _libssh2_channel_read(LIBSSH2_CHANNEL *channel, int stream_id,
+                              char *buf, size_t buflen)
+{
+    LIBSSH2_SESSION *session = channel->session;
+    int rc;
+    size_t bytes_read = 0;
+    size_t bytes_want;
+    int unlink_packet;
+    LIBSSH2_PACKET *read_packet;
+    LIBSSH2_PACKET *read_next;
+
+    _libssh2_debug(session, LIBSSH2_TRACE_CONN,
+                   "channel_read() wants %d bytes from channel %lu/%lu "
+                   "stream #%d",
+                   (int) buflen, channel->local.id, channel->remote.id,
+                   stream_id);
+
+    /* expand the receiving window first if it has become too narrow */
+    if((channel->read_state == libssh2_NB_state_jump1) ||
+       (channel->remote.window_size <
+        channel->remote.window_size_initial / 4 * 3 + buflen) ) {
+
+        uint32_t adjustment = channel->remote.window_size_initial + buflen -
+            channel->remote.window_size;
+        if(adjustment < LIBSSH2_CHANNEL_MINADJUST)
+            adjustment = LIBSSH2_CHANNEL_MINADJUST;
+
+        /* the actual window adjusting may not finish so we need to deal with
+           this special state here */
+        channel->read_state = libssh2_NB_state_jump1;
+        rc = _libssh2_channel_receive_window_adjust(channel, adjustment,
+                                                    0, NULL);
+        if(rc)
+            return rc;
+
+        channel->read_state = libssh2_NB_state_idle;
+    }
+
+    /* Process all pending incoming packets. Tests prove that this way
+       produces faster transfers. */
+    do {
+        rc = _libssh2_transport_read(session);
+    } while(rc > 0);
+
+    if((rc < 0) && (rc != LIBSSH2_ERROR_EAGAIN))
+        return _libssh2_error(session, rc, "transport read");
+
+    read_packet = _libssh2_list_first(&session->packets);
+    while(read_packet && (bytes_read < buflen)) {
+        /* previously this loop condition also checked for
+           !channel->remote.close but we cannot let it do this:
+
+           We may have a series of packets to read that are still pending even
+           if a close has been received. Acknowledging the close too early
+           makes us flush buffers prematurely and loose data.
+        */
+
+        LIBSSH2_PACKET *readpkt = read_packet;
+
+        /* In case packet gets destroyed during this iteration */
+        read_next = _libssh2_list_next(&readpkt->node);
+
+        if(readpkt->data_len < 5) {
+            read_packet = read_next;
+            _libssh2_debug(channel->session, LIBSSH2_TRACE_ERROR,
+                           "Unexpected packet length");
+            continue;
+        }
+
+        channel->read_local_id =
+            _libssh2_ntohu32(readpkt->data + 1);
+
+        /*
+         * Either we asked for a specific extended data stream
+         * (and data was available),
+         * or the standard stream (and data was available),
+         * or the standard stream with extended_data_merge
+         * enabled and data was available
+         */
+        if((stream_id
+             && (readpkt->data[0] == SSH_MSG_CHANNEL_EXTENDED_DATA)
+             && (channel->local.id == channel->read_local_id)
+             && (readpkt->data_len >= 9)
+             && (stream_id == (int) _libssh2_ntohu32(readpkt->data + 5)))
+            || (!stream_id && (readpkt->data[0] == SSH_MSG_CHANNEL_DATA)
+                && (channel->local.id == channel->read_local_id))
+            || (!stream_id
+                && (readpkt->data[0] == SSH_MSG_CHANNEL_EXTENDED_DATA)
+                && (channel->local.id == channel->read_local_id)
+                && (channel->remote.extended_data_ignore_mode ==
+                    LIBSSH2_CHANNEL_EXTENDED_DATA_MERGE))) {
+
+            /* figure out much more data we want to read */
+            bytes_want = buflen - bytes_read;
+            unlink_packet = FALSE;
+
+            if(bytes_want >= (readpkt->data_len - readpkt->data_head)) {
+                /* we want more than this node keeps, so adjust the number and
+                   delete this node after the copy */
+                bytes_want = readpkt->data_len - readpkt->data_head;
+                unlink_packet = TRUE;
+            }
+
+            _libssh2_debug(session, LIBSSH2_TRACE_CONN,
+                           "channel_read() got %d of data from %lu/%lu/%d%s",
+                           bytes_want, channel->local.id,
+                           channel->remote.id, stream_id,
+                           unlink_packet?" [ul]":"");
+
+            /* copy data from this struct to the target buffer */
+            memcpy(&buf[bytes_read],
+                   &readpkt->data[readpkt->data_head], bytes_want);
+
+            /* advance pointer and counter */
+            readpkt->data_head += bytes_want;
+            bytes_read += bytes_want;
+
+            /* if drained, remove from list */
+            if(unlink_packet) {
+                /* detach readpkt from session->packets list */
+                _libssh2_list_remove(&readpkt->node);
+
+                LIBSSH2_FREE(session, readpkt->data);
+                LIBSSH2_FREE(session, readpkt);
+            }
+        }
+
+        /* check the next struct in the chain */
+        read_packet = read_next;
+    }
+
+    if(!bytes_read) {
+        /* If the channel is already at EOF or even closed, we need to signal
+           that back. We may have gotten that info while draining the incoming
+           transport layer until EAGAIN so we must not be fooled by that
+           return code. */
+        if(channel->remote.eof || channel->remote.close)
+            return 0;
+        else if(rc != LIBSSH2_ERROR_EAGAIN)
+            return 0;
+
+        /* if the transport layer said EAGAIN then we say so as well */
+        return _libssh2_error(session, rc, "would block");
+    }
+
+    channel->read_avail -= bytes_read;
+    channel->remote.window_size -= bytes_read;
+
+    return bytes_read;
+}
+
+/*
+ * libssh2_channel_read_ex
+ *
+ * Read data from a channel (blocking or non-blocking depending on set state)
+ *
+ * When this is done non-blocking, it is important to not return 0 until the
+ * currently read channel is complete. If we read stuff from the wire but it
+ * was no payload data to fill in the buffer with, we MUST make sure to return
+ * LIBSSH2_ERROR_EAGAIN.
+ *
+ * This function will first make sure there's a receive window enough to
+ * receive a full buffer's wort of contents. An application may choose to
+ * adjust the receive window more to increase transfer performance.
+ */
+LIBSSH2_API ssize_t
+libssh2_channel_read_ex(LIBSSH2_CHANNEL *channel, int stream_id, char *buf,
+                        size_t buflen)
+{
+    int rc;
+    unsigned long recv_window;
+
+    if(!channel)
+        return LIBSSH2_ERROR_BAD_USE;
+
+    recv_window = libssh2_channel_window_read_ex(channel, NULL, NULL);
+
+    if(buflen > recv_window) {
+        BLOCK_ADJUST(rc, channel->session,
+                     _libssh2_channel_receive_window_adjust(channel, buflen,
+                                                            1, NULL));
+    }
+
+    BLOCK_ADJUST(rc, channel->session,
+                 _libssh2_channel_read(channel, stream_id, buf, buflen));
+    return rc;
+}
+
+/*
+ * _libssh2_channel_packet_data_len
+ *
+ * Return the size of the data block of the current packet, or 0 if there
+ * isn't a packet.
+ */
+size_t
+_libssh2_channel_packet_data_len(LIBSSH2_CHANNEL * channel, int stream_id)
+{
+    LIBSSH2_SESSION *session = channel->session;
+    LIBSSH2_PACKET *read_packet;
+    LIBSSH2_PACKET *next_packet;
+    uint32_t read_local_id;
+
+    read_packet = _libssh2_list_first(&session->packets);
+    if(read_packet == NULL)
+        return 0;
+
+    while(read_packet) {
+
+        next_packet = _libssh2_list_next(&read_packet->node);
+
+        if(read_packet->data_len < 5) {
+            read_packet = next_packet;
+            _libssh2_debug(channel->session, LIBSSH2_TRACE_ERROR,
+                           "Unexpected packet length");
+            continue;
+        }
+
+        read_local_id = _libssh2_ntohu32(read_packet->data + 1);
+
+        /*
+         * Either we asked for a specific extended data stream
+         * (and data was available),
+         * or the standard stream (and data was available),
+         * or the standard stream with extended_data_merge
+         * enabled and data was available
+         */
+        if((stream_id
+             && (read_packet->data[0] == SSH_MSG_CHANNEL_EXTENDED_DATA)
+             && (channel->local.id == read_local_id)
+             && (read_packet->data_len >= 9)
+             && (stream_id == (int) _libssh2_ntohu32(read_packet->data + 5)))
+            ||
+            (!stream_id
+             && (read_packet->data[0] == SSH_MSG_CHANNEL_DATA)
+             && (channel->local.id == read_local_id))
+            ||
+            (!stream_id
+             && (read_packet->data[0] == SSH_MSG_CHANNEL_EXTENDED_DATA)
+             && (channel->local.id == read_local_id)
+             && (channel->remote.extended_data_ignore_mode
+                 == LIBSSH2_CHANNEL_EXTENDED_DATA_MERGE))) {
+            return (read_packet->data_len - read_packet->data_head);
+        }
+
+        read_packet = next_packet;
+    }
+
+    return 0;
+}
+
+/*
+ * _libssh2_channel_write
+ *
+ * Send data to a channel. Note that if this returns EAGAIN, the caller must
+ * call this function again with the SAME input arguments.
+ *
+ * Returns: number of bytes sent, or if it returns a negative number, that is
+ * the error code!
+ */
+ssize_t
+_libssh2_channel_write(LIBSSH2_CHANNEL *channel, int stream_id,
+                       const unsigned char *buf, size_t buflen)
+{
+    int rc = 0;
+    LIBSSH2_SESSION *session = channel->session;
+    ssize_t wrote = 0; /* counter for this specific this call */
+
+    /* In theory we could split larger buffers into several smaller packets
+     * but it turns out to be really hard and nasty to do while still offering
+     * the API/prototype.
+     *
+     * Instead we only deal with the first 32K in this call and for the parent
+     * function to call it again with the remainder! 32K is a conservative
+     * limit based on the text in RFC4253 section 6.1.
+     */
+    if(buflen > 32700)
+        buflen = 32700;
+
+    if(channel->write_state == libssh2_NB_state_idle) {
+        unsigned char *s = channel->write_packet;
+
+        _libssh2_debug(channel->session, LIBSSH2_TRACE_CONN,
+                       "Writing %d bytes on channel %lu/%lu, stream #%d",
+                       (int) buflen, channel->local.id, channel->remote.id,
+                       stream_id);
+
+        if(channel->local.close)
+            return _libssh2_error(channel->session,
+                                  LIBSSH2_ERROR_CHANNEL_CLOSED,
+                                  "We've already closed this channel");
+        else if(channel->local.eof)
+            return _libssh2_error(channel->session,
+                                  LIBSSH2_ERROR_CHANNEL_EOF_SENT,
+                                  "EOF has already been received, "
+                                  "data might be ignored");
+
+        /* drain the incoming flow first, mostly to make sure we get all
+         * pending window adjust packets */
+        do
+            rc = _libssh2_transport_read(session);
+        while(rc > 0);
+
+        if((rc < 0) && (rc != LIBSSH2_ERROR_EAGAIN)) {
+            return _libssh2_error(channel->session, rc,
+                                  "Failure while draining incoming flow");
+        }
+
+        if(channel->local.window_size <= 0) {
+            /* there's no room for data so we stop */
+
+            /* Waiting on the socket to be writable would be wrong because we
+             * would be back here immediately, but a readable socket might
+             * herald an incoming window adjustment.
+             */
+            session->socket_block_directions = LIBSSH2_SESSION_BLOCK_INBOUND;
+
+            return (rc == LIBSSH2_ERROR_EAGAIN?rc:0);
+        }
+
+        channel->write_bufwrite = buflen;
+
+        *(s++) = stream_id ? SSH_MSG_CHANNEL_EXTENDED_DATA :
+            SSH_MSG_CHANNEL_DATA;
+        _libssh2_store_u32(&s, channel->remote.id);
+        if(stream_id)
+            _libssh2_store_u32(&s, stream_id);
+
+        /* Don't exceed the remote end's limits */
+        /* REMEMBER local means local as the SOURCE of the data */
+        if(channel->write_bufwrite > channel->local.window_size) {
+            _libssh2_debug(session, LIBSSH2_TRACE_CONN,
+                           "Splitting write block due to %lu byte "
+                           "window_size on %lu/%lu/%d",
+                           channel->local.window_size, channel->local.id,
+                           channel->remote.id, stream_id);
+            channel->write_bufwrite = channel->local.window_size;
+        }
+        if(channel->write_bufwrite > channel->local.packet_size) {
+            _libssh2_debug(session, LIBSSH2_TRACE_CONN,
+                           "Splitting write block due to %lu byte "
+                           "packet_size on %lu/%lu/%d",
+                           channel->local.packet_size, channel->local.id,
+                           channel->remote.id, stream_id);
+            channel->write_bufwrite = channel->local.packet_size;
+        }
+        /* store the size here only, the buffer is passed in as-is to
+           _libssh2_transport_send() */
+        _libssh2_store_u32(&s, channel->write_bufwrite);
+        channel->write_packet_len = s - channel->write_packet;
+
+        _libssh2_debug(session, LIBSSH2_TRACE_CONN,
+                       "Sending %d bytes on channel %lu/%lu, stream_id=%d",
+                       (int) channel->write_bufwrite, channel->local.id,
+                       channel->remote.id, stream_id);
+
+        channel->write_state = libssh2_NB_state_created;
+    }
+
+    if(channel->write_state == libssh2_NB_state_created) {
+        rc = _libssh2_transport_send(session, channel->write_packet,
+                                     channel->write_packet_len,
+                                     buf, channel->write_bufwrite);
+        if(rc == LIBSSH2_ERROR_EAGAIN) {
+            return _libssh2_error(session, rc,
+                                  "Unable to send channel data");
+        }
+        else if(rc) {
+            channel->write_state = libssh2_NB_state_idle;
+            return _libssh2_error(session, rc,
+                                  "Unable to send channel data");
+        }
+        /* Shrink local window size */
+        channel->local.window_size -= channel->write_bufwrite;
+
+        wrote += channel->write_bufwrite;
+
+        /* Since _libssh2_transport_write() succeeded, we must return
+           now to allow the caller to provide the next chunk of data.
+
+           We cannot move on to send the next piece of data that may
+           already have been provided in this same function call, as we
+           risk getting EAGAIN for that and we can't return information
+           both about sent data as well as EAGAIN. So, by returning short
+           now, the caller will call this function again with new data to
+           send */
+
+        channel->write_state = libssh2_NB_state_idle;
+
+        return wrote;
+    }
+
+    return LIBSSH2_ERROR_INVAL; /* reaching this point is really bad */
+}
+
+/*
+ * libssh2_channel_write_ex
+ *
+ * Send data to a channel
+ */
+LIBSSH2_API ssize_t
+libssh2_channel_write_ex(LIBSSH2_CHANNEL *channel, int stream_id,
+                         const char *buf, size_t buflen)
+{
+    ssize_t rc;
+
+    if(!channel)
+        return LIBSSH2_ERROR_BAD_USE;
+
+    BLOCK_ADJUST(rc, channel->session,
+                 _libssh2_channel_write(channel, stream_id,
+                                        (unsigned char *)buf, buflen));
+    return rc;
+}
+
+/*
+ * channel_send_eof
+ *
+ * Send EOF on channel
+ */
+static int channel_send_eof(LIBSSH2_CHANNEL *channel)
+{
+    LIBSSH2_SESSION *session = channel->session;
+    unsigned char packet[5];    /* packet_type(1) + channelno(4) */
+    int rc;
+
+    _libssh2_debug(session, LIBSSH2_TRACE_CONN,
+                   "Sending EOF on channel %lu/%lu",
+                   channel->local.id, channel->remote.id);
+    packet[0] = SSH_MSG_CHANNEL_EOF;
+    _libssh2_htonu32(packet + 1, channel->remote.id);
+    rc = _libssh2_transport_send(session, packet, 5, NULL, 0);
+    if(rc == LIBSSH2_ERROR_EAGAIN) {
+        _libssh2_error(session, rc,
+                       "Would block sending EOF");
+        return rc;
+    }
+    else if(rc) {
+        return _libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND,
+                              "Unable to send EOF on channel");
+    }
+    channel->local.eof = 1;
+
+    return 0;
+}
+
+/*
+ * libssh2_channel_send_eof
+ *
+ * Send EOF on channel
+ */
+LIBSSH2_API int
+libssh2_channel_send_eof(LIBSSH2_CHANNEL *channel)
+{
+    int rc;
+
+    if(!channel)
+        return LIBSSH2_ERROR_BAD_USE;
+
+    BLOCK_ADJUST(rc, channel->session, channel_send_eof(channel));
+    return rc;
+}
+
+/*
+ * libssh2_channel_eof
+ *
+ * Read channel's eof status
+ */
+LIBSSH2_API int
+libssh2_channel_eof(LIBSSH2_CHANNEL * channel)
+{
+    LIBSSH2_SESSION *session;
+    LIBSSH2_PACKET *packet;
+    LIBSSH2_PACKET *next_packet;
+
+    if(!channel)
+        return LIBSSH2_ERROR_BAD_USE;
+
+    session = channel->session;
+    packet = _libssh2_list_first(&session->packets);
+
+    while(packet) {
+
+        next_packet = _libssh2_list_next(&packet->node);
+
+        if(packet->data_len < 1) {
+            packet = next_packet;
+            _libssh2_debug(channel->session, LIBSSH2_TRACE_ERROR,
+                           "Unexpected packet length");
+            continue;
+        }
+
+        if(((packet->data[0] == SSH_MSG_CHANNEL_DATA)
+            || (packet->data[0] == SSH_MSG_CHANNEL_EXTENDED_DATA))
+            && ((packet->data_len >= 5)
+            && (channel->local.id == _libssh2_ntohu32(packet->data + 1)))) {
+            /* There's data waiting to be read yet, mask the EOF status */
+            return 0;
+        }
+        packet = next_packet;
+    }
+
+    return channel->remote.eof;
+}
+
+/*
+ * channel_wait_eof
+ *
+ * Awaiting channel EOF
+ */
+static int channel_wait_eof(LIBSSH2_CHANNEL *channel)
+{
+    LIBSSH2_SESSION *session = channel->session;
+    int rc;
+
+    if(channel->wait_eof_state == libssh2_NB_state_idle) {
+        _libssh2_debug(session, LIBSSH2_TRACE_CONN,
+                       "Awaiting EOF for channel %lu/%lu", channel->local.id,
+                       channel->remote.id);
+
+        channel->wait_eof_state = libssh2_NB_state_created;
+    }
+
+    /*
+     * While channel is not eof, read more packets from the network.
+     * Either the EOF will be set or network timeout will occur.
+     */
+    do {
+        if(channel->remote.eof) {
+            break;
+        }
+
+        if((channel->remote.window_size == channel->read_avail) &&
+            session->api_block_mode)
+            return _libssh2_error(session, LIBSSH2_ERROR_CHANNEL_WINDOW_FULL,
+                                  "Receiving channel window "
+                                  "has been exhausted");
+
+        rc = _libssh2_transport_read(session);
+        if(rc == LIBSSH2_ERROR_EAGAIN) {
+            return rc;
+        }
+        else if(rc < 0) {
+            channel->wait_eof_state = libssh2_NB_state_idle;
+            return _libssh2_error(session, rc,
+                                  "_libssh2_transport_read() bailed out!");
+        }
+    } while(1);
+
+    channel->wait_eof_state = libssh2_NB_state_idle;
+
+    return 0;
+}
+
+/*
+ * libssh2_channel_wait_eof
+ *
+ * Awaiting channel EOF
+ */
+LIBSSH2_API int
+libssh2_channel_wait_eof(LIBSSH2_CHANNEL *channel)
+{
+    int rc;
+
+    if(!channel)
+        return LIBSSH2_ERROR_BAD_USE;
+
+    BLOCK_ADJUST(rc, channel->session, channel_wait_eof(channel));
+    return rc;
+}
+
+int _libssh2_channel_close(LIBSSH2_CHANNEL * channel)
+{
+    LIBSSH2_SESSION *session = channel->session;
+    int rc = 0;
+
+    if(channel->local.close) {
+        /* Already closed, act like we sent another close,
+         * even though we didn't... shhhhhh */
+        channel->close_state = libssh2_NB_state_idle;
+        return 0;
+    }
+
+    if(!channel->local.eof) {
+        rc = channel_send_eof(channel);
+        if(rc) {
+            if(rc == LIBSSH2_ERROR_EAGAIN) {
+                return rc;
+            }
+            _libssh2_error(session, rc,
+                "Unable to send EOF, but closing channel anyway");
+        }
+    }
+
+    /* ignore if we have received a remote eof or not, as it is now too
+       late for us to wait for it. Continue closing! */
+
+    if(channel->close_state == libssh2_NB_state_idle) {
+        _libssh2_debug(session, LIBSSH2_TRACE_CONN, "Closing channel %lu/%lu",
+                       channel->local.id, channel->remote.id);
+
+        channel->close_packet[0] = SSH_MSG_CHANNEL_CLOSE;
+        _libssh2_htonu32(channel->close_packet + 1, channel->remote.id);
+
+        channel->close_state = libssh2_NB_state_created;
+    }
+
+    if(channel->close_state == libssh2_NB_state_created) {
+        rc = _libssh2_transport_send(session, channel->close_packet, 5,
+                                     NULL, 0);
+        if(rc == LIBSSH2_ERROR_EAGAIN) {
+            _libssh2_error(session, rc,
+                           "Would block sending close-channel");
+            return rc;
+
+        }
+        else if(rc) {
+            _libssh2_error(session, rc,
+                           "Unable to send close-channel request, "
+                           "but closing anyway");
+            /* skip waiting for the response and fall through to
+               LIBSSH2_CHANNEL_CLOSE below */
+
+        }
+        else
+            channel->close_state = libssh2_NB_state_sent;
+    }
+
+    if(channel->close_state == libssh2_NB_state_sent) {
+        /* We must wait for the remote SSH_MSG_CHANNEL_CLOSE message */
+
+        while(!channel->remote.close && !rc &&
+               (session->socket_state != LIBSSH2_SOCKET_DISCONNECTED))
+            rc = _libssh2_transport_read(session);
+    }
+
+    if(rc != LIBSSH2_ERROR_EAGAIN) {
+        /* set the local close state first when we're perfectly confirmed to
+           not do any more EAGAINs */
+        channel->local.close = 1;
+
+        /* We call the callback last in this function to make it keep the local
+           data as long as EAGAIN is returned. */
+        if(channel->close_cb) {
+            LIBSSH2_CHANNEL_CLOSE(session, channel);
+        }
+
+        channel->close_state = libssh2_NB_state_idle;
+    }
+
+    /* return 0 or an error */
+    return rc >= 0 ? 0 : rc;
+}
+
+/*
+ * libssh2_channel_close
+ *
+ * Close a channel
+ */
+LIBSSH2_API int
+libssh2_channel_close(LIBSSH2_CHANNEL *channel)
+{
+    int rc;
+
+    if(!channel)
+        return LIBSSH2_ERROR_BAD_USE;
+
+    BLOCK_ADJUST(rc, channel->session, _libssh2_channel_close(channel) );
+    return rc;
+}
+
+/*
+ * channel_wait_closed
+ *
+ * Awaiting channel close after EOF
+ */
+static int channel_wait_closed(LIBSSH2_CHANNEL *channel)
+{
+    LIBSSH2_SESSION *session = channel->session;
+    int rc;
+
+    if(!channel->remote.eof) {
+        return _libssh2_error(session, LIBSSH2_ERROR_INVAL,
+                              "libssh2_channel_wait_closed() invoked when "
+                              "channel is not in EOF state");
+    }
+
+    if(channel->wait_closed_state == libssh2_NB_state_idle) {
+        _libssh2_debug(session, LIBSSH2_TRACE_CONN,
+                       "Awaiting close of channel %lu/%lu", channel->local.id,
+                       channel->remote.id);
+
+        channel->wait_closed_state = libssh2_NB_state_created;
+    }
+
+    /*
+     * While channel is not closed, read more packets from the network.
+     * Either the channel will be closed or network timeout will occur.
+     */
+    if(!channel->remote.close) {
+        do {
+            rc = _libssh2_transport_read(session);
+            if(channel->remote.close)
+                /* it is now closed, move on! */
+                break;
+        } while(rc > 0);
+        if(rc < 0)
+            return rc;
+    }
+
+    channel->wait_closed_state = libssh2_NB_state_idle;
+
+    return 0;
+}
+
+/*
+ * libssh2_channel_wait_closed
+ *
+ * Awaiting channel close after EOF
+ */
+LIBSSH2_API int
+libssh2_channel_wait_closed(LIBSSH2_CHANNEL *channel)
+{
+    int rc;
+
+    if(!channel)
+        return LIBSSH2_ERROR_BAD_USE;
+
+    BLOCK_ADJUST(rc, channel->session, channel_wait_closed(channel));
+    return rc;
+}
+
+/*
+ * _libssh2_channel_free
+ *
+ * Make sure a channel is closed, then remove the channel from the session
+ * and free its resource(s)
+ *
+ * Returns 0 on success, negative on failure
+ */
+int _libssh2_channel_free(LIBSSH2_CHANNEL *channel)
+{
+    LIBSSH2_SESSION *session = channel->session;
+    unsigned char channel_id[4];
+    unsigned char *data;
+    size_t data_len;
+    int rc;
+
+    assert(session);
+
+    if(channel->free_state == libssh2_NB_state_idle) {
+        _libssh2_debug(session, LIBSSH2_TRACE_CONN,
+                       "Freeing channel %lu/%lu resources", channel->local.id,
+                       channel->remote.id);
+
+        channel->free_state = libssh2_NB_state_created;
+    }
+
+    /* Allow channel freeing even when the socket has lost its connection */
+    if(!channel->local.close
+        && (session->socket_state == LIBSSH2_SOCKET_CONNECTED)) {
+        rc = _libssh2_channel_close(channel);
+
+        if(rc == LIBSSH2_ERROR_EAGAIN)
+            return rc;
+
+        /* ignore all other errors as they otherwise risk blocking the channel
+           free from happening */
+    }
+
+    channel->free_state = libssh2_NB_state_idle;
+
+    if(channel->exit_signal) {
+        LIBSSH2_FREE(session, channel->exit_signal);
+    }
+
+    /*
+     * channel->remote.close *might* not be set yet, Well...
+     * We've sent the close packet, what more do you want?
+     * Just let packet_add ignore it when it finally arrives
+     */
+
+    /* Clear out packets meant for this channel */
+    _libssh2_htonu32(channel_id, channel->local.id);
+    while((_libssh2_packet_ask(session, SSH_MSG_CHANNEL_DATA, &data,
+                                &data_len, 1, channel_id, 4) >= 0)
+           ||
+           (_libssh2_packet_ask(session, SSH_MSG_CHANNEL_EXTENDED_DATA, &data,
+                                &data_len, 1, channel_id, 4) >= 0)) {
+        LIBSSH2_FREE(session, data);
+    }
+
+    /* free "channel_type" */
+    if(channel->channel_type) {
+        LIBSSH2_FREE(session, channel->channel_type);
+    }
+
+    /* Unlink from channel list */
+    _libssh2_list_remove(&channel->node);
+
+    /*
+     * Make sure all memory used in the state variables are free
+     */
+    if(channel->setenv_packet) {
+        LIBSSH2_FREE(session, channel->setenv_packet);
+    }
+    if(channel->reqX11_packet) {
+        LIBSSH2_FREE(session, channel->reqX11_packet);
+    }
+    if(channel->process_packet) {
+        LIBSSH2_FREE(session, channel->process_packet);
+    }
+
+    LIBSSH2_FREE(session, channel);
+
+    return 0;
+}
+
+/*
+ * libssh2_channel_free
+ *
+ * Make sure a channel is closed, then remove the channel from the session
+ * and free its resource(s)
+ *
+ * Returns 0 on success, negative on failure
+ */
+LIBSSH2_API int
+libssh2_channel_free(LIBSSH2_CHANNEL *channel)
+{
+    int rc;
+
+    if(!channel)
+        return LIBSSH2_ERROR_BAD_USE;
+
+    BLOCK_ADJUST(rc, channel->session, _libssh2_channel_free(channel));
+    return rc;
+}
+/*
+ * libssh2_channel_window_read_ex
+ *
+ * Check the status of the read window. Returns the number of bytes which the
+ * remote end may send without overflowing the window limit read_avail (if
+ * passed) will be populated with the number of bytes actually available to be
+ * read window_size_initial (if passed) will be populated with the
+ * window_size_initial as defined by the channel_open request
+ */
+LIBSSH2_API unsigned long
+libssh2_channel_window_read_ex(LIBSSH2_CHANNEL *channel,
+                               unsigned long *read_avail,
+                               unsigned long *window_size_initial)
+{
+    if(!channel)
+        return 0; /* no channel, no window! */
+
+    if(window_size_initial) {
+        *window_size_initial = channel->remote.window_size_initial;
+    }
+
+    if(read_avail) {
+        size_t bytes_queued = 0;
+        LIBSSH2_PACKET *next_packet;
+        LIBSSH2_PACKET *packet =
+            _libssh2_list_first(&channel->session->packets);
+
+        while(packet) {
+            unsigned char packet_type;
+               next_packet = _libssh2_list_next(&packet->node);
+
+            if(packet->data_len < 1) {
+                packet = next_packet;
+                _libssh2_debug(channel->session, LIBSSH2_TRACE_ERROR,
+                               "Unexpected packet length");
+                continue;
+            }
+
+            packet_type = packet->data[0];
+
+            if(((packet_type == SSH_MSG_CHANNEL_DATA)
+                || (packet_type == SSH_MSG_CHANNEL_EXTENDED_DATA))
+               && ((packet->data_len >= 5)
+                   && (_libssh2_ntohu32(packet->data + 1) ==
+                       channel->local.id))) {
+                bytes_queued += packet->data_len - packet->data_head;
+            }
+
+            packet = next_packet;
+        }
+
+        *read_avail = bytes_queued;
+    }
+
+    return channel->remote.window_size;
+}
+
+/*
+ * libssh2_channel_window_write_ex
+ *
+ * Check the status of the write window Returns the number of bytes which may
+ * be safely written on the channel without blocking window_size_initial (if
+ * passed) will be populated with the size of the initial window as defined by
+ * the channel_open request
+ */
+LIBSSH2_API unsigned long
+libssh2_channel_window_write_ex(LIBSSH2_CHANNEL *channel,
+                                unsigned long *window_size_initial)
+{
+    if(!channel)
+        return 0; /* no channel, no window! */
+
+    if(window_size_initial) {
+        /* For locally initiated channels this is very often 0, so it's not
+         * *that* useful as information goes */
+        *window_size_initial = channel->local.window_size_initial;
+    }
+
+    return channel->local.window_size;
+}

+ 141 - 0
libssh2/libssh2/src/channel.h

@@ -0,0 +1,141 @@
+#ifndef __LIBSSH2_CHANNEL_H
+#define __LIBSSH2_CHANNEL_H
+/* Copyright (c) 2008-2010 by Daniel Stenberg
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms,
+ * with or without modification, are permitted provided
+ * that the following conditions are met:
+ *
+ *   Redistributions of source code must retain the above
+ *   copyright notice, this list of conditions and the
+ *   following disclaimer.
+ *
+ *   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.
+ *
+ *   Neither the name of the copyright holder nor the names
+ *   of any other contributors may be used to endorse or
+ *   promote products derived from this software without
+ *   specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+ * CONTRIBUTORS "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 COPYRIGHT OWNER OR
+ * CONTRIBUTORS 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.
+ */
+
+/*
+ * _libssh2_channel_receive_window_adjust
+ *
+ * Adjust the receive window for a channel by adjustment bytes. If the amount
+ * to be adjusted is less than LIBSSH2_CHANNEL_MINADJUST and force is 0 the
+ * adjustment amount will be queued for a later packet.
+ *
+ * Always non-blocking.
+ */
+int _libssh2_channel_receive_window_adjust(LIBSSH2_CHANNEL * channel,
+                                           uint32_t adjustment,
+                                           unsigned char force,
+                                           unsigned int *store);
+
+/*
+ * _libssh2_channel_flush
+ *
+ * Flush data from one (or all) stream
+ * Returns number of bytes flushed, or negative on failure
+ */
+int _libssh2_channel_flush(LIBSSH2_CHANNEL *channel, int streamid);
+
+/*
+ * _libssh2_channel_free
+ *
+ * Make sure a channel is closed, then remove the channel from the session
+ * and free its resource(s)
+ *
+ * Returns 0 on success, negative on failure
+ */
+int _libssh2_channel_free(LIBSSH2_CHANNEL *channel);
+
+int
+_libssh2_channel_extended_data(LIBSSH2_CHANNEL *channel, int ignore_mode);
+
+/*
+ * _libssh2_channel_write
+ *
+ * Send data to a channel
+ */
+ssize_t
+_libssh2_channel_write(LIBSSH2_CHANNEL *channel, int stream_id,
+                       const unsigned char *buf, size_t buflen);
+
+/*
+ * _libssh2_channel_open
+ *
+ * Establish a generic session channel
+ */
+LIBSSH2_CHANNEL *
+_libssh2_channel_open(LIBSSH2_SESSION * session, const char *channel_type,
+                      uint32_t channel_type_len,
+                      uint32_t window_size,
+                      uint32_t packet_size,
+                      const unsigned char *message, size_t message_len);
+
+
+/*
+ * _libssh2_channel_process_startup
+ *
+ * Primitive for libssh2_channel_(shell|exec|subsystem)
+ */
+int
+_libssh2_channel_process_startup(LIBSSH2_CHANNEL *channel,
+                                 const char *request, size_t request_len,
+                                 const char *message, size_t message_len);
+
+/*
+ * _libssh2_channel_read
+ *
+ * Read data from a channel
+ *
+ * It is important to not return 0 until the currently read channel is
+ * complete. If we read stuff from the wire but it was no payload data to fill
+ * in the buffer with, we MUST make sure to return PACKET_EAGAIN.
+ */
+ssize_t _libssh2_channel_read(LIBSSH2_CHANNEL *channel, int stream_id,
+                              char *buf, size_t buflen);
+
+uint32_t _libssh2_channel_nextid(LIBSSH2_SESSION * session);
+
+LIBSSH2_CHANNEL *_libssh2_channel_locate(LIBSSH2_SESSION * session,
+                                         uint32_t channel_id);
+
+size_t _libssh2_channel_packet_data_len(LIBSSH2_CHANNEL * channel,
+                                        int stream_id);
+
+int _libssh2_channel_close(LIBSSH2_CHANNEL * channel);
+
+/*
+ * _libssh2_channel_forward_cancel
+ *
+ * Stop listening on a remote port and free the listener
+ * Toss out any pending (un-accept()ed) connections
+ *
+ * Return 0 on success, LIBSSH2_ERROR_EAGAIN if would block, -1 on error
+ */
+int _libssh2_channel_forward_cancel(LIBSSH2_LISTENER *listener);
+
+#endif /* __LIBSSH2_CHANNEL_H */
+

+ 376 - 0
libssh2/libssh2/src/comp.c

@@ -0,0 +1,376 @@
+/* Copyright (c) 2004-2007, 2019, Sara Golemon <sarag@libssh2.org>
+ * Copyright (c) 2010-2014, Daniel Stenberg <daniel@haxx.se>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms,
+ * with or without modification, are permitted provided
+ * that the following conditions are met:
+ *
+ *   Redistributions of source code must retain the above
+ *   copyright notice, this list of conditions and the
+ *   following disclaimer.
+ *
+ *   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.
+ *
+ *   Neither the name of the copyright holder nor the names
+ *   of any other contributors may be used to endorse or
+ *   promote products derived from this software without
+ *   specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+ * CONTRIBUTORS "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 COPYRIGHT OWNER OR
+ * CONTRIBUTORS 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 "libssh2_priv.h"
+#ifdef LIBSSH2_HAVE_ZLIB
+# include <zlib.h>
+#endif
+
+#include "comp.h"
+
+/* ********
+ * none *
+ ******** */
+
+/*
+ * comp_method_none_comp
+ *
+ * Minimalist compression: Absolutely none
+ */
+static int
+comp_method_none_comp(LIBSSH2_SESSION *session,
+                      unsigned char *dest,
+                      size_t *dest_len,
+                      const unsigned char *src,
+                      size_t src_len,
+                      void **abstract)
+{
+    (void) session;
+    (void) abstract;
+    (void) dest;
+    (void) dest_len;
+    (void) src;
+    (void) src_len;
+
+    return 0;
+}
+
+/*
+ * comp_method_none_decomp
+ *
+ * Minimalist decompression: Absolutely none
+ */
+static int
+comp_method_none_decomp(LIBSSH2_SESSION * session,
+                        unsigned char **dest,
+                        size_t *dest_len,
+                        size_t payload_limit,
+                        const unsigned char *src,
+                        size_t src_len, void **abstract)
+{
+    (void) session;
+    (void) payload_limit;
+    (void) abstract;
+    *dest = (unsigned char *) src;
+    *dest_len = src_len;
+    return 0;
+}
+
+
+
+static const LIBSSH2_COMP_METHOD comp_method_none = {
+    "none",
+    0, /* not really compressing */
+    0, /* isn't used in userauth, go figure */
+    NULL,
+    comp_method_none_comp,
+    comp_method_none_decomp,
+    NULL
+};
+
+#ifdef LIBSSH2_HAVE_ZLIB
+/* ********
+ * zlib *
+ ******** */
+
+/* Memory management wrappers
+ * Yes, I realize we're doing a callback to a callback,
+ * Deal...
+ */
+
+static voidpf
+comp_method_zlib_alloc(voidpf opaque, uInt items, uInt size)
+{
+    LIBSSH2_SESSION *session = (LIBSSH2_SESSION *) opaque;
+
+    return (voidpf) LIBSSH2_ALLOC(session, items * size);
+}
+
+static void
+comp_method_zlib_free(voidpf opaque, voidpf address)
+{
+    LIBSSH2_SESSION *session = (LIBSSH2_SESSION *) opaque;
+
+    LIBSSH2_FREE(session, address);
+}
+
+
+
+/* libssh2_comp_method_zlib_init
+ * All your bandwidth are belong to us (so save some)
+ */
+static int
+comp_method_zlib_init(LIBSSH2_SESSION * session, int compr,
+                      void **abstract)
+{
+    z_stream *strm;
+    int status;
+
+    strm = LIBSSH2_CALLOC(session, sizeof(z_stream));
+    if(!strm) {
+        return _libssh2_error(session, LIBSSH2_ERROR_ALLOC,
+                              "Unable to allocate memory for "
+                              "zlib compression/decompression");
+    }
+
+    strm->opaque = (voidpf) session;
+    strm->zalloc = (alloc_func) comp_method_zlib_alloc;
+    strm->zfree = (free_func) comp_method_zlib_free;
+    if(compr) {
+        /* deflate */
+        status = deflateInit(strm, Z_DEFAULT_COMPRESSION);
+    }
+    else {
+        /* inflate */
+        status = inflateInit(strm);
+    }
+
+    if(status != Z_OK) {
+        LIBSSH2_FREE(session, strm);
+        _libssh2_debug(session, LIBSSH2_TRACE_TRANS,
+                       "unhandled zlib error %d", status);
+        return LIBSSH2_ERROR_COMPRESS;
+    }
+    *abstract = strm;
+
+    return LIBSSH2_ERROR_NONE;
+}
+
+/*
+ * libssh2_comp_method_zlib_comp
+ *
+ * Compresses source to destination. Without allocation.
+ */
+static int
+comp_method_zlib_comp(LIBSSH2_SESSION *session,
+                      unsigned char *dest,
+
+                      /* dest_len is a pointer to allow this function to
+                         update it with the final actual size used */
+                      size_t *dest_len,
+                      const unsigned char *src,
+                      size_t src_len,
+                      void **abstract)
+{
+    z_stream *strm = *abstract;
+    int out_maxlen = *dest_len;
+    int status;
+
+    strm->next_in = (unsigned char *) src;
+    strm->avail_in = src_len;
+    strm->next_out = dest;
+    strm->avail_out = out_maxlen;
+
+    status = deflate(strm, Z_PARTIAL_FLUSH);
+
+    if((status == Z_OK) && (strm->avail_out > 0)) {
+        *dest_len = out_maxlen - strm->avail_out;
+        return 0;
+    }
+
+    _libssh2_debug(session, LIBSSH2_TRACE_TRANS,
+                   "unhandled zlib compression error %d, avail_out",
+                   status, strm->avail_out);
+    return _libssh2_error(session, LIBSSH2_ERROR_ZLIB, "compression failure");
+}
+
+/*
+ * libssh2_comp_method_zlib_decomp
+ *
+ * Decompresses source to destination. Allocates the output memory.
+ */
+static int
+comp_method_zlib_decomp(LIBSSH2_SESSION * session,
+                        unsigned char **dest,
+                        size_t *dest_len,
+                        size_t payload_limit,
+                        const unsigned char *src,
+                        size_t src_len, void **abstract)
+{
+    z_stream *strm = *abstract;
+    /* A short-term alloc of a full data chunk is better than a series of
+       reallocs */
+    char *out;
+    size_t out_maxlen = src_len;
+
+    if(src_len <= SIZE_MAX / 4)
+        out_maxlen = src_len * 4;
+    else
+        out_maxlen = payload_limit;
+
+    /* If strm is null, then we have not yet been initialized. */
+    if(strm == NULL)
+        return _libssh2_error(session, LIBSSH2_ERROR_COMPRESS,
+                              "decompression uninitialized");;
+
+    /* In practice they never come smaller than this */
+    if(out_maxlen < 25)
+        out_maxlen = 25;
+
+    if(out_maxlen > payload_limit)
+        out_maxlen = payload_limit;
+
+    strm->next_in = (unsigned char *) src;
+    strm->avail_in = src_len;
+    strm->next_out = (unsigned char *) LIBSSH2_ALLOC(session, out_maxlen);
+    out = (char *) strm->next_out;
+    strm->avail_out = out_maxlen;
+    if(!strm->next_out)
+        return _libssh2_error(session, LIBSSH2_ERROR_ALLOC,
+                              "Unable to allocate decompression buffer");
+
+    /* Loop until it's all inflated or hit error */
+    for(;;) {
+        int status;
+        size_t out_ofs;
+        char *newout;
+
+        status = inflate(strm, Z_PARTIAL_FLUSH);
+
+        if(status == Z_OK) {
+            if(strm->avail_out > 0)
+                /* status is OK and the output buffer has not been exhausted
+                   so we're done */
+                break;
+        }
+        else if(status == Z_BUF_ERROR) {
+            /* the input data has been exhausted so we are done */
+            break;
+        }
+        else {
+            /* error state */
+            LIBSSH2_FREE(session, out);
+            _libssh2_debug(session, LIBSSH2_TRACE_TRANS,
+                           "unhandled zlib error %d", status);
+            return _libssh2_error(session, LIBSSH2_ERROR_ZLIB,
+                                  "decompression failure");
+        }
+
+        if(out_maxlen > payload_limit || out_maxlen > SIZE_MAX / 2) {
+            LIBSSH2_FREE(session, out);
+            return _libssh2_error(session, LIBSSH2_ERROR_ZLIB,
+                                  "Excessive growth in decompression phase");
+        }
+
+        /* If we get here we need to grow the output buffer and try again */
+        out_ofs = out_maxlen - strm->avail_out;
+        out_maxlen *= 2;
+        newout = LIBSSH2_REALLOC(session, out, out_maxlen);
+        if(!newout) {
+            LIBSSH2_FREE(session, out);
+            return _libssh2_error(session, LIBSSH2_ERROR_ALLOC,
+                                  "Unable to expand decompression buffer");
+        }
+        out = newout;
+        strm->next_out = (unsigned char *) out + out_ofs;
+        strm->avail_out = out_maxlen - out_ofs;
+    }
+
+    *dest = (unsigned char *) out;
+    *dest_len = out_maxlen - strm->avail_out;
+
+    return 0;
+}
+
+
+/* libssh2_comp_method_zlib_dtor
+ * All done, no more compression for you
+ */
+static int
+comp_method_zlib_dtor(LIBSSH2_SESSION *session, int compr, void **abstract)
+{
+    z_stream *strm = *abstract;
+
+    if(strm) {
+        if(compr)
+            deflateEnd(strm);
+        else
+            inflateEnd(strm);
+        LIBSSH2_FREE(session, strm);
+    }
+
+    *abstract = NULL;
+    return 0;
+}
+
+static const LIBSSH2_COMP_METHOD comp_method_zlib = {
+    "zlib",
+    1, /* yes, this compresses */
+    1, /* do compression during userauth */
+    comp_method_zlib_init,
+    comp_method_zlib_comp,
+    comp_method_zlib_decomp,
+    comp_method_zlib_dtor,
+};
+
+static const LIBSSH2_COMP_METHOD comp_method_zlib_openssh = {
+    "zlib@openssh.com",
+    1, /* yes, this compresses */
+    0, /* don't use compression during userauth */
+    comp_method_zlib_init,
+    comp_method_zlib_comp,
+    comp_method_zlib_decomp,
+    comp_method_zlib_dtor,
+};
+#endif /* LIBSSH2_HAVE_ZLIB */
+
+/* If compression is enabled by the API, then this array is used which then
+   may allow compression if zlib is available at build time */
+static const LIBSSH2_COMP_METHOD *comp_methods[] = {
+#ifdef LIBSSH2_HAVE_ZLIB
+    &comp_method_zlib,
+    &comp_method_zlib_openssh,
+#endif /* LIBSSH2_HAVE_ZLIB */
+    &comp_method_none,
+    NULL
+};
+
+/* If compression is disabled by the API, then this array is used */
+static const LIBSSH2_COMP_METHOD *no_comp_methods[] = {
+    &comp_method_none,
+    NULL
+};
+
+const LIBSSH2_COMP_METHOD **
+_libssh2_comp_methods(LIBSSH2_SESSION *session)
+{
+    if(session->flag.compress)
+        return comp_methods;
+    else
+        return no_comp_methods;
+}

+ 45 - 0
libssh2/libssh2/src/comp.h

@@ -0,0 +1,45 @@
+#ifndef __LIBSSH2_COMP_H
+#define __LIBSSH2_COMP_H
+
+/* Copyright (C) 2009-2010 by Daniel Stenberg
+ *
+ * Redistribution and use in source and binary forms,
+ * with or without modification, are permitted provided
+ * that the following conditions are met:
+ *
+ *   Redistributions of source code must retain the above
+ *   copyright notice, this list of conditions and the
+ *   following disclaimer.
+ *
+ *   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.
+ *
+ *   Neither the name of the copyright holder nor the names
+ *   of any other contributors may be used to endorse or
+ *   promote products derived from this software without
+ *   specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+ * CONTRIBUTORS "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 COPYRIGHT OWNER OR
+ * CONTRIBUTORS 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 "libssh2_priv.h"
+
+const LIBSSH2_COMP_METHOD **_libssh2_comp_methods(LIBSSH2_SESSION *session);
+
+#endif /* __LIBSSH2_COMP_H */

+ 349 - 0
libssh2/libssh2/src/crypt.c

@@ -0,0 +1,349 @@
+/* Copyright (c) 2009, 2010 Simon Josefsson <simon@josefsson.org>
+ * Copyright (c) 2004-2007, Sara Golemon <sarag@libssh2.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms,
+ * with or without modification, are permitted provided
+ * that the following conditions are met:
+ *
+ *   Redistributions of source code must retain the above
+ *   copyright notice, this list of conditions and the
+ *   following disclaimer.
+ *
+ *   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.
+ *
+ *   Neither the name of the copyright holder nor the names
+ *   of any other contributors may be used to endorse or
+ *   promote products derived from this software without
+ *   specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+ * CONTRIBUTORS "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 COPYRIGHT OWNER OR
+ * CONTRIBUTORS 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 "libssh2_priv.h"
+
+#ifdef LIBSSH2_CRYPT_NONE
+
+/* crypt_none_crypt
+ * Minimalist cipher: VERY secure *wink*
+ */
+static int
+crypt_none_crypt(LIBSSH2_SESSION * session, unsigned char *buf,
+                         void **abstract)
+{
+    /* Do nothing to the data! */
+    return 0;
+}
+
+static const LIBSSH2_CRYPT_METHOD libssh2_crypt_method_none = {
+    "none",
+    "DEK-Info: NONE",
+    8,                /* blocksize (SSH2 defines minimum blocksize as 8) */
+    0,                /* iv_len */
+    0,                /* secret_len */
+    0,                /* flags */
+    NULL,
+    crypt_none_crypt,
+    NULL
+};
+#endif /* LIBSSH2_CRYPT_NONE */
+
+struct crypt_ctx
+{
+    int encrypt;
+    _libssh2_cipher_type(algo);
+    _libssh2_cipher_ctx h;
+};
+
+static int
+crypt_init(LIBSSH2_SESSION * session,
+           const LIBSSH2_CRYPT_METHOD * method,
+           unsigned char *iv, int *free_iv,
+           unsigned char *secret, int *free_secret,
+           int encrypt, void **abstract)
+{
+    struct crypt_ctx *ctx = LIBSSH2_ALLOC(session,
+                                          sizeof(struct crypt_ctx));
+    if(!ctx)
+        return LIBSSH2_ERROR_ALLOC;
+
+    ctx->encrypt = encrypt;
+    ctx->algo = method->algo;
+    if(_libssh2_cipher_init(&ctx->h, ctx->algo, iv, secret, encrypt)) {
+        LIBSSH2_FREE(session, ctx);
+        return -1;
+    }
+    *abstract = ctx;
+    *free_iv = 1;
+    *free_secret = 1;
+    return 0;
+}
+
+static int
+crypt_encrypt(LIBSSH2_SESSION * session, unsigned char *block,
+              size_t blocksize, void **abstract)
+{
+    struct crypt_ctx *cctx = *(struct crypt_ctx **) abstract;
+    (void) session;
+    return _libssh2_cipher_crypt(&cctx->h, cctx->algo, cctx->encrypt, block,
+                                 blocksize);
+}
+
+static int
+crypt_dtor(LIBSSH2_SESSION * session, void **abstract)
+{
+    struct crypt_ctx **cctx = (struct crypt_ctx **) abstract;
+    if(cctx && *cctx) {
+        _libssh2_cipher_dtor(&(*cctx)->h);
+        LIBSSH2_FREE(session, *cctx);
+        *abstract = NULL;
+    }
+    return 0;
+}
+
+#if LIBSSH2_AES_CTR
+static const LIBSSH2_CRYPT_METHOD libssh2_crypt_method_aes128_ctr = {
+    "aes128-ctr",
+    "",
+    16,                         /* blocksize */
+    16,                         /* initial value length */
+    16,                         /* secret length -- 16*8 == 128bit */
+    0,                          /* flags */
+    &crypt_init,
+    &crypt_encrypt,
+    &crypt_dtor,
+    _libssh2_cipher_aes128ctr
+};
+
+static const LIBSSH2_CRYPT_METHOD libssh2_crypt_method_aes192_ctr = {
+    "aes192-ctr",
+    "",
+    16,                         /* blocksize */
+    16,                         /* initial value length */
+    24,                         /* secret length -- 24*8 == 192bit */
+    0,                          /* flags */
+    &crypt_init,
+    &crypt_encrypt,
+    &crypt_dtor,
+    _libssh2_cipher_aes192ctr
+};
+
+static const LIBSSH2_CRYPT_METHOD libssh2_crypt_method_aes256_ctr = {
+    "aes256-ctr",
+    "",
+    16,                         /* blocksize */
+    16,                         /* initial value length */
+    32,                         /* secret length -- 32*8 == 256bit */
+    0,                          /* flags */
+    &crypt_init,
+    &crypt_encrypt,
+    &crypt_dtor,
+    _libssh2_cipher_aes256ctr
+};
+#endif
+
+#if LIBSSH2_AES
+static const LIBSSH2_CRYPT_METHOD libssh2_crypt_method_aes128_cbc = {
+    "aes128-cbc",
+    "DEK-Info: AES-128-CBC",
+    16,                         /* blocksize */
+    16,                         /* initial value length */
+    16,                         /* secret length -- 16*8 == 128bit */
+    0,                          /* flags */
+    &crypt_init,
+    &crypt_encrypt,
+    &crypt_dtor,
+    _libssh2_cipher_aes128
+};
+
+static const LIBSSH2_CRYPT_METHOD libssh2_crypt_method_aes192_cbc = {
+    "aes192-cbc",
+    "DEK-Info: AES-192-CBC",
+    16,                         /* blocksize */
+    16,                         /* initial value length */
+    24,                         /* secret length -- 24*8 == 192bit */
+    0,                          /* flags */
+    &crypt_init,
+    &crypt_encrypt,
+    &crypt_dtor,
+    _libssh2_cipher_aes192
+};
+
+static const LIBSSH2_CRYPT_METHOD libssh2_crypt_method_aes256_cbc = {
+    "aes256-cbc",
+    "DEK-Info: AES-256-CBC",
+    16,                         /* blocksize */
+    16,                         /* initial value length */
+    32,                         /* secret length -- 32*8 == 256bit */
+    0,                          /* flags */
+    &crypt_init,
+    &crypt_encrypt,
+    &crypt_dtor,
+    _libssh2_cipher_aes256
+};
+
+/* rijndael-cbc@lysator.liu.se == aes256-cbc */
+static const LIBSSH2_CRYPT_METHOD
+    libssh2_crypt_method_rijndael_cbc_lysator_liu_se = {
+    "rijndael-cbc@lysator.liu.se",
+    "DEK-Info: AES-256-CBC",
+    16,                         /* blocksize */
+    16,                         /* initial value length */
+    32,                         /* secret length -- 32*8 == 256bit */
+    0,                          /* flags */
+    &crypt_init,
+    &crypt_encrypt,
+    &crypt_dtor,
+    _libssh2_cipher_aes256
+};
+#endif /* LIBSSH2_AES */
+
+#if LIBSSH2_BLOWFISH
+static const LIBSSH2_CRYPT_METHOD libssh2_crypt_method_blowfish_cbc = {
+    "blowfish-cbc",
+    "",
+    8,                          /* blocksize */
+    8,                          /* initial value length */
+    16,                         /* secret length */
+    0,                          /* flags */
+    &crypt_init,
+    &crypt_encrypt,
+    &crypt_dtor,
+    _libssh2_cipher_blowfish
+};
+#endif /* LIBSSH2_BLOWFISH */
+
+#if LIBSSH2_RC4
+static const LIBSSH2_CRYPT_METHOD libssh2_crypt_method_arcfour = {
+    "arcfour",
+    "DEK-Info: RC4",
+    8,                          /* blocksize */
+    8,                          /* initial value length */
+    16,                         /* secret length */
+    0,                          /* flags */
+    &crypt_init,
+    &crypt_encrypt,
+    &crypt_dtor,
+    _libssh2_cipher_arcfour
+};
+
+static int
+crypt_init_arcfour128(LIBSSH2_SESSION * session,
+                      const LIBSSH2_CRYPT_METHOD * method,
+                      unsigned char *iv, int *free_iv,
+                      unsigned char *secret, int *free_secret,
+                      int encrypt, void **abstract)
+{
+    int rc;
+
+    rc = crypt_init(session, method, iv, free_iv, secret, free_secret,
+                    encrypt, abstract);
+    if(rc == 0) {
+        struct crypt_ctx *cctx = *(struct crypt_ctx **) abstract;
+        unsigned char block[8];
+        size_t discard = 1536;
+        for(; discard; discard -= 8)
+            _libssh2_cipher_crypt(&cctx->h, cctx->algo, cctx->encrypt, block,
+                                  method->blocksize);
+    }
+
+    return rc;
+}
+
+static const LIBSSH2_CRYPT_METHOD libssh2_crypt_method_arcfour128 = {
+    "arcfour128",
+    "",
+    8,                          /* blocksize */
+    8,                          /* initial value length */
+    16,                         /* secret length */
+    0,                          /* flags */
+    &crypt_init_arcfour128,
+    &crypt_encrypt,
+    &crypt_dtor,
+    _libssh2_cipher_arcfour
+};
+#endif /* LIBSSH2_RC4 */
+
+#if LIBSSH2_CAST
+static const LIBSSH2_CRYPT_METHOD libssh2_crypt_method_cast128_cbc = {
+    "cast128-cbc",
+    "",
+    8,                          /* blocksize */
+    8,                          /* initial value length */
+    16,                         /* secret length */
+    0,                          /* flags */
+    &crypt_init,
+    &crypt_encrypt,
+    &crypt_dtor,
+    _libssh2_cipher_cast5
+};
+#endif /* LIBSSH2_CAST */
+
+#if LIBSSH2_3DES
+static const LIBSSH2_CRYPT_METHOD libssh2_crypt_method_3des_cbc = {
+    "3des-cbc",
+    "DEK-Info: DES-EDE3-CBC",
+    8,                          /* blocksize */
+    8,                          /* initial value length */
+    24,                         /* secret length */
+    0,                          /* flags */
+    &crypt_init,
+    &crypt_encrypt,
+    &crypt_dtor,
+    _libssh2_cipher_3des
+};
+#endif
+
+static const LIBSSH2_CRYPT_METHOD *_libssh2_crypt_methods[] = {
+#if LIBSSH2_AES_CTR
+  &libssh2_crypt_method_aes128_ctr,
+  &libssh2_crypt_method_aes192_ctr,
+  &libssh2_crypt_method_aes256_ctr,
+#endif /* LIBSSH2_AES */
+#if LIBSSH2_AES
+    &libssh2_crypt_method_aes256_cbc,
+    &libssh2_crypt_method_rijndael_cbc_lysator_liu_se,  /* == aes256-cbc */
+    &libssh2_crypt_method_aes192_cbc,
+    &libssh2_crypt_method_aes128_cbc,
+#endif /* LIBSSH2_AES */
+#if LIBSSH2_BLOWFISH
+    &libssh2_crypt_method_blowfish_cbc,
+#endif /* LIBSSH2_BLOWFISH */
+#if LIBSSH2_RC4
+    &libssh2_crypt_method_arcfour128,
+    &libssh2_crypt_method_arcfour,
+#endif /* LIBSSH2_RC4 */
+#if LIBSSH2_CAST
+    &libssh2_crypt_method_cast128_cbc,
+#endif /* LIBSSH2_CAST */
+#if LIBSSH2_3DES
+    &libssh2_crypt_method_3des_cbc,
+#endif /*  LIBSSH2_DES */
+#ifdef LIBSSH2_CRYPT_NONE
+    &libssh2_crypt_method_none,
+#endif
+    NULL
+};
+
+/* Expose to kex.c */
+const LIBSSH2_CRYPT_METHOD **
+libssh2_crypt_methods(void)
+{
+    return _libssh2_crypt_methods;
+}

+ 248 - 0
libssh2/libssh2/src/crypto.h

@@ -0,0 +1,248 @@
+/* Copyright (C) 2009, 2010 Simon Josefsson
+ * Copyright (C) 2006, 2007 The Written Word, Inc.  All rights reserved.
+ * Copyright (C) 2010-2019 Daniel Stenberg
+ *
+ * Redistribution and use in source and binary forms,
+ * with or without modification, are permitted provided
+ * that the following conditions are met:
+ *
+ *   Redistributions of source code must retain the above
+ *   copyright notice, this list of conditions and the
+ *   following disclaimer.
+ *
+ *   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.
+ *
+ *   Neither the name of the copyright holder nor the names
+ *   of any other contributors may be used to endorse or
+ *   promote products derived from this software without
+ *   specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+ * CONTRIBUTORS "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 COPYRIGHT OWNER OR
+ * CONTRIBUTORS 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 LIBSSH2_CRYPTO_H
+#define LIBSSH2_CRYPTO_H
+
+#ifdef LIBSSH2_OPENSSL
+#include "openssl.h"
+#endif
+
+#ifdef LIBSSH2_LIBGCRYPT
+#include "libgcrypt.h"
+#endif
+
+#ifdef LIBSSH2_WINCNG
+#include "wincng.h"
+#endif
+
+#ifdef LIBSSH2_OS400QC3
+#include "os400qc3.h"
+#endif
+
+#ifdef LIBSSH2_MBEDTLS
+#include "mbedtls.h"
+#endif
+
+#define LIBSSH2_ED25519_KEY_LEN 32
+#define LIBSSH2_ED25519_PRIVATE_KEY_LEN 64
+#define LIBSSH2_ED25519_SIG_LEN 64
+
+#if LIBSSH2_RSA
+int _libssh2_rsa_new(libssh2_rsa_ctx ** rsa,
+                     const unsigned char *edata,
+                     unsigned long elen,
+                     const unsigned char *ndata,
+                     unsigned long nlen,
+                     const unsigned char *ddata,
+                     unsigned long dlen,
+                     const unsigned char *pdata,
+                     unsigned long plen,
+                     const unsigned char *qdata,
+                     unsigned long qlen,
+                     const unsigned char *e1data,
+                     unsigned long e1len,
+                     const unsigned char *e2data,
+                     unsigned long e2len,
+                     const unsigned char *coeffdata, unsigned long coefflen);
+int _libssh2_rsa_new_private(libssh2_rsa_ctx ** rsa,
+                             LIBSSH2_SESSION * session,
+                             const char *filename,
+                             unsigned const char *passphrase);
+int _libssh2_rsa_sha1_verify(libssh2_rsa_ctx * rsa,
+                             const unsigned char *sig,
+                             unsigned long sig_len,
+                             const unsigned char *m, unsigned long m_len);
+int _libssh2_rsa_sha1_sign(LIBSSH2_SESSION * session,
+                           libssh2_rsa_ctx * rsactx,
+                           const unsigned char *hash,
+                           size_t hash_len,
+                           unsigned char **signature,
+                           size_t *signature_len);
+int _libssh2_rsa_new_private_frommemory(libssh2_rsa_ctx ** rsa,
+                                        LIBSSH2_SESSION * session,
+                                        const char *filedata,
+                                        size_t filedata_len,
+                                        unsigned const char *passphrase);
+#endif
+
+#if LIBSSH2_DSA
+int _libssh2_dsa_new(libssh2_dsa_ctx ** dsa,
+                     const unsigned char *pdata,
+                     unsigned long plen,
+                     const unsigned char *qdata,
+                     unsigned long qlen,
+                     const unsigned char *gdata,
+                     unsigned long glen,
+                     const unsigned char *ydata,
+                     unsigned long ylen,
+                     const unsigned char *x, unsigned long x_len);
+int _libssh2_dsa_new_private(libssh2_dsa_ctx ** dsa,
+                             LIBSSH2_SESSION * session,
+                             const char *filename,
+                             unsigned const char *passphrase);
+int _libssh2_dsa_sha1_verify(libssh2_dsa_ctx * dsactx,
+                             const unsigned char *sig,
+                             const unsigned char *m, unsigned long m_len);
+int _libssh2_dsa_sha1_sign(libssh2_dsa_ctx * dsactx,
+                           const unsigned char *hash,
+                           unsigned long hash_len, unsigned char *sig);
+int _libssh2_dsa_new_private_frommemory(libssh2_dsa_ctx ** dsa,
+                                        LIBSSH2_SESSION * session,
+                                        const char *filedata,
+                                        size_t filedata_len,
+                                        unsigned const char *passphrase);
+#endif
+
+#if LIBSSH2_ECDSA
+int
+_libssh2_ecdsa_curve_name_with_octal_new(libssh2_ecdsa_ctx ** ecdsactx,
+                                         const unsigned char *k,
+                                         size_t k_len,
+                                         libssh2_curve_type type);
+int
+_libssh2_ecdsa_new_private(libssh2_ecdsa_ctx ** ec_ctx,
+                           LIBSSH2_SESSION * session,
+                           const char *filename,
+                           unsigned const char *passphrase);
+
+int
+_libssh2_ecdsa_verify(libssh2_ecdsa_ctx * ctx,
+                      const unsigned char *r, size_t r_len,
+                      const unsigned char *s, size_t s_len,
+                      const unsigned char *m, size_t m_len);
+
+int
+_libssh2_ecdsa_create_key(LIBSSH2_SESSION *session,
+                          _libssh2_ec_key **out_private_key,
+                          unsigned char **out_public_key_octal,
+                          size_t *out_public_key_octal_len,
+                          libssh2_curve_type curve_type);
+
+int
+_libssh2_ecdh_gen_k(_libssh2_bn **k, _libssh2_ec_key *private_key,
+                    const unsigned char *server_public_key,
+                    size_t server_public_key_len);
+
+int
+_libssh2_ecdsa_sign(LIBSSH2_SESSION *session, libssh2_ecdsa_ctx *ec_ctx,
+                    const unsigned char *hash, unsigned long hash_len,
+                    unsigned char **signature, size_t *signature_len);
+
+int _libssh2_ecdsa_new_private_frommemory(libssh2_ecdsa_ctx ** ec_ctx,
+                                          LIBSSH2_SESSION * session,
+                                          const char *filedata,
+                                          size_t filedata_len,
+                                          unsigned const char *passphrase);
+
+libssh2_curve_type
+_libssh2_ecdsa_key_get_curve_type(_libssh2_ec_key *key);
+
+int
+_libssh2_ecdsa_curve_type_from_name(const char *name,
+                                    libssh2_curve_type *out_type);
+
+#endif /* LIBSSH2_ECDSA */
+
+#if LIBSSH2_ED25519
+
+int
+_libssh2_curve25519_new(LIBSSH2_SESSION *session, libssh2_ed25519_ctx **ctx,
+                        uint8_t **out_public_key, uint8_t **out_private_key);
+
+int
+_libssh2_curve25519_gen_k(_libssh2_bn **k,
+                          uint8_t private_key[LIBSSH2_ED25519_KEY_LEN],
+                          uint8_t server_public_key[LIBSSH2_ED25519_KEY_LEN]);
+
+int
+_libssh2_ed25519_verify(libssh2_ed25519_ctx *ctx, const uint8_t *s,
+                        size_t s_len, const uint8_t *m, size_t m_len);
+
+int
+_libssh2_ed25519_new_private(libssh2_ed25519_ctx **ed_ctx,
+                            LIBSSH2_SESSION *session,
+                            const char *filename, const uint8_t *passphrase);
+
+int
+_libssh2_ed25519_new_public(libssh2_ed25519_ctx **ed_ctx,
+                            LIBSSH2_SESSION *session,
+                            const unsigned char *raw_pub_key,
+                            const uint8_t key_len);
+
+int
+_libssh2_ed25519_sign(libssh2_ed25519_ctx *ctx, LIBSSH2_SESSION *session,
+                      uint8_t **out_sig, size_t *out_sig_len,
+                      const uint8_t *message, size_t message_len);
+
+int
+_libssh2_ed25519_new_private_frommemory(libssh2_ed25519_ctx **ed_ctx,
+                                        LIBSSH2_SESSION *session,
+                                        const char *filedata,
+                                        size_t filedata_len,
+                                        unsigned const char *passphrase);
+
+#endif /* LIBSSH2_ED25519 */
+
+
+int _libssh2_cipher_init(_libssh2_cipher_ctx * h,
+                         _libssh2_cipher_type(algo),
+                         unsigned char *iv,
+                         unsigned char *secret, int encrypt);
+
+int _libssh2_cipher_crypt(_libssh2_cipher_ctx * ctx,
+                          _libssh2_cipher_type(algo),
+                          int encrypt, unsigned char *block, size_t blocksize);
+
+int _libssh2_pub_priv_keyfile(LIBSSH2_SESSION *session,
+                              unsigned char **method,
+                              size_t *method_len,
+                              unsigned char **pubkeydata,
+                              size_t *pubkeydata_len,
+                              const char *privatekey,
+                              const char *passphrase);
+
+int _libssh2_pub_priv_keyfilememory(LIBSSH2_SESSION *session,
+                                    unsigned char **method,
+                                    size_t *method_len,
+                                    unsigned char **pubkeydata,
+                                    size_t *pubkeydata_len,
+                                    const char *privatekeydata,
+                                    size_t privatekeydata_len,
+                                    const char *passphrase);
+
+#endif

+ 77 - 0
libssh2/libssh2/src/global.c

@@ -0,0 +1,77 @@
+/* Copyright (c) 2010 Lars Nordin <Lars.Nordin@SDlabs.se>
+ * Copyright (C) 2010 Simon Josefsson <simon@josefsson.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms,
+ * with or without modification, are permitted provided
+ * that the following conditions are met:
+ *
+ *   Redistributions of source code must retain the above
+ *   copyright notice, this list of conditions and the
+ *   following disclaimer.
+ *
+ *   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.
+ *
+ *   Neither the name of the copyright holder nor the names
+ *   of any other contributors may be used to endorse or
+ *   promote products derived from this software without
+ *   specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+ * CONTRIBUTORS "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 COPYRIGHT OWNER OR
+ * CONTRIBUTORS 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 "libssh2_priv.h"
+
+static int _libssh2_initialized = 0;
+static int _libssh2_init_flags = 0;
+
+LIBSSH2_API int
+libssh2_init(int flags)
+{
+    if(_libssh2_initialized == 0 && !(flags & LIBSSH2_INIT_NO_CRYPTO)) {
+        libssh2_crypto_init();
+    }
+
+    _libssh2_initialized++;
+    _libssh2_init_flags |= flags;
+
+    return 0;
+}
+
+LIBSSH2_API void
+libssh2_exit(void)
+{
+    if(_libssh2_initialized == 0)
+        return;
+
+    _libssh2_initialized--;
+
+    if(!(_libssh2_init_flags & LIBSSH2_INIT_NO_CRYPTO)) {
+        libssh2_crypto_exit();
+    }
+
+    return;
+}
+
+void
+_libssh2_init_if_needed(void)
+{
+    if(_libssh2_initialized == 0)
+        (void)libssh2_init (0);
+}

+ 1129 - 0
libssh2/libssh2/src/hostkey.c

@@ -0,0 +1,1129 @@
+/* Copyright (c) 2004-2006, Sara Golemon <sarag@libssh2.org>
+ * Copyright (c) 2009-2019 by Daniel Stenberg
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms,
+ * with or without modification, are permitted provided
+ * that the following conditions are met:
+ *
+ *   Redistributions of source code must retain the above
+ *   copyright notice, this list of conditions and the
+ *   following disclaimer.
+ *
+ *   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.
+ *
+ *   Neither the name of the copyright holder nor the names
+ *   of any other contributors may be used to endorse or
+ *   promote products derived from this software without
+ *   specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+ * CONTRIBUTORS "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 COPYRIGHT OWNER OR
+ * CONTRIBUTORS 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 "libssh2_priv.h"
+#include "misc.h"
+
+/* Needed for struct iovec on some platforms */
+#ifdef HAVE_SYS_UIO_H
+#include <sys/uio.h>
+#endif
+
+#if LIBSSH2_RSA
+/* ***********
+ * ssh-rsa *
+ *********** */
+
+static int hostkey_method_ssh_rsa_dtor(LIBSSH2_SESSION * session,
+                                       void **abstract);
+
+/*
+ * hostkey_method_ssh_rsa_init
+ *
+ * Initialize the server hostkey working area with e/n pair
+ */
+static int
+hostkey_method_ssh_rsa_init(LIBSSH2_SESSION * session,
+                            const unsigned char *hostkey_data,
+                            size_t hostkey_data_len,
+                            void **abstract)
+{
+    libssh2_rsa_ctx *rsactx;
+    unsigned char *e, *n;
+    size_t e_len, n_len;
+    struct string_buf buf;
+
+    if(*abstract) {
+        hostkey_method_ssh_rsa_dtor(session, abstract);
+        *abstract = NULL;
+    }
+
+    if(hostkey_data_len < 19) {
+        _libssh2_debug(session, LIBSSH2_TRACE_ERROR,
+                       "host key length too short");
+        return -1;
+    }
+
+    buf.data = (unsigned char *)hostkey_data;
+    buf.dataptr = buf.data;
+    buf.len = hostkey_data_len;
+
+    if(_libssh2_match_string(&buf, "ssh-rsa"))
+        return -1;
+
+    if(_libssh2_get_string(&buf, &e, &e_len))
+        return -1;
+
+    if(_libssh2_get_string(&buf, &n, &n_len))
+        return -1;
+
+    if(_libssh2_rsa_new(&rsactx, e, e_len, n, n_len, NULL, 0,
+                        NULL, 0, NULL, 0, NULL, 0, NULL, 0, NULL, 0)) {
+        return -1;
+    }
+
+    *abstract = rsactx;
+
+    return 0;
+}
+
+/*
+ * hostkey_method_ssh_rsa_initPEM
+ *
+ * Load a Private Key from a PEM file
+ */
+static int
+hostkey_method_ssh_rsa_initPEM(LIBSSH2_SESSION * session,
+                               const char *privkeyfile,
+                               unsigned const char *passphrase,
+                               void **abstract)
+{
+    libssh2_rsa_ctx *rsactx;
+    int ret;
+
+    if(*abstract) {
+        hostkey_method_ssh_rsa_dtor(session, abstract);
+        *abstract = NULL;
+    }
+
+    ret = _libssh2_rsa_new_private(&rsactx, session, privkeyfile, passphrase);
+    if(ret) {
+        return -1;
+    }
+
+    *abstract = rsactx;
+
+    return 0;
+}
+
+/*
+ * hostkey_method_ssh_rsa_initPEMFromMemory
+ *
+ * Load a Private Key from a memory
+ */
+static int
+hostkey_method_ssh_rsa_initPEMFromMemory(LIBSSH2_SESSION * session,
+                                         const char *privkeyfiledata,
+                                         size_t privkeyfiledata_len,
+                                         unsigned const char *passphrase,
+                                         void **abstract)
+{
+    libssh2_rsa_ctx *rsactx;
+    int ret;
+
+    if(*abstract) {
+        hostkey_method_ssh_rsa_dtor(session, abstract);
+        *abstract = NULL;
+    }
+
+    ret = _libssh2_rsa_new_private_frommemory(&rsactx, session,
+                                              privkeyfiledata,
+                                              privkeyfiledata_len, passphrase);
+    if(ret) {
+        return -1;
+    }
+
+    *abstract = rsactx;
+
+    return 0;
+}
+
+/*
+ * hostkey_method_ssh_rsa_sign
+ *
+ * Verify signature created by remote
+ */
+static int
+hostkey_method_ssh_rsa_sig_verify(LIBSSH2_SESSION * session,
+                                  const unsigned char *sig,
+                                  size_t sig_len,
+                                  const unsigned char *m,
+                                  size_t m_len, void **abstract)
+{
+    libssh2_rsa_ctx *rsactx = (libssh2_rsa_ctx *) (*abstract);
+    (void) session;
+
+    /* Skip past keyname_len(4) + keyname(7){"ssh-rsa"} + signature_len(4) */
+    if(sig_len < 15)
+        return -1;
+
+    sig += 15;
+    sig_len -= 15;
+    return _libssh2_rsa_sha1_verify(rsactx, sig, sig_len, m, m_len);
+}
+
+/*
+ * hostkey_method_ssh_rsa_signv
+ *
+ * Construct a signature from an array of vectors
+ */
+static int
+hostkey_method_ssh_rsa_signv(LIBSSH2_SESSION * session,
+                             unsigned char **signature,
+                             size_t *signature_len,
+                             int veccount,
+                             const struct iovec datavec[],
+                             void **abstract)
+{
+    libssh2_rsa_ctx *rsactx = (libssh2_rsa_ctx *) (*abstract);
+
+#ifdef _libssh2_rsa_sha1_signv
+    return _libssh2_rsa_sha1_signv(session, signature, signature_len,
+                                   veccount, datavec, rsactx);
+#else
+    int ret;
+    int i;
+    unsigned char hash[SHA_DIGEST_LENGTH];
+    libssh2_sha1_ctx ctx;
+
+    libssh2_sha1_init(&ctx);
+    for(i = 0; i < veccount; i++) {
+        libssh2_sha1_update(ctx, datavec[i].iov_base, datavec[i].iov_len);
+    }
+    libssh2_sha1_final(ctx, hash);
+
+    ret = _libssh2_rsa_sha1_sign(session, rsactx, hash, SHA_DIGEST_LENGTH,
+                                 signature, signature_len);
+    if(ret) {
+        return -1;
+    }
+
+    return 0;
+#endif
+}
+
+/*
+ * hostkey_method_ssh_rsa_dtor
+ *
+ * Shutdown the hostkey
+ */
+static int
+hostkey_method_ssh_rsa_dtor(LIBSSH2_SESSION * session, void **abstract)
+{
+    libssh2_rsa_ctx *rsactx = (libssh2_rsa_ctx *) (*abstract);
+    (void) session;
+
+    _libssh2_rsa_free(rsactx);
+
+    *abstract = NULL;
+
+    return 0;
+}
+
+#ifdef OPENSSL_NO_MD5
+#define MD5_DIGEST_LENGTH 16
+#endif
+
+static const LIBSSH2_HOSTKEY_METHOD hostkey_method_ssh_rsa = {
+    "ssh-rsa",
+    MD5_DIGEST_LENGTH,
+    hostkey_method_ssh_rsa_init,
+    hostkey_method_ssh_rsa_initPEM,
+    hostkey_method_ssh_rsa_initPEMFromMemory,
+    hostkey_method_ssh_rsa_sig_verify,
+    hostkey_method_ssh_rsa_signv,
+    NULL,                       /* encrypt */
+    hostkey_method_ssh_rsa_dtor,
+};
+#endif /* LIBSSH2_RSA */
+
+#if LIBSSH2_DSA
+/* ***********
+ * ssh-dss *
+ *********** */
+
+static int hostkey_method_ssh_dss_dtor(LIBSSH2_SESSION * session,
+                                       void **abstract);
+
+/*
+ * hostkey_method_ssh_dss_init
+ *
+ * Initialize the server hostkey working area with p/q/g/y set
+ */
+static int
+hostkey_method_ssh_dss_init(LIBSSH2_SESSION * session,
+                            const unsigned char *hostkey_data,
+                            size_t hostkey_data_len,
+                            void **abstract)
+{
+    libssh2_dsa_ctx *dsactx;
+    unsigned char *p, *q, *g, *y;
+    size_t p_len, q_len, g_len, y_len;
+    struct string_buf buf;
+
+    if(*abstract) {
+        hostkey_method_ssh_dss_dtor(session, abstract);
+        *abstract = NULL;
+    }
+
+    if(hostkey_data_len < 27) {
+        _libssh2_debug(session, LIBSSH2_TRACE_ERROR,
+                       "host key length too short");
+        return -1;
+    }
+
+    buf.data = (unsigned char *)hostkey_data;
+    buf.dataptr = buf.data;
+    buf.len = hostkey_data_len;
+
+    if(_libssh2_match_string(&buf, "ssh-dss"))
+        return -1;
+
+    if(_libssh2_get_string(&buf, &p, &p_len))
+       return -1;
+
+    if(_libssh2_get_string(&buf, &q, &q_len))
+        return -1;
+
+    if(_libssh2_get_string(&buf, &g, &g_len))
+        return -1;
+
+    if(_libssh2_get_string(&buf, &y, &y_len))
+        return -1;
+
+    if(_libssh2_dsa_new(&dsactx, p, p_len, q, q_len,
+                        g, g_len, y, y_len, NULL, 0)) {
+        return -1;
+    }
+
+    *abstract = dsactx;
+
+    return 0;
+}
+
+/*
+ * hostkey_method_ssh_dss_initPEM
+ *
+ * Load a Private Key from a PEM file
+ */
+static int
+hostkey_method_ssh_dss_initPEM(LIBSSH2_SESSION * session,
+                               const char *privkeyfile,
+                               unsigned const char *passphrase,
+                               void **abstract)
+{
+    libssh2_dsa_ctx *dsactx;
+    int ret;
+
+    if(*abstract) {
+        hostkey_method_ssh_dss_dtor(session, abstract);
+        *abstract = NULL;
+    }
+
+    ret = _libssh2_dsa_new_private(&dsactx, session, privkeyfile, passphrase);
+    if(ret) {
+        return -1;
+    }
+
+    *abstract = dsactx;
+
+    return 0;
+}
+
+/*
+ * hostkey_method_ssh_dss_initPEMFromMemory
+ *
+ * Load a Private Key from memory
+ */
+static int
+hostkey_method_ssh_dss_initPEMFromMemory(LIBSSH2_SESSION * session,
+                                         const char *privkeyfiledata,
+                                         size_t privkeyfiledata_len,
+                                         unsigned const char *passphrase,
+                                         void **abstract)
+{
+    libssh2_dsa_ctx *dsactx;
+    int ret;
+
+    if(*abstract) {
+        hostkey_method_ssh_dss_dtor(session, abstract);
+        *abstract = NULL;
+    }
+
+    ret = _libssh2_dsa_new_private_frommemory(&dsactx, session,
+                                              privkeyfiledata,
+                                              privkeyfiledata_len, passphrase);
+    if(ret) {
+        return -1;
+    }
+
+    *abstract = dsactx;
+
+    return 0;
+}
+
+/*
+ * libssh2_hostkey_method_ssh_dss_sign
+ *
+ * Verify signature created by remote
+ */
+static int
+hostkey_method_ssh_dss_sig_verify(LIBSSH2_SESSION * session,
+                                  const unsigned char *sig,
+                                  size_t sig_len,
+                                  const unsigned char *m,
+                                  size_t m_len, void **abstract)
+{
+    libssh2_dsa_ctx *dsactx = (libssh2_dsa_ctx *) (*abstract);
+
+    /* Skip past keyname_len(4) + keyname(7){"ssh-dss"} + signature_len(4) */
+    if(sig_len != 55) {
+        return _libssh2_error(session, LIBSSH2_ERROR_PROTO,
+                              "Invalid DSS signature length");
+    }
+
+    sig += 15;
+    sig_len -= 15;
+
+    return _libssh2_dsa_sha1_verify(dsactx, sig, m, m_len);
+}
+
+/*
+ * hostkey_method_ssh_dss_signv
+ *
+ * Construct a signature from an array of vectors
+ */
+static int
+hostkey_method_ssh_dss_signv(LIBSSH2_SESSION * session,
+                             unsigned char **signature,
+                             size_t *signature_len,
+                             int veccount,
+                             const struct iovec datavec[],
+                             void **abstract)
+{
+    libssh2_dsa_ctx *dsactx = (libssh2_dsa_ctx *) (*abstract);
+    unsigned char hash[SHA_DIGEST_LENGTH];
+    libssh2_sha1_ctx ctx;
+    int i;
+
+    *signature = LIBSSH2_CALLOC(session, 2 * SHA_DIGEST_LENGTH);
+    if(!*signature) {
+        return -1;
+    }
+
+    *signature_len = 2 * SHA_DIGEST_LENGTH;
+
+    libssh2_sha1_init(&ctx);
+    for(i = 0; i < veccount; i++) {
+        libssh2_sha1_update(ctx, datavec[i].iov_base, datavec[i].iov_len);
+    }
+    libssh2_sha1_final(ctx, hash);
+
+    if(_libssh2_dsa_sha1_sign(dsactx, hash, SHA_DIGEST_LENGTH, *signature)) {
+        LIBSSH2_FREE(session, *signature);
+        return -1;
+    }
+
+    return 0;
+}
+
+/*
+ * libssh2_hostkey_method_ssh_dss_dtor
+ *
+ * Shutdown the hostkey method
+ */
+static int
+hostkey_method_ssh_dss_dtor(LIBSSH2_SESSION * session, void **abstract)
+{
+    libssh2_dsa_ctx *dsactx = (libssh2_dsa_ctx *) (*abstract);
+    (void) session;
+
+    _libssh2_dsa_free(dsactx);
+
+    *abstract = NULL;
+
+    return 0;
+}
+
+static const LIBSSH2_HOSTKEY_METHOD hostkey_method_ssh_dss = {
+    "ssh-dss",
+    MD5_DIGEST_LENGTH,
+    hostkey_method_ssh_dss_init,
+    hostkey_method_ssh_dss_initPEM,
+    hostkey_method_ssh_dss_initPEMFromMemory,
+    hostkey_method_ssh_dss_sig_verify,
+    hostkey_method_ssh_dss_signv,
+    NULL,                       /* encrypt */
+    hostkey_method_ssh_dss_dtor,
+};
+#endif /* LIBSSH2_DSA */
+
+#if LIBSSH2_ECDSA
+
+/* ***********
+ * ecdsa-sha2-nistp256/384/521 *
+ *********** */
+
+static int
+hostkey_method_ssh_ecdsa_dtor(LIBSSH2_SESSION * session,
+                              void **abstract);
+
+/*
+ * hostkey_method_ssh_ecdsa_init
+ *
+ * Initialize the server hostkey working area with e/n pair
+ */
+static int
+hostkey_method_ssh_ecdsa_init(LIBSSH2_SESSION * session,
+                          const unsigned char *hostkey_data,
+                          size_t hostkey_data_len,
+                          void **abstract)
+{
+    libssh2_ecdsa_ctx *ecdsactx = NULL;
+    unsigned char *type_str, *domain, *public_key;
+    size_t key_len, len;
+    libssh2_curve_type type;
+    struct string_buf buf;
+
+    if(abstract != NULL && *abstract) {
+        hostkey_method_ssh_ecdsa_dtor(session, abstract);
+        *abstract = NULL;
+    }
+
+    if(hostkey_data_len < 39) {
+        _libssh2_debug(session, LIBSSH2_TRACE_ERROR,
+                       "host key length too short");
+        return -1;
+    }
+
+    buf.data = (unsigned char *)hostkey_data;
+    buf.dataptr = buf.data;
+    buf.len = hostkey_data_len;
+
+    if(_libssh2_get_string(&buf, &type_str, &len) || len != 19)
+        return -1;
+
+    if(strncmp((char *) type_str, "ecdsa-sha2-nistp256", 19) == 0) {
+        type = LIBSSH2_EC_CURVE_NISTP256;
+    }
+    else if(strncmp((char *) type_str, "ecdsa-sha2-nistp384", 19) == 0) {
+        type = LIBSSH2_EC_CURVE_NISTP384;
+    }
+    else if(strncmp((char *) type_str, "ecdsa-sha2-nistp521", 19) == 0) {
+        type = LIBSSH2_EC_CURVE_NISTP521;
+    }
+    else {
+        return -1;
+    }
+
+    if(_libssh2_get_string(&buf, &domain, &len) || len != 8)
+        return -1;
+
+    if(type == LIBSSH2_EC_CURVE_NISTP256 &&
+       strncmp((char *)domain, "nistp256", 8) != 0) {
+        return -1;
+    }
+    else if(type == LIBSSH2_EC_CURVE_NISTP384 &&
+            strncmp((char *)domain, "nistp384", 8) != 0) {
+        return -1;
+    }
+    else if(type == LIBSSH2_EC_CURVE_NISTP521 &&
+            strncmp((char *)domain, "nistp521", 8) != 0) {
+        return -1;
+    }
+
+    /* public key */
+    if(_libssh2_get_string(&buf, &public_key, &key_len))
+        return -1;
+
+    if(_libssh2_ecdsa_curve_name_with_octal_new(&ecdsactx, public_key,
+                                                key_len, type))
+        return -1;
+
+    if(abstract != NULL)
+        *abstract = ecdsactx;
+
+    return 0;
+}
+
+/*
+ * hostkey_method_ssh_ecdsa_initPEM
+ *
+ * Load a Private Key from a PEM file
+ */
+static int
+hostkey_method_ssh_ecdsa_initPEM(LIBSSH2_SESSION * session,
+                             const char *privkeyfile,
+                             unsigned const char *passphrase,
+                             void **abstract)
+{
+    libssh2_ecdsa_ctx *ec_ctx = NULL;
+    int ret;
+
+    if(abstract != NULL && *abstract) {
+        hostkey_method_ssh_ecdsa_dtor(session, abstract);
+        *abstract = NULL;
+    }
+
+    ret = _libssh2_ecdsa_new_private(&ec_ctx, session,
+                                     privkeyfile, passphrase);
+
+    if(abstract != NULL)
+        *abstract = ec_ctx;
+
+    return ret;
+}
+
+/*
+ * hostkey_method_ssh_ecdsa_initPEMFromMemory
+ *
+ * Load a Private Key from memory
+ */
+static int
+hostkey_method_ssh_ecdsa_initPEMFromMemory(LIBSSH2_SESSION * session,
+                                         const char *privkeyfiledata,
+                                         size_t privkeyfiledata_len,
+                                         unsigned const char *passphrase,
+                                         void **abstract)
+{
+    libssh2_ecdsa_ctx *ec_ctx = NULL;
+    int ret;
+
+    if(abstract != NULL && *abstract) {
+        hostkey_method_ssh_ecdsa_dtor(session, abstract);
+        *abstract = NULL;
+    }
+
+    ret = _libssh2_ecdsa_new_private_frommemory(&ec_ctx, session,
+                                                privkeyfiledata,
+                                                privkeyfiledata_len,
+                                                passphrase);
+    if(ret) {
+        return -1;
+    }
+
+    if(abstract != NULL)
+        *abstract = ec_ctx;
+
+    return 0;
+}
+
+/*
+ * hostkey_method_ecdsa_sig_verify
+ *
+ * Verify signature created by remote
+ */
+static int
+hostkey_method_ssh_ecdsa_sig_verify(LIBSSH2_SESSION * session,
+                                    const unsigned char *sig,
+                                    size_t sig_len,
+                                    const unsigned char *m,
+                                    size_t m_len, void **abstract)
+{
+    unsigned char *r, *s, *name;
+    size_t r_len, s_len, name_len;
+    unsigned int len;
+    struct string_buf buf;
+    libssh2_ecdsa_ctx *ctx = (libssh2_ecdsa_ctx *) (*abstract);
+
+    (void) session;
+
+    if(sig_len < 35)
+        return -1;
+
+    /* keyname_len(4) + keyname(19){"ecdsa-sha2-nistp256"} +
+       signature_len(4) */
+    buf.data = (unsigned char *)sig;
+    buf.dataptr = buf.data;
+    buf.len = sig_len;
+
+   if(_libssh2_get_string(&buf, &name, &name_len) || name_len != 19)
+        return -1;
+
+    if(_libssh2_get_u32(&buf, &len) != 0 || len < 8)
+        return -1;
+
+    if(_libssh2_get_string(&buf, &r, &r_len))
+       return -1;
+
+    if(_libssh2_get_string(&buf, &s, &s_len))
+        return -1;
+
+    return _libssh2_ecdsa_verify(ctx, r, r_len, s, s_len, m, m_len);
+}
+
+
+#define LIBSSH2_HOSTKEY_METHOD_EC_SIGNV_HASH(digest_type)               \
+    {                                                                   \
+        unsigned char hash[SHA##digest_type##_DIGEST_LENGTH];           \
+        libssh2_sha##digest_type##_ctx ctx;                             \
+        int i;                                                          \
+        libssh2_sha##digest_type##_init(&ctx);                          \
+        for(i = 0; i < veccount; i++) {                                 \
+            libssh2_sha##digest_type##_update(ctx, datavec[i].iov_base, \
+                                              datavec[i].iov_len);      \
+        }                                                               \
+        libssh2_sha##digest_type##_final(ctx, hash);                    \
+        ret = _libssh2_ecdsa_sign(session, ec_ctx, hash,                \
+                                  SHA##digest_type##_DIGEST_LENGTH,     \
+                                  signature, signature_len);            \
+    }
+
+
+/*
+ * hostkey_method_ecdsa_signv
+ *
+ * Construct a signature from an array of vectors
+ */
+static int
+hostkey_method_ssh_ecdsa_signv(LIBSSH2_SESSION * session,
+                               unsigned char **signature,
+                               size_t *signature_len,
+                               int veccount,
+                               const struct iovec datavec[],
+                               void **abstract)
+{
+    libssh2_ecdsa_ctx *ec_ctx = (libssh2_ecdsa_ctx *) (*abstract);
+    libssh2_curve_type type = _libssh2_ecdsa_key_get_curve_type(ec_ctx);
+    int ret = 0;
+
+    if(type == LIBSSH2_EC_CURVE_NISTP256) {
+        LIBSSH2_HOSTKEY_METHOD_EC_SIGNV_HASH(256);
+    }
+    else if(type == LIBSSH2_EC_CURVE_NISTP384) {
+        LIBSSH2_HOSTKEY_METHOD_EC_SIGNV_HASH(384);
+    }
+    else if(type == LIBSSH2_EC_CURVE_NISTP521) {
+        LIBSSH2_HOSTKEY_METHOD_EC_SIGNV_HASH(512);
+    }
+    else {
+        return -1;
+    }
+
+    return ret;
+}
+
+/*
+ * hostkey_method_ssh_ecdsa_dtor
+ *
+ * Shutdown the hostkey by freeing EC_KEY context
+ */
+static int
+hostkey_method_ssh_ecdsa_dtor(LIBSSH2_SESSION * session, void **abstract)
+{
+    libssh2_ecdsa_ctx *keyctx = (libssh2_ecdsa_ctx *) (*abstract);
+    (void) session;
+
+    if(keyctx != NULL)
+        _libssh2_ecdsa_free(keyctx);
+
+    *abstract = NULL;
+
+    return 0;
+}
+
+static const LIBSSH2_HOSTKEY_METHOD hostkey_method_ecdsa_ssh_nistp256 = {
+    "ecdsa-sha2-nistp256",
+    SHA256_DIGEST_LENGTH,
+    hostkey_method_ssh_ecdsa_init,
+    hostkey_method_ssh_ecdsa_initPEM,
+    hostkey_method_ssh_ecdsa_initPEMFromMemory,
+    hostkey_method_ssh_ecdsa_sig_verify,
+    hostkey_method_ssh_ecdsa_signv,
+    NULL,                       /* encrypt */
+    hostkey_method_ssh_ecdsa_dtor,
+};
+
+static const LIBSSH2_HOSTKEY_METHOD hostkey_method_ecdsa_ssh_nistp384 = {
+    "ecdsa-sha2-nistp384",
+    SHA384_DIGEST_LENGTH,
+    hostkey_method_ssh_ecdsa_init,
+    hostkey_method_ssh_ecdsa_initPEM,
+    hostkey_method_ssh_ecdsa_initPEMFromMemory,
+    hostkey_method_ssh_ecdsa_sig_verify,
+    hostkey_method_ssh_ecdsa_signv,
+    NULL,                       /* encrypt */
+    hostkey_method_ssh_ecdsa_dtor,
+};
+
+static const LIBSSH2_HOSTKEY_METHOD hostkey_method_ecdsa_ssh_nistp521 = {
+    "ecdsa-sha2-nistp521",
+    SHA512_DIGEST_LENGTH,
+    hostkey_method_ssh_ecdsa_init,
+    hostkey_method_ssh_ecdsa_initPEM,
+    hostkey_method_ssh_ecdsa_initPEMFromMemory,
+    hostkey_method_ssh_ecdsa_sig_verify,
+    hostkey_method_ssh_ecdsa_signv,
+    NULL,                       /* encrypt */
+    hostkey_method_ssh_ecdsa_dtor,
+};
+
+#endif /* LIBSSH2_ECDSA */
+
+#if LIBSSH2_ED25519
+
+/* ***********
+ * ed25519 *
+ *********** */
+
+static int hostkey_method_ssh_ed25519_dtor(LIBSSH2_SESSION * session,
+                                           void **abstract);
+
+/*
+ * hostkey_method_ssh_ed25519_init
+ *
+ * Initialize the server hostkey working area with e/n pair
+ */
+static int
+hostkey_method_ssh_ed25519_init(LIBSSH2_SESSION * session,
+                                const unsigned char *hostkey_data,
+                                size_t hostkey_data_len,
+                                void **abstract)
+{
+    const unsigned char *s;
+    unsigned long len, key_len;
+    libssh2_ed25519_ctx *ctx = NULL;
+
+    if(*abstract) {
+        hostkey_method_ssh_ed25519_dtor(session, abstract);
+        *abstract = NULL;
+    }
+
+    if(hostkey_data_len < 19) {
+        _libssh2_debug(session, LIBSSH2_TRACE_ERROR,
+                       "host key length too short");
+        return -1;
+    }
+
+    s = hostkey_data;
+    len = _libssh2_ntohu32(s);
+    s += 4;
+
+    if(len != 11 || strncmp((char *) s, "ssh-ed25519", 11) != 0) {
+        return -1;
+    }
+
+    s += 11;
+
+    /* public key */
+    key_len = _libssh2_ntohu32(s);
+    s += 4;
+
+    if(_libssh2_ed25519_new_public(&ctx, session, s, key_len) != 0) {
+        return -1;
+    }
+
+    *abstract = ctx;
+
+    return 0;
+}
+
+/*
+ * hostkey_method_ssh_ed25519_initPEM
+ *
+ * Load a Private Key from a PEM file
+ */
+static int
+hostkey_method_ssh_ed25519_initPEM(LIBSSH2_SESSION * session,
+                             const char *privkeyfile,
+                             unsigned const char *passphrase,
+                             void **abstract)
+{
+    libssh2_ed25519_ctx *ec_ctx = NULL;
+    int ret;
+
+    if(*abstract) {
+        hostkey_method_ssh_ed25519_dtor(session, abstract);
+        *abstract = NULL;
+    }
+
+    ret = _libssh2_ed25519_new_private(&ec_ctx, session,
+                                       privkeyfile, passphrase);
+    if(ret) {
+        return -1;
+    }
+
+    *abstract = ec_ctx;
+
+    return ret;
+}
+
+/*
+ * hostkey_method_ssh_ed25519_initPEMFromMemory
+ *
+ * Load a Private Key from memory
+ */
+static int
+hostkey_method_ssh_ed25519_initPEMFromMemory(LIBSSH2_SESSION * session,
+                                             const char *privkeyfiledata,
+                                             size_t privkeyfiledata_len,
+                                             unsigned const char *passphrase,
+                                             void **abstract)
+{
+    libssh2_ed25519_ctx *ed_ctx = NULL;
+    int ret;
+
+    if(abstract != NULL && *abstract) {
+        hostkey_method_ssh_ed25519_dtor(session, abstract);
+        *abstract = NULL;
+    }
+
+    ret = _libssh2_ed25519_new_private_frommemory(&ed_ctx, session,
+                                                  privkeyfiledata,
+                                                  privkeyfiledata_len,
+                                                  passphrase);
+    if(ret) {
+        return -1;
+    }
+
+    if(abstract != NULL)
+        *abstract = ed_ctx;
+
+    return 0;
+}
+
+/*
+ * hostkey_method_ssh_ed25519_sig_verify
+ *
+ * Verify signature created by remote
+ */
+static int
+hostkey_method_ssh_ed25519_sig_verify(LIBSSH2_SESSION * session,
+                                      const unsigned char *sig,
+                                      size_t sig_len,
+                                      const unsigned char *m,
+                                      size_t m_len, void **abstract)
+{
+    libssh2_ed25519_ctx *ctx = (libssh2_ed25519_ctx *) (*abstract);
+    (void) session;
+
+    if(sig_len < 19)
+        return -1;
+
+    /* Skip past keyname_len(4) + keyname(11){"ssh-ed25519"} +
+       signature_len(4) */
+    sig += 19;
+    sig_len -= 19;
+
+    if(sig_len != LIBSSH2_ED25519_SIG_LEN)
+        return -1;
+
+    return _libssh2_ed25519_verify(ctx, sig, sig_len, m, m_len);
+}
+
+/*
+ * hostkey_method_ssh_ed25519_signv
+ *
+ * Construct a signature from an array of vectors
+ */
+static int
+hostkey_method_ssh_ed25519_signv(LIBSSH2_SESSION * session,
+                           unsigned char **signature,
+                           size_t *signature_len,
+                           int veccount,
+                           const struct iovec datavec[],
+                           void **abstract)
+{
+    libssh2_ed25519_ctx *ctx = (libssh2_ed25519_ctx *) (*abstract);
+
+    if(veccount != 1) {
+        return -1;
+    }
+
+    return _libssh2_ed25519_sign(ctx, session, signature, signature_len,
+                                 datavec[0].iov_base, datavec[0].iov_len);
+}
+
+
+/*
+ * hostkey_method_ssh_ed25519_dtor
+ *
+ * Shutdown the hostkey by freeing key context
+ */
+static int
+hostkey_method_ssh_ed25519_dtor(LIBSSH2_SESSION * session, void **abstract)
+{
+    libssh2_ed25519_ctx *keyctx = (libssh2_ed25519_ctx*) (*abstract);
+    (void) session;
+
+    if(keyctx)
+        _libssh2_ed25519_free(keyctx);
+
+    *abstract = NULL;
+
+    return 0;
+}
+
+static const LIBSSH2_HOSTKEY_METHOD hostkey_method_ssh_ed25519 = {
+    "ssh-ed25519",
+    SHA256_DIGEST_LENGTH,
+    hostkey_method_ssh_ed25519_init,
+    hostkey_method_ssh_ed25519_initPEM,
+    hostkey_method_ssh_ed25519_initPEMFromMemory,
+    hostkey_method_ssh_ed25519_sig_verify,
+    hostkey_method_ssh_ed25519_signv,
+    NULL,                       /* encrypt */
+    hostkey_method_ssh_ed25519_dtor,
+};
+
+#endif /*LIBSSH2_ED25519*/
+
+
+static const LIBSSH2_HOSTKEY_METHOD *hostkey_methods[] = {
+#if LIBSSH2_ECDSA
+    &hostkey_method_ecdsa_ssh_nistp256,
+    &hostkey_method_ecdsa_ssh_nistp384,
+    &hostkey_method_ecdsa_ssh_nistp521,
+#endif
+#if LIBSSH2_ED25519
+    &hostkey_method_ssh_ed25519,
+#endif
+#if LIBSSH2_RSA
+    &hostkey_method_ssh_rsa,
+#endif /* LIBSSH2_RSA */
+#if LIBSSH2_DSA
+    &hostkey_method_ssh_dss,
+#endif /* LIBSSH2_DSA */
+    NULL
+};
+
+const LIBSSH2_HOSTKEY_METHOD **
+libssh2_hostkey_methods(void)
+{
+    return hostkey_methods;
+}
+
+/*
+ * libssh2_hostkey_hash
+ *
+ * Returns hash signature
+ * Returned buffer should NOT be freed
+ * Length of buffer is determined by hash type
+ * i.e. MD5 == 16, SHA1 == 20, SHA256 == 32
+ */
+LIBSSH2_API const char *
+libssh2_hostkey_hash(LIBSSH2_SESSION * session, int hash_type)
+{
+    switch(hash_type) {
+#if LIBSSH2_MD5
+    case LIBSSH2_HOSTKEY_HASH_MD5:
+        return (session->server_hostkey_md5_valid)
+          ? (char *) session->server_hostkey_md5
+          : NULL;
+        break;
+#endif /* LIBSSH2_MD5 */
+    case LIBSSH2_HOSTKEY_HASH_SHA1:
+        return (session->server_hostkey_sha1_valid)
+          ? (char *) session->server_hostkey_sha1
+          : NULL;
+        break;
+    case LIBSSH2_HOSTKEY_HASH_SHA256:
+        return (session->server_hostkey_sha256_valid)
+          ? (char *) session->server_hostkey_sha256
+          : NULL;
+        break;
+    default:
+        return NULL;
+    }
+}
+
+static int hostkey_type(const unsigned char *hostkey, size_t len)
+{
+    static const unsigned char rsa[] = {
+        0, 0, 0, 0x07, 's', 's', 'h', '-', 'r', 's', 'a'
+    };
+    static const unsigned char dss[] = {
+        0, 0, 0, 0x07, 's', 's', 'h', '-', 'd', 's', 's'
+    };
+    static const unsigned char ecdsa_256[] = {
+        0, 0, 0, 0x13, 'e', 'c', 'd', 's', 'a', '-', 's', 'h', 'a', '2', '-',
+        'n', 'i', 's', 't', 'p', '2', '5', '6'
+    };
+    static const unsigned char ecdsa_384[] = {
+        0, 0, 0, 0x13, 'e', 'c', 'd', 's', 'a', '-', 's', 'h', 'a', '2', '-',
+        'n', 'i', 's', 't', 'p', '3', '8', '4'
+    };
+    static const unsigned char ecdsa_521[] = {
+        0, 0, 0, 0x13, 'e', 'c', 'd', 's', 'a', '-', 's', 'h', 'a', '2', '-',
+        'n', 'i', 's', 't', 'p', '5', '2', '1'
+    };
+    static const unsigned char ed25519[] = {
+        0, 0, 0, 0x0b, 's', 's', 'h', '-', 'e', 'd', '2', '5', '5', '1', '9'
+    };
+
+    if(len < 11)
+        return LIBSSH2_HOSTKEY_TYPE_UNKNOWN;
+
+    if(!memcmp(rsa, hostkey, 11))
+        return LIBSSH2_HOSTKEY_TYPE_RSA;
+
+    if(!memcmp(dss, hostkey, 11))
+        return LIBSSH2_HOSTKEY_TYPE_DSS;
+
+    if(len < 15)
+        return LIBSSH2_HOSTKEY_TYPE_UNKNOWN;
+
+    if(!memcmp(ed25519, hostkey, 15))
+        return LIBSSH2_HOSTKEY_TYPE_ED25519;
+
+    if(len < 23)
+        return LIBSSH2_HOSTKEY_TYPE_UNKNOWN;
+
+    if(!memcmp(ecdsa_256, hostkey, 23))
+        return LIBSSH2_HOSTKEY_TYPE_ECDSA_256;
+
+    if(!memcmp(ecdsa_384, hostkey, 23))
+        return LIBSSH2_HOSTKEY_TYPE_ECDSA_384;
+
+    if(!memcmp(ecdsa_521, hostkey, 23))
+        return LIBSSH2_HOSTKEY_TYPE_ECDSA_521;
+
+    return LIBSSH2_HOSTKEY_TYPE_UNKNOWN;
+}
+
+/*
+ * libssh2_session_hostkey()
+ *
+ * Returns the server key and length.
+ *
+ */
+LIBSSH2_API const char *
+libssh2_session_hostkey(LIBSSH2_SESSION *session, size_t *len, int *type)
+{
+    if(session->server_hostkey_len) {
+        if(len)
+            *len = session->server_hostkey_len;
+        if(type)
+            *type = hostkey_type(session->server_hostkey,
+                                 session->server_hostkey_len);
+        return (char *) session->server_hostkey;
+    }
+    if(len)
+        *len = 0;
+    return NULL;
+}

+ 100 - 0
libssh2/libssh2/src/keepalive.c

@@ -0,0 +1,100 @@
+/* Copyright (C) 2010  Simon Josefsson
+ * Author: Simon Josefsson
+ *
+ * Redistribution and use in source and binary forms,
+ * with or without modification, are permitted provided
+ * that the following conditions are met:
+ *
+ *   Redistributions of source code must retain the above
+ *   copyright notice, this list of conditions and the
+ *   following disclaimer.
+ *
+ *   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.
+ *
+ *   Neither the name of the copyright holder nor the names
+ *   of any other contributors may be used to endorse or
+ *   promote products derived from this software without
+ *   specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+ * CONTRIBUTORS "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 COPYRIGHT OWNER OR
+ * CONTRIBUTORS 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 "libssh2_priv.h"
+#include "transport.h" /* _libssh2_transport_write */
+
+/* Keep-alive stuff. */
+
+LIBSSH2_API void
+libssh2_keepalive_config (LIBSSH2_SESSION *session,
+                          int want_reply,
+                          unsigned interval)
+{
+    if(interval == 1)
+        session->keepalive_interval = 2;
+    else
+        session->keepalive_interval = interval;
+    session->keepalive_want_reply = want_reply ? 1 : 0;
+}
+
+LIBSSH2_API int
+libssh2_keepalive_send (LIBSSH2_SESSION *session,
+                        int *seconds_to_next)
+{
+    time_t now;
+
+    if(!session->keepalive_interval) {
+        if(seconds_to_next)
+            *seconds_to_next = 0;
+        return 0;
+    }
+
+    now = time(NULL);
+
+    if(session->keepalive_last_sent + session->keepalive_interval <= now) {
+        /* Format is
+           "SSH_MSG_GLOBAL_REQUEST || 4-byte len || str || want-reply". */
+        unsigned char keepalive_data[]
+            = "\x50\x00\x00\x00\x15keepalive@libssh2.orgW";
+        size_t len = sizeof(keepalive_data) - 1;
+        int rc;
+
+        keepalive_data[len - 1] =
+            (unsigned char)session->keepalive_want_reply;
+
+        rc = _libssh2_transport_send(session, keepalive_data, len, NULL, 0);
+        /* Silently ignore PACKET_EAGAIN here: if the write buffer is
+           already full, sending another keepalive is not useful. */
+        if(rc && rc != LIBSSH2_ERROR_EAGAIN) {
+            _libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND,
+                           "Unable to send keepalive message");
+            return rc;
+        }
+
+        session->keepalive_last_sent = now;
+        if(seconds_to_next)
+            *seconds_to_next = session->keepalive_interval;
+    }
+    else if(seconds_to_next) {
+        *seconds_to_next = (int) (session->keepalive_last_sent - now)
+            + session->keepalive_interval;
+    }
+
+    return 0;
+}

+ 4424 - 0
libssh2/libssh2/src/kex.c

@@ -0,0 +1,4424 @@
+/* Copyright (c) 2004-2007, Sara Golemon <sarag@libssh2.org>
+ * Copyright (c) 2010-2019, Daniel Stenberg <daniel@haxx.se>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms,
+ * with or without modification, are permitted provided
+ * that the following conditions are met:
+ *
+ *   Redistributions of source code must retain the above
+ *   copyright notice, this list of conditions and the
+ *   following disclaimer.
+ *
+ *   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.
+ *
+ *   Neither the name of the copyright holder nor the names
+ *   of any other contributors may be used to endorse or
+ *   promote products derived from this software without
+ *   specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+ * CONTRIBUTORS "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 COPYRIGHT OWNER OR
+ * CONTRIBUTORS 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 "libssh2_priv.h"
+
+#include "transport.h"
+#include "comp.h"
+#include "mac.h"
+
+/* TODO: Switch this to an inline and handle alloc() failures */
+/* Helper macro called from
+   kex_method_diffie_hellman_group1_sha1_key_exchange */
+#define LIBSSH2_KEX_METHOD_DIFFIE_HELLMAN_SHA1_HASH(value, reqlen, version) \
+    {                                                                   \
+        libssh2_sha1_ctx hash;                                          \
+        unsigned long len = 0;                                          \
+        if(!(value)) {                                                  \
+            value = LIBSSH2_ALLOC(session, reqlen + SHA_DIGEST_LENGTH); \
+        }                                                               \
+        if(value)                                                       \
+            while(len < (unsigned long)reqlen) {                        \
+                libssh2_sha1_init(&hash);                               \
+                libssh2_sha1_update(hash, exchange_state->k_value,      \
+                                    exchange_state->k_value_len);       \
+                libssh2_sha1_update(hash, exchange_state->h_sig_comp,   \
+                                    SHA_DIGEST_LENGTH);                 \
+                if(len > 0) {                                           \
+                    libssh2_sha1_update(hash, value, len);              \
+                }                                                       \
+                else {                                                  \
+                    libssh2_sha1_update(hash, (version), 1);            \
+                    libssh2_sha1_update(hash, session->session_id,      \
+                                        session->session_id_len);       \
+                }                                                       \
+                libssh2_sha1_final(hash, (value) + len);                \
+                len += SHA_DIGEST_LENGTH;                               \
+            }                                                           \
+    }                                                                   \
+
+
+#define LIBSSH2_KEX_METHOD_EC_SHA_VALUE_HASH(value, reqlen, version)    \
+    {                                                                   \
+        if(type == LIBSSH2_EC_CURVE_NISTP256) {                         \
+            LIBSSH2_KEX_METHOD_SHA_VALUE_HASH(256, value, reqlen, version); \
+        }                                                               \
+        else if(type == LIBSSH2_EC_CURVE_NISTP384) {                    \
+            LIBSSH2_KEX_METHOD_SHA_VALUE_HASH(384, value, reqlen, version); \
+        }                                                               \
+        else if(type == LIBSSH2_EC_CURVE_NISTP521) {                    \
+            LIBSSH2_KEX_METHOD_SHA_VALUE_HASH(512, value, reqlen, version); \
+        }                                                               \
+    }                                                                   \
+
+
+#define LIBSSH2_KEX_METHOD_SHA_VALUE_HASH(digest_type, value,           \
+                                          reqlen, version)              \
+{                                                                       \
+    libssh2_sha##digest_type##_ctx hash;                                \
+    unsigned long len = 0;                                              \
+    if(!(value)) {                                                      \
+        value = LIBSSH2_ALLOC(session,                                  \
+                              reqlen + SHA##digest_type##_DIGEST_LENGTH); \
+    }                                                                   \
+    if(value)                                                           \
+        while(len < (unsigned long)reqlen) {                            \
+            libssh2_sha##digest_type##_init(&hash);                     \
+            libssh2_sha##digest_type##_update(hash,                     \
+                                              exchange_state->k_value,  \
+                                              exchange_state->k_value_len); \
+            libssh2_sha##digest_type##_update(hash,                     \
+                                              exchange_state->h_sig_comp, \
+                                         SHA##digest_type##_DIGEST_LENGTH); \
+            if(len > 0) {                                               \
+                libssh2_sha##digest_type##_update(hash, value, len);    \
+            }                                                           \
+            else {                                                      \
+                libssh2_sha##digest_type##_update(hash, (version), 1);  \
+                libssh2_sha##digest_type##_update(hash, session->session_id, \
+                                                  session->session_id_len); \
+            }                                                           \
+            libssh2_sha##digest_type##_final(hash, (value) + len);      \
+            len += SHA##digest_type##_DIGEST_LENGTH;                    \
+        }                                                               \
+}
+
+
+/*
+ * diffie_hellman_sha1
+ *
+ * Diffie Hellman Key Exchange, Group Agnostic
+ */
+static int diffie_hellman_sha1(LIBSSH2_SESSION *session,
+                               _libssh2_bn *g,
+                               _libssh2_bn *p,
+                               int group_order,
+                               unsigned char packet_type_init,
+                               unsigned char packet_type_reply,
+                               unsigned char *midhash,
+                               unsigned long midhash_len,
+                               kmdhgGPshakex_state_t *exchange_state)
+{
+    int ret = 0;
+    int rc;
+    libssh2_sha1_ctx exchange_hash_ctx;
+
+    if(exchange_state->state == libssh2_NB_state_idle) {
+        /* Setup initial values */
+        exchange_state->e_packet = NULL;
+        exchange_state->s_packet = NULL;
+        exchange_state->k_value = NULL;
+        exchange_state->ctx = _libssh2_bn_ctx_new();
+        libssh2_dh_init(&exchange_state->x);
+        exchange_state->e = _libssh2_bn_init(); /* g^x mod p */
+        exchange_state->f = _libssh2_bn_init_from_bin(); /* g^(Random from
+                                                            server) mod p */
+        exchange_state->k = _libssh2_bn_init(); /* The shared secret: f^x mod
+                                                   p */
+
+        /* Zero the whole thing out */
+        memset(&exchange_state->req_state, 0, sizeof(packet_require_state_t));
+
+        /* Generate x and e */
+        rc = libssh2_dh_key_pair(&exchange_state->x, exchange_state->e, g, p,
+                                 group_order, exchange_state->ctx);
+        if(rc)
+            goto clean_exit;
+
+        /* Send KEX init */
+        /* packet_type(1) + String Length(4) + leading 0(1) */
+        exchange_state->e_packet_len =
+            _libssh2_bn_bytes(exchange_state->e) + 6;
+        if(_libssh2_bn_bits(exchange_state->e) % 8) {
+            /* Leading 00 not needed */
+            exchange_state->e_packet_len--;
+        }
+
+        exchange_state->e_packet =
+            LIBSSH2_ALLOC(session, exchange_state->e_packet_len);
+        if(!exchange_state->e_packet) {
+            ret = _libssh2_error(session, LIBSSH2_ERROR_ALLOC,
+                                 "Out of memory error");
+            goto clean_exit;
+        }
+        exchange_state->e_packet[0] = packet_type_init;
+        _libssh2_htonu32(exchange_state->e_packet + 1,
+                         exchange_state->e_packet_len - 5);
+        if(_libssh2_bn_bits(exchange_state->e) % 8) {
+            _libssh2_bn_to_bin(exchange_state->e,
+                               exchange_state->e_packet + 5);
+        }
+        else {
+            exchange_state->e_packet[5] = 0;
+            _libssh2_bn_to_bin(exchange_state->e,
+                               exchange_state->e_packet + 6);
+        }
+
+        _libssh2_debug(session, LIBSSH2_TRACE_KEX, "Sending KEX packet %d",
+                       (int) packet_type_init);
+        exchange_state->state = libssh2_NB_state_created;
+    }
+
+    if(exchange_state->state == libssh2_NB_state_created) {
+        rc = _libssh2_transport_send(session, exchange_state->e_packet,
+                                     exchange_state->e_packet_len,
+                                     NULL, 0);
+        if(rc == LIBSSH2_ERROR_EAGAIN) {
+            return rc;
+        }
+        else if(rc) {
+            ret = _libssh2_error(session, rc,
+                                 "Unable to send KEX init message");
+            goto clean_exit;
+        }
+        exchange_state->state = libssh2_NB_state_sent;
+    }
+
+    if(exchange_state->state == libssh2_NB_state_sent) {
+        if(session->burn_optimistic_kexinit) {
+            /* The first KEX packet to come along will be the guess initially
+             * sent by the server.  That guess turned out to be wrong so we
+             * need to silently ignore it */
+            int burn_type;
+
+            _libssh2_debug(session, LIBSSH2_TRACE_KEX,
+                           "Waiting for badly guessed KEX packet "
+                           "(to be ignored)");
+            burn_type =
+                _libssh2_packet_burn(session, &exchange_state->burn_state);
+            if(burn_type == LIBSSH2_ERROR_EAGAIN) {
+                return burn_type;
+            }
+            else if(burn_type <= 0) {
+                /* Failed to receive a packet */
+                ret = burn_type;
+                goto clean_exit;
+            }
+            session->burn_optimistic_kexinit = 0;
+
+            _libssh2_debug(session, LIBSSH2_TRACE_KEX,
+                           "Burnt packet of type: %02x",
+                           (unsigned int) burn_type);
+        }
+
+        exchange_state->state = libssh2_NB_state_sent1;
+    }
+
+    if(exchange_state->state == libssh2_NB_state_sent1) {
+        /* Wait for KEX reply */
+        struct string_buf buf;
+        size_t host_key_len;
+
+        rc = _libssh2_packet_require(session, packet_type_reply,
+                                     &exchange_state->s_packet,
+                                     &exchange_state->s_packet_len, 0, NULL,
+                                     0, &exchange_state->req_state);
+        if(rc == LIBSSH2_ERROR_EAGAIN) {
+            return rc;
+        }
+        if(rc) {
+            ret = _libssh2_error(session, LIBSSH2_ERROR_TIMEOUT,
+                                 "Timed out waiting for KEX reply");
+            goto clean_exit;
+        }
+
+        /* Parse KEXDH_REPLY */
+        if(exchange_state->s_packet_len < 5) {
+            ret = _libssh2_error(session, LIBSSH2_ERROR_PROTO,
+                                 "Unexpected packet length");
+            goto clean_exit;
+        }
+
+        buf.data = exchange_state->s_packet;
+        buf.len = exchange_state->s_packet_len;
+        buf.dataptr = buf.data;
+        buf.dataptr++; /* advance past type */
+
+        if(session->server_hostkey)
+            LIBSSH2_FREE(session, session->server_hostkey);
+
+        if(_libssh2_copy_string(session, &buf, &(session->server_hostkey),
+                                &host_key_len)) {
+            ret = _libssh2_error(session, LIBSSH2_ERROR_ALLOC,
+                                 "Could not copy host key");
+            goto clean_exit;
+        }
+
+        session->server_hostkey_len = (uint32_t)host_key_len;
+
+#if LIBSSH2_MD5
+        {
+            libssh2_md5_ctx fingerprint_ctx;
+
+            if(libssh2_md5_init(&fingerprint_ctx)) {
+                libssh2_md5_update(fingerprint_ctx, session->server_hostkey,
+                                   session->server_hostkey_len);
+                libssh2_md5_final(fingerprint_ctx,
+                                  session->server_hostkey_md5);
+                session->server_hostkey_md5_valid = TRUE;
+            }
+            else {
+                session->server_hostkey_md5_valid = FALSE;
+            }
+        }
+#ifdef LIBSSH2DEBUG
+        {
+            char fingerprint[50], *fprint = fingerprint;
+            int i;
+            for(i = 0; i < 16; i++, fprint += 3) {
+                snprintf(fprint, 4, "%02x:", session->server_hostkey_md5[i]);
+            }
+            *(--fprint) = '\0';
+            _libssh2_debug(session, LIBSSH2_TRACE_KEX,
+                           "Server's MD5 Fingerprint: %s", fingerprint);
+        }
+#endif /* LIBSSH2DEBUG */
+#endif /* ! LIBSSH2_MD5 */
+
+        {
+            libssh2_sha1_ctx fingerprint_ctx;
+
+            if(libssh2_sha1_init(&fingerprint_ctx)) {
+                libssh2_sha1_update(fingerprint_ctx, session->server_hostkey,
+                                    session->server_hostkey_len);
+                libssh2_sha1_final(fingerprint_ctx,
+                                   session->server_hostkey_sha1);
+                session->server_hostkey_sha1_valid = TRUE;
+            }
+            else {
+                session->server_hostkey_sha1_valid = FALSE;
+            }
+        }
+#ifdef LIBSSH2DEBUG
+        {
+            char fingerprint[64], *fprint = fingerprint;
+            int i;
+
+            for(i = 0; i < 20; i++, fprint += 3) {
+                snprintf(fprint, 4, "%02x:", session->server_hostkey_sha1[i]);
+            }
+            *(--fprint) = '\0';
+            _libssh2_debug(session, LIBSSH2_TRACE_KEX,
+                           "Server's SHA1 Fingerprint: %s", fingerprint);
+        }
+#endif /* LIBSSH2DEBUG */
+
+        {
+            libssh2_sha256_ctx fingerprint_ctx;
+
+            if(libssh2_sha256_init(&fingerprint_ctx)) {
+                libssh2_sha256_update(fingerprint_ctx, session->server_hostkey,
+                                    session->server_hostkey_len);
+                libssh2_sha256_final(fingerprint_ctx,
+                                   session->server_hostkey_sha256);
+                session->server_hostkey_sha256_valid = TRUE;
+            }
+            else {
+                session->server_hostkey_sha256_valid = FALSE;
+            }
+        }
+#ifdef LIBSSH2DEBUG
+        {
+            char *base64Fingerprint = NULL;
+            _libssh2_base64_encode(session,
+                                   (const char *)
+                                   session->server_hostkey_sha256,
+                                   SHA256_DIGEST_LENGTH, &base64Fingerprint);
+            if(base64Fingerprint != NULL) {
+                _libssh2_debug(session, LIBSSH2_TRACE_KEX,
+                               "Server's SHA256 Fingerprint: %s",
+                               base64Fingerprint);
+                LIBSSH2_FREE(session, base64Fingerprint);
+            }
+        }
+#endif /* LIBSSH2DEBUG */
+
+
+        if(session->hostkey->init(session, session->server_hostkey,
+                                   session->server_hostkey_len,
+                                   &session->server_hostkey_abstract)) {
+            ret = _libssh2_error(session, LIBSSH2_ERROR_HOSTKEY_INIT,
+                                 "Unable to initialize hostkey importer");
+            goto clean_exit;
+        }
+
+        if(_libssh2_get_string(&buf, &(exchange_state->f_value),
+                               &(exchange_state->f_value_len))) {
+            ret = _libssh2_error(session, LIBSSH2_ERROR_HOSTKEY_INIT,
+                                 "Unable to get f value");
+            goto clean_exit;
+        }
+
+        _libssh2_bn_from_bin(exchange_state->f, exchange_state->f_value_len,
+                             exchange_state->f_value);
+
+        if(_libssh2_get_string(&buf, &(exchange_state->h_sig),
+                               &(exchange_state->h_sig_len))) {
+            ret = _libssh2_error(session, LIBSSH2_ERROR_HOSTKEY_INIT,
+                                 "Unable to get h sig");
+            goto clean_exit;
+        }
+
+        /* Compute the shared secret */
+        libssh2_dh_secret(&exchange_state->x, exchange_state->k,
+                          exchange_state->f, p, exchange_state->ctx);
+        exchange_state->k_value_len = _libssh2_bn_bytes(exchange_state->k) + 5;
+        if(_libssh2_bn_bits(exchange_state->k) % 8) {
+            /* don't need leading 00 */
+            exchange_state->k_value_len--;
+        }
+        exchange_state->k_value =
+            LIBSSH2_ALLOC(session, exchange_state->k_value_len);
+        if(!exchange_state->k_value) {
+            ret = _libssh2_error(session, LIBSSH2_ERROR_ALLOC,
+                                 "Unable to allocate buffer for K");
+            goto clean_exit;
+        }
+        _libssh2_htonu32(exchange_state->k_value,
+                         exchange_state->k_value_len - 4);
+        if(_libssh2_bn_bits(exchange_state->k) % 8) {
+            _libssh2_bn_to_bin(exchange_state->k, exchange_state->k_value + 4);
+        }
+        else {
+            exchange_state->k_value[4] = 0;
+            _libssh2_bn_to_bin(exchange_state->k, exchange_state->k_value + 5);
+        }
+
+        exchange_state->exchange_hash = (void *)&exchange_hash_ctx;
+        libssh2_sha1_init(&exchange_hash_ctx);
+
+        if(session->local.banner) {
+            _libssh2_htonu32(exchange_state->h_sig_comp,
+                             strlen((char *) session->local.banner) - 2);
+            libssh2_sha1_update(exchange_hash_ctx,
+                                exchange_state->h_sig_comp, 4);
+            libssh2_sha1_update(exchange_hash_ctx,
+                                session->local.banner,
+                                strlen((char *) session->local.banner) - 2);
+        }
+        else {
+            _libssh2_htonu32(exchange_state->h_sig_comp,
+                             sizeof(LIBSSH2_SSH_DEFAULT_BANNER) - 1);
+            libssh2_sha1_update(exchange_hash_ctx,
+                                exchange_state->h_sig_comp, 4);
+            libssh2_sha1_update(exchange_hash_ctx,
+                                (const unsigned char *)
+                                LIBSSH2_SSH_DEFAULT_BANNER,
+                                sizeof(LIBSSH2_SSH_DEFAULT_BANNER) - 1);
+        }
+
+        _libssh2_htonu32(exchange_state->h_sig_comp,
+                         strlen((char *) session->remote.banner));
+        libssh2_sha1_update(exchange_hash_ctx,
+                            exchange_state->h_sig_comp, 4);
+        libssh2_sha1_update(exchange_hash_ctx,
+                            session->remote.banner,
+                            strlen((char *) session->remote.banner));
+
+        _libssh2_htonu32(exchange_state->h_sig_comp,
+                         session->local.kexinit_len);
+        libssh2_sha1_update(exchange_hash_ctx,
+                            exchange_state->h_sig_comp, 4);
+        libssh2_sha1_update(exchange_hash_ctx,
+                            session->local.kexinit,
+                            session->local.kexinit_len);
+
+        _libssh2_htonu32(exchange_state->h_sig_comp,
+                         session->remote.kexinit_len);
+        libssh2_sha1_update(exchange_hash_ctx,
+                            exchange_state->h_sig_comp, 4);
+        libssh2_sha1_update(exchange_hash_ctx,
+                            session->remote.kexinit,
+                            session->remote.kexinit_len);
+
+        _libssh2_htonu32(exchange_state->h_sig_comp,
+                         session->server_hostkey_len);
+        libssh2_sha1_update(exchange_hash_ctx,
+                            exchange_state->h_sig_comp, 4);
+        libssh2_sha1_update(exchange_hash_ctx,
+                            session->server_hostkey,
+                            session->server_hostkey_len);
+
+        if(packet_type_init == SSH_MSG_KEX_DH_GEX_INIT) {
+            /* diffie-hellman-group-exchange hashes additional fields */
+#ifdef LIBSSH2_DH_GEX_NEW
+            _libssh2_htonu32(exchange_state->h_sig_comp,
+                             LIBSSH2_DH_GEX_MINGROUP);
+            _libssh2_htonu32(exchange_state->h_sig_comp + 4,
+                             LIBSSH2_DH_GEX_OPTGROUP);
+            _libssh2_htonu32(exchange_state->h_sig_comp + 8,
+                             LIBSSH2_DH_GEX_MAXGROUP);
+            libssh2_sha1_update(exchange_hash_ctx,
+                                exchange_state->h_sig_comp, 12);
+#else
+            _libssh2_htonu32(exchange_state->h_sig_comp,
+                             LIBSSH2_DH_GEX_OPTGROUP);
+            libssh2_sha1_update(exchange_hash_ctx,
+                                exchange_state->h_sig_comp, 4);
+#endif
+        }
+
+        if(midhash) {
+            libssh2_sha1_update(exchange_hash_ctx, midhash,
+                                midhash_len);
+        }
+
+        libssh2_sha1_update(exchange_hash_ctx,
+                            exchange_state->e_packet + 1,
+                            exchange_state->e_packet_len - 1);
+
+        _libssh2_htonu32(exchange_state->h_sig_comp,
+                         exchange_state->f_value_len);
+        libssh2_sha1_update(exchange_hash_ctx,
+                            exchange_state->h_sig_comp, 4);
+        libssh2_sha1_update(exchange_hash_ctx,
+                            exchange_state->f_value,
+                            exchange_state->f_value_len);
+
+        libssh2_sha1_update(exchange_hash_ctx,
+                            exchange_state->k_value,
+                            exchange_state->k_value_len);
+
+        libssh2_sha1_final(exchange_hash_ctx,
+                           exchange_state->h_sig_comp);
+
+        if(session->hostkey->
+            sig_verify(session, exchange_state->h_sig,
+                       exchange_state->h_sig_len, exchange_state->h_sig_comp,
+                       20, &session->server_hostkey_abstract)) {
+            ret = _libssh2_error(session, LIBSSH2_ERROR_HOSTKEY_SIGN,
+                                 "Unable to verify hostkey signature");
+            goto clean_exit;
+        }
+
+        _libssh2_debug(session, LIBSSH2_TRACE_KEX, "Sending NEWKEYS message");
+        exchange_state->c = SSH_MSG_NEWKEYS;
+
+        exchange_state->state = libssh2_NB_state_sent2;
+    }
+
+    if(exchange_state->state == libssh2_NB_state_sent2) {
+        rc = _libssh2_transport_send(session, &exchange_state->c, 1, NULL, 0);
+        if(rc == LIBSSH2_ERROR_EAGAIN) {
+            return rc;
+        }
+        else if(rc) {
+            ret = _libssh2_error(session, rc,
+                                 "Unable to send NEWKEYS message");
+            goto clean_exit;
+        }
+
+        exchange_state->state = libssh2_NB_state_sent3;
+    }
+
+    if(exchange_state->state == libssh2_NB_state_sent3) {
+        rc = _libssh2_packet_require(session, SSH_MSG_NEWKEYS,
+                                     &exchange_state->tmp,
+                                     &exchange_state->tmp_len, 0, NULL, 0,
+                                     &exchange_state->req_state);
+        if(rc == LIBSSH2_ERROR_EAGAIN) {
+            return rc;
+        }
+        else if(rc) {
+            ret = _libssh2_error(session, rc, "Timed out waiting for NEWKEYS");
+            goto clean_exit;
+        }
+        /* The first key exchange has been performed,
+           switch to active crypt/comp/mac mode */
+        session->state |= LIBSSH2_STATE_NEWKEYS;
+        _libssh2_debug(session, LIBSSH2_TRACE_KEX, "Received NEWKEYS message");
+
+        /* This will actually end up being just packet_type(1)
+           for this packet type anyway */
+        LIBSSH2_FREE(session, exchange_state->tmp);
+
+        if(!session->session_id) {
+            session->session_id = LIBSSH2_ALLOC(session, SHA_DIGEST_LENGTH);
+            if(!session->session_id) {
+                ret = _libssh2_error(session, LIBSSH2_ERROR_ALLOC,
+                                     "Unable to allocate buffer for "
+                                     "SHA digest");
+                goto clean_exit;
+            }
+            memcpy(session->session_id, exchange_state->h_sig_comp,
+                   SHA_DIGEST_LENGTH);
+            session->session_id_len = SHA_DIGEST_LENGTH;
+            _libssh2_debug(session, LIBSSH2_TRACE_KEX,
+                           "session_id calculated");
+        }
+
+        /* Cleanup any existing cipher */
+        if(session->local.crypt->dtor) {
+            session->local.crypt->dtor(session,
+                                       &session->local.crypt_abstract);
+        }
+
+        /* Calculate IV/Secret/Key for each direction */
+        if(session->local.crypt->init) {
+            unsigned char *iv = NULL, *secret = NULL;
+            int free_iv = 0, free_secret = 0;
+
+            LIBSSH2_KEX_METHOD_DIFFIE_HELLMAN_SHA1_HASH(iv,
+                                                        session->local.crypt->
+                                                        iv_len,
+                                                        (const unsigned char *)
+                                                        "A");
+            if(!iv) {
+                ret = -1;
+                goto clean_exit;
+            }
+            LIBSSH2_KEX_METHOD_DIFFIE_HELLMAN_SHA1_HASH(secret,
+                                                        session->local.crypt->
+                                                        secret_len,
+                                                        (const unsigned char *)
+                                                        "C");
+            if(!secret) {
+                LIBSSH2_FREE(session, iv);
+                ret = LIBSSH2_ERROR_KEX_FAILURE;
+                goto clean_exit;
+            }
+            if(session->local.crypt->
+                init(session, session->local.crypt, iv, &free_iv, secret,
+                     &free_secret, 1, &session->local.crypt_abstract)) {
+                LIBSSH2_FREE(session, iv);
+                LIBSSH2_FREE(session, secret);
+                ret = LIBSSH2_ERROR_KEX_FAILURE;
+                goto clean_exit;
+            }
+
+            if(free_iv) {
+                _libssh2_explicit_zero(iv, session->local.crypt->iv_len);
+                LIBSSH2_FREE(session, iv);
+            }
+
+            if(free_secret) {
+                _libssh2_explicit_zero(secret,
+                                       session->local.crypt->secret_len);
+                LIBSSH2_FREE(session, secret);
+            }
+        }
+        _libssh2_debug(session, LIBSSH2_TRACE_KEX,
+                       "Client to Server IV and Key calculated");
+
+        if(session->remote.crypt->dtor) {
+            /* Cleanup any existing cipher */
+            session->remote.crypt->dtor(session,
+                                        &session->remote.crypt_abstract);
+        }
+
+        if(session->remote.crypt->init) {
+            unsigned char *iv = NULL, *secret = NULL;
+            int free_iv = 0, free_secret = 0;
+
+            LIBSSH2_KEX_METHOD_DIFFIE_HELLMAN_SHA1_HASH(iv,
+                                                        session->remote.crypt->
+                                                        iv_len,
+                                                        (const unsigned char *)
+                                                        "B");
+            if(!iv) {
+                ret = LIBSSH2_ERROR_KEX_FAILURE;
+                goto clean_exit;
+            }
+            LIBSSH2_KEX_METHOD_DIFFIE_HELLMAN_SHA1_HASH(secret,
+                                                        session->remote.crypt->
+                                                        secret_len,
+                                                        (const unsigned char *)
+                                                        "D");
+            if(!secret) {
+                LIBSSH2_FREE(session, iv);
+                ret = LIBSSH2_ERROR_KEX_FAILURE;
+                goto clean_exit;
+            }
+            if(session->remote.crypt->
+                init(session, session->remote.crypt, iv, &free_iv, secret,
+                     &free_secret, 0, &session->remote.crypt_abstract)) {
+                LIBSSH2_FREE(session, iv);
+                LIBSSH2_FREE(session, secret);
+                ret = LIBSSH2_ERROR_KEX_FAILURE;
+                goto clean_exit;
+            }
+
+            if(free_iv) {
+                _libssh2_explicit_zero(iv, session->remote.crypt->iv_len);
+                LIBSSH2_FREE(session, iv);
+            }
+
+            if(free_secret) {
+                _libssh2_explicit_zero(secret,
+                                       session->remote.crypt->secret_len);
+                LIBSSH2_FREE(session, secret);
+            }
+        }
+        _libssh2_debug(session, LIBSSH2_TRACE_KEX,
+                       "Server to Client IV and Key calculated");
+
+        if(session->local.mac->dtor) {
+            session->local.mac->dtor(session, &session->local.mac_abstract);
+        }
+
+        if(session->local.mac->init) {
+            unsigned char *key = NULL;
+            int free_key = 0;
+
+            LIBSSH2_KEX_METHOD_DIFFIE_HELLMAN_SHA1_HASH(key,
+                                                        session->local.mac->
+                                                        key_len,
+                                                        (const unsigned char *)
+                                                        "E");
+            if(!key) {
+                ret = LIBSSH2_ERROR_KEX_FAILURE;
+                goto clean_exit;
+            }
+            session->local.mac->init(session, key, &free_key,
+                                     &session->local.mac_abstract);
+
+            if(free_key) {
+                _libssh2_explicit_zero(key, session->local.mac->key_len);
+                LIBSSH2_FREE(session, key);
+            }
+        }
+        _libssh2_debug(session, LIBSSH2_TRACE_KEX,
+                       "Client to Server HMAC Key calculated");
+
+        if(session->remote.mac->dtor) {
+            session->remote.mac->dtor(session, &session->remote.mac_abstract);
+        }
+
+        if(session->remote.mac->init) {
+            unsigned char *key = NULL;
+            int free_key = 0;
+
+            LIBSSH2_KEX_METHOD_DIFFIE_HELLMAN_SHA1_HASH(key,
+                                                        session->remote.mac->
+                                                        key_len,
+                                                        (const unsigned char *)
+                                                        "F");
+            if(!key) {
+                ret = LIBSSH2_ERROR_KEX_FAILURE;
+                goto clean_exit;
+            }
+            session->remote.mac->init(session, key, &free_key,
+                                      &session->remote.mac_abstract);
+
+            if(free_key) {
+                _libssh2_explicit_zero(key, session->remote.mac->key_len);
+                LIBSSH2_FREE(session, key);
+            }
+        }
+        _libssh2_debug(session, LIBSSH2_TRACE_KEX,
+                       "Server to Client HMAC Key calculated");
+
+        /* Initialize compression for each direction */
+
+        /* Cleanup any existing compression */
+        if(session->local.comp && session->local.comp->dtor) {
+            session->local.comp->dtor(session, 1,
+                                      &session->local.comp_abstract);
+        }
+
+        if(session->local.comp && session->local.comp->init) {
+            if(session->local.comp->init(session, 1,
+                                          &session->local.comp_abstract)) {
+                ret = LIBSSH2_ERROR_KEX_FAILURE;
+                goto clean_exit;
+            }
+        }
+        _libssh2_debug(session, LIBSSH2_TRACE_KEX,
+                       "Client to Server compression initialized");
+
+        if(session->remote.comp && session->remote.comp->dtor) {
+            session->remote.comp->dtor(session, 0,
+                                       &session->remote.comp_abstract);
+        }
+
+        if(session->remote.comp && session->remote.comp->init) {
+            if(session->remote.comp->init(session, 0,
+                                           &session->remote.comp_abstract)) {
+                ret = LIBSSH2_ERROR_KEX_FAILURE;
+                goto clean_exit;
+            }
+        }
+        _libssh2_debug(session, LIBSSH2_TRACE_KEX,
+                       "Server to Client compression initialized");
+
+    }
+
+  clean_exit:
+    libssh2_dh_dtor(&exchange_state->x);
+    _libssh2_bn_free(exchange_state->e);
+    exchange_state->e = NULL;
+    _libssh2_bn_free(exchange_state->f);
+    exchange_state->f = NULL;
+    _libssh2_bn_free(exchange_state->k);
+    exchange_state->k = NULL;
+    _libssh2_bn_ctx_free(exchange_state->ctx);
+    exchange_state->ctx = NULL;
+
+    if(exchange_state->e_packet) {
+        LIBSSH2_FREE(session, exchange_state->e_packet);
+        exchange_state->e_packet = NULL;
+    }
+
+    if(exchange_state->s_packet) {
+        LIBSSH2_FREE(session, exchange_state->s_packet);
+        exchange_state->s_packet = NULL;
+    }
+
+    if(exchange_state->k_value) {
+        LIBSSH2_FREE(session, exchange_state->k_value);
+        exchange_state->k_value = NULL;
+    }
+
+    exchange_state->state = libssh2_NB_state_idle;
+
+    return ret;
+}
+
+
+/*
+ * diffie_hellman_sha256
+ *
+ * Diffie Hellman Key Exchange, Group Agnostic
+ */
+static int diffie_hellman_sha256(LIBSSH2_SESSION *session,
+                                 _libssh2_bn *g,
+                                 _libssh2_bn *p,
+                                 int group_order,
+                                 unsigned char packet_type_init,
+                                 unsigned char packet_type_reply,
+                                 unsigned char *midhash,
+                                 unsigned long midhash_len,
+                                 kmdhgGPshakex_state_t *exchange_state)
+{
+    int ret = 0;
+    int rc;
+    libssh2_sha256_ctx exchange_hash_ctx;
+
+    if(exchange_state->state == libssh2_NB_state_idle) {
+        /* Setup initial values */
+        exchange_state->e_packet = NULL;
+        exchange_state->s_packet = NULL;
+        exchange_state->k_value = NULL;
+        exchange_state->ctx = _libssh2_bn_ctx_new();
+        libssh2_dh_init(&exchange_state->x);
+        exchange_state->e = _libssh2_bn_init(); /* g^x mod p */
+        exchange_state->f = _libssh2_bn_init_from_bin(); /* g^(Random from
+                                                            server) mod p */
+        exchange_state->k = _libssh2_bn_init(); /* The shared secret: f^x mod
+                                                   p */
+
+        /* Zero the whole thing out */
+        memset(&exchange_state->req_state, 0, sizeof(packet_require_state_t));
+
+        /* Generate x and e */
+        rc = libssh2_dh_key_pair(&exchange_state->x, exchange_state->e, g, p,
+                                 group_order, exchange_state->ctx);
+        if(rc)
+            goto clean_exit;
+
+        /* Send KEX init */
+        /* packet_type(1) + String Length(4) + leading 0(1) */
+        exchange_state->e_packet_len =
+            _libssh2_bn_bytes(exchange_state->e) + 6;
+        if(_libssh2_bn_bits(exchange_state->e) % 8) {
+            /* Leading 00 not needed */
+            exchange_state->e_packet_len--;
+        }
+
+        exchange_state->e_packet =
+            LIBSSH2_ALLOC(session, exchange_state->e_packet_len);
+        if(!exchange_state->e_packet) {
+            ret = _libssh2_error(session, LIBSSH2_ERROR_ALLOC,
+                                 "Out of memory error");
+            goto clean_exit;
+        }
+        exchange_state->e_packet[0] = packet_type_init;
+        _libssh2_htonu32(exchange_state->e_packet + 1,
+                         exchange_state->e_packet_len - 5);
+        if(_libssh2_bn_bits(exchange_state->e) % 8) {
+            _libssh2_bn_to_bin(exchange_state->e,
+                               exchange_state->e_packet + 5);
+        }
+        else {
+            exchange_state->e_packet[5] = 0;
+            _libssh2_bn_to_bin(exchange_state->e,
+                               exchange_state->e_packet + 6);
+        }
+
+        _libssh2_debug(session, LIBSSH2_TRACE_KEX, "Sending KEX packet %d",
+                       (int) packet_type_init);
+        exchange_state->state = libssh2_NB_state_created;
+    }
+
+    if(exchange_state->state == libssh2_NB_state_created) {
+        rc = _libssh2_transport_send(session, exchange_state->e_packet,
+                                     exchange_state->e_packet_len,
+                                     NULL, 0);
+        if(rc == LIBSSH2_ERROR_EAGAIN) {
+            return rc;
+        }
+        else if(rc) {
+            ret = _libssh2_error(session, rc,
+                                 "Unable to send KEX init message");
+            goto clean_exit;
+        }
+        exchange_state->state = libssh2_NB_state_sent;
+    }
+
+    if(exchange_state->state == libssh2_NB_state_sent) {
+        if(session->burn_optimistic_kexinit) {
+            /* The first KEX packet to come along will be the guess initially
+             * sent by the server.  That guess turned out to be wrong so we
+             * need to silently ignore it */
+            int burn_type;
+
+            _libssh2_debug(session, LIBSSH2_TRACE_KEX,
+                           "Waiting for badly guessed KEX packet "
+                           "(to be ignored)");
+            burn_type =
+                _libssh2_packet_burn(session, &exchange_state->burn_state);
+            if(burn_type == LIBSSH2_ERROR_EAGAIN) {
+                return burn_type;
+            }
+            else if(burn_type <= 0) {
+                /* Failed to receive a packet */
+                ret = burn_type;
+                goto clean_exit;
+            }
+            session->burn_optimistic_kexinit = 0;
+
+            _libssh2_debug(session, LIBSSH2_TRACE_KEX,
+                           "Burnt packet of type: %02x",
+                           (unsigned int) burn_type);
+        }
+
+        exchange_state->state = libssh2_NB_state_sent1;
+    }
+
+    if(exchange_state->state == libssh2_NB_state_sent1) {
+        /* Wait for KEX reply */
+        struct string_buf buf;
+        size_t host_key_len;
+
+        rc = _libssh2_packet_require(session, packet_type_reply,
+                                     &exchange_state->s_packet,
+                                     &exchange_state->s_packet_len, 0, NULL,
+                                     0, &exchange_state->req_state);
+        if(rc == LIBSSH2_ERROR_EAGAIN) {
+            return rc;
+        }
+        if(rc) {
+            ret = _libssh2_error(session, LIBSSH2_ERROR_TIMEOUT,
+                                 "Timed out waiting for KEX reply");
+            goto clean_exit;
+        }
+
+        /* Parse KEXDH_REPLY */
+        if(exchange_state->s_packet_len < 5) {
+            ret = _libssh2_error(session, LIBSSH2_ERROR_PROTO,
+                                 "Unexpected packet length");
+            goto clean_exit;
+        }
+
+        buf.data = exchange_state->s_packet;
+        buf.len = exchange_state->s_packet_len;
+        buf.dataptr = buf.data;
+        buf.dataptr++; /* advance past type */
+
+        if(session->server_hostkey)
+            LIBSSH2_FREE(session, session->server_hostkey);
+
+        if(_libssh2_copy_string(session, &buf, &(session->server_hostkey),
+                                &host_key_len)) {
+            ret = _libssh2_error(session, LIBSSH2_ERROR_ALLOC,
+                                 "Could not copy host key");
+            goto clean_exit;
+        }
+
+        session->server_hostkey_len = (uint32_t)host_key_len;
+
+#if LIBSSH2_MD5
+        {
+            libssh2_md5_ctx fingerprint_ctx;
+
+            if(libssh2_md5_init(&fingerprint_ctx)) {
+                libssh2_md5_update(fingerprint_ctx, session->server_hostkey,
+                                   session->server_hostkey_len);
+                libssh2_md5_final(fingerprint_ctx,
+                                  session->server_hostkey_md5);
+                session->server_hostkey_md5_valid = TRUE;
+            }
+            else {
+                session->server_hostkey_md5_valid = FALSE;
+            }
+        }
+#ifdef LIBSSH2DEBUG
+        {
+            char fingerprint[50], *fprint = fingerprint;
+            int i;
+            for(i = 0; i < 16; i++, fprint += 3) {
+                snprintf(fprint, 4, "%02x:", session->server_hostkey_md5[i]);
+            }
+            *(--fprint) = '\0';
+            _libssh2_debug(session, LIBSSH2_TRACE_KEX,
+                           "Server's MD5 Fingerprint: %s", fingerprint);
+        }
+#endif /* LIBSSH2DEBUG */
+#endif /* ! LIBSSH2_MD5 */
+
+        {
+            libssh2_sha1_ctx fingerprint_ctx;
+
+            if(libssh2_sha1_init(&fingerprint_ctx)) {
+                libssh2_sha1_update(fingerprint_ctx, session->server_hostkey,
+                                    session->server_hostkey_len);
+                libssh2_sha1_final(fingerprint_ctx,
+                                   session->server_hostkey_sha1);
+                session->server_hostkey_sha1_valid = TRUE;
+            }
+            else {
+                session->server_hostkey_sha1_valid = FALSE;
+            }
+        }
+#ifdef LIBSSH2DEBUG
+        {
+            char fingerprint[64], *fprint = fingerprint;
+            int i;
+
+            for(i = 0; i < 20; i++, fprint += 3) {
+                snprintf(fprint, 4, "%02x:", session->server_hostkey_sha1[i]);
+            }
+            *(--fprint) = '\0';
+            _libssh2_debug(session, LIBSSH2_TRACE_KEX,
+                           "Server's SHA1 Fingerprint: %s", fingerprint);
+        }
+#endif /* LIBSSH2DEBUG */
+
+        {
+            libssh2_sha256_ctx fingerprint_ctx;
+
+            if(libssh2_sha256_init(&fingerprint_ctx)) {
+                libssh2_sha256_update(fingerprint_ctx, session->server_hostkey,
+                                      session->server_hostkey_len);
+                libssh2_sha256_final(fingerprint_ctx,
+                                     session->server_hostkey_sha256);
+                session->server_hostkey_sha256_valid = TRUE;
+            }
+            else {
+                session->server_hostkey_sha256_valid = FALSE;
+            }
+        }
+#ifdef LIBSSH2DEBUG
+        {
+            char *base64Fingerprint = NULL;
+            _libssh2_base64_encode(session,
+                                   (const char *)
+                                   session->server_hostkey_sha256,
+                                   SHA256_DIGEST_LENGTH, &base64Fingerprint);
+            if(base64Fingerprint != NULL) {
+                _libssh2_debug(session, LIBSSH2_TRACE_KEX,
+                               "Server's SHA256 Fingerprint: %s",
+                               base64Fingerprint);
+                LIBSSH2_FREE(session, base64Fingerprint);
+            }
+        }
+#endif /* LIBSSH2DEBUG */
+
+        if(session->hostkey->init(session, session->server_hostkey,
+                                   session->server_hostkey_len,
+                                   &session->server_hostkey_abstract)) {
+            ret = _libssh2_error(session, LIBSSH2_ERROR_HOSTKEY_INIT,
+                                 "Unable to initialize hostkey importer");
+            goto clean_exit;
+        }
+
+        if(_libssh2_get_string(&buf, &(exchange_state->f_value),
+                               &(exchange_state->f_value_len))) {
+            ret = _libssh2_error(session, LIBSSH2_ERROR_HOSTKEY_INIT,
+                                 "Unable to get f value");
+            goto clean_exit;
+        }
+
+        _libssh2_bn_from_bin(exchange_state->f, exchange_state->f_value_len,
+                             exchange_state->f_value);
+
+        if(_libssh2_get_string(&buf, &(exchange_state->h_sig),
+                               &(exchange_state->h_sig_len))) {
+            ret = _libssh2_error(session, LIBSSH2_ERROR_HOSTKEY_INIT,
+                                 "Unable to get h sig");
+            goto clean_exit;
+        }
+
+        /* Compute the shared secret */
+        libssh2_dh_secret(&exchange_state->x, exchange_state->k,
+                          exchange_state->f, p, exchange_state->ctx);
+        exchange_state->k_value_len = _libssh2_bn_bytes(exchange_state->k) + 5;
+        if(_libssh2_bn_bits(exchange_state->k) % 8) {
+            /* don't need leading 00 */
+            exchange_state->k_value_len--;
+        }
+        exchange_state->k_value =
+            LIBSSH2_ALLOC(session, exchange_state->k_value_len);
+        if(!exchange_state->k_value) {
+            ret = _libssh2_error(session, LIBSSH2_ERROR_ALLOC,
+                                 "Unable to allocate buffer for K");
+            goto clean_exit;
+        }
+        _libssh2_htonu32(exchange_state->k_value,
+                         exchange_state->k_value_len - 4);
+        if(_libssh2_bn_bits(exchange_state->k) % 8) {
+            _libssh2_bn_to_bin(exchange_state->k, exchange_state->k_value + 4);
+        }
+        else {
+            exchange_state->k_value[4] = 0;
+            _libssh2_bn_to_bin(exchange_state->k, exchange_state->k_value + 5);
+        }
+
+        exchange_state->exchange_hash = (void *)&exchange_hash_ctx;
+        libssh2_sha256_init(&exchange_hash_ctx);
+
+        if(session->local.banner) {
+            _libssh2_htonu32(exchange_state->h_sig_comp,
+                             strlen((char *) session->local.banner) - 2);
+            libssh2_sha256_update(exchange_hash_ctx,
+                                  exchange_state->h_sig_comp, 4);
+            libssh2_sha256_update(exchange_hash_ctx,
+                                  session->local.banner,
+                                  strlen((char *) session->local.banner) - 2);
+        }
+        else {
+            _libssh2_htonu32(exchange_state->h_sig_comp,
+                             sizeof(LIBSSH2_SSH_DEFAULT_BANNER) - 1);
+            libssh2_sha256_update(exchange_hash_ctx,
+                                  exchange_state->h_sig_comp, 4);
+            libssh2_sha256_update(exchange_hash_ctx,
+                                  (const unsigned char *)
+                                  LIBSSH2_SSH_DEFAULT_BANNER,
+                                  sizeof(LIBSSH2_SSH_DEFAULT_BANNER) - 1);
+        }
+
+        _libssh2_htonu32(exchange_state->h_sig_comp,
+                         strlen((char *) session->remote.banner));
+        libssh2_sha256_update(exchange_hash_ctx,
+                              exchange_state->h_sig_comp, 4);
+        libssh2_sha256_update(exchange_hash_ctx,
+                              session->remote.banner,
+                              strlen((char *) session->remote.banner));
+
+        _libssh2_htonu32(exchange_state->h_sig_comp,
+                         session->local.kexinit_len);
+        libssh2_sha256_update(exchange_hash_ctx,
+                              exchange_state->h_sig_comp, 4);
+        libssh2_sha256_update(exchange_hash_ctx,
+                              session->local.kexinit,
+                              session->local.kexinit_len);
+
+        _libssh2_htonu32(exchange_state->h_sig_comp,
+                         session->remote.kexinit_len);
+        libssh2_sha256_update(exchange_hash_ctx,
+                              exchange_state->h_sig_comp, 4);
+        libssh2_sha256_update(exchange_hash_ctx,
+                              session->remote.kexinit,
+                              session->remote.kexinit_len);
+
+        _libssh2_htonu32(exchange_state->h_sig_comp,
+                         session->server_hostkey_len);
+        libssh2_sha256_update(exchange_hash_ctx,
+                              exchange_state->h_sig_comp, 4);
+        libssh2_sha256_update(exchange_hash_ctx,
+                              session->server_hostkey,
+                              session->server_hostkey_len);
+
+        if(packet_type_init == SSH_MSG_KEX_DH_GEX_INIT) {
+            /* diffie-hellman-group-exchange hashes additional fields */
+#ifdef LIBSSH2_DH_GEX_NEW
+            _libssh2_htonu32(exchange_state->h_sig_comp,
+                             LIBSSH2_DH_GEX_MINGROUP);
+            _libssh2_htonu32(exchange_state->h_sig_comp + 4,
+                             LIBSSH2_DH_GEX_OPTGROUP);
+            _libssh2_htonu32(exchange_state->h_sig_comp + 8,
+                             LIBSSH2_DH_GEX_MAXGROUP);
+            libssh2_sha256_update(exchange_hash_ctx,
+                                  exchange_state->h_sig_comp, 12);
+#else
+            _libssh2_htonu32(exchange_state->h_sig_comp,
+                             LIBSSH2_DH_GEX_OPTGROUP);
+            libssh2_sha256_update(exchange_hash_ctx,
+                                  exchange_state->h_sig_comp, 4);
+#endif
+        }
+
+        if(midhash) {
+            libssh2_sha256_update(exchange_hash_ctx, midhash,
+                                  midhash_len);
+        }
+
+        libssh2_sha256_update(exchange_hash_ctx,
+                              exchange_state->e_packet + 1,
+                              exchange_state->e_packet_len - 1);
+
+        _libssh2_htonu32(exchange_state->h_sig_comp,
+                         exchange_state->f_value_len);
+        libssh2_sha256_update(exchange_hash_ctx,
+                              exchange_state->h_sig_comp, 4);
+        libssh2_sha256_update(exchange_hash_ctx,
+                              exchange_state->f_value,
+                              exchange_state->f_value_len);
+
+        libssh2_sha256_update(exchange_hash_ctx,
+                              exchange_state->k_value,
+                              exchange_state->k_value_len);
+
+        libssh2_sha256_final(exchange_hash_ctx,
+                             exchange_state->h_sig_comp);
+
+        if(session->hostkey->
+           sig_verify(session, exchange_state->h_sig,
+                      exchange_state->h_sig_len, exchange_state->h_sig_comp,
+                      SHA256_DIGEST_LENGTH,
+                      &session->server_hostkey_abstract)) {
+            ret = _libssh2_error(session, LIBSSH2_ERROR_HOSTKEY_SIGN,
+                                 "Unable to verify hostkey signature");
+            goto clean_exit;
+        }
+
+
+
+        _libssh2_debug(session, LIBSSH2_TRACE_KEX, "Sending NEWKEYS message");
+        exchange_state->c = SSH_MSG_NEWKEYS;
+
+        exchange_state->state = libssh2_NB_state_sent2;
+    }
+
+    if(exchange_state->state == libssh2_NB_state_sent2) {
+        rc = _libssh2_transport_send(session, &exchange_state->c, 1, NULL, 0);
+        if(rc == LIBSSH2_ERROR_EAGAIN) {
+            return rc;
+        }
+        else if(rc) {
+            ret = _libssh2_error(session, rc,
+                                 "Unable to send NEWKEYS message");
+            goto clean_exit;
+        }
+
+        exchange_state->state = libssh2_NB_state_sent3;
+    }
+
+    if(exchange_state->state == libssh2_NB_state_sent3) {
+        rc = _libssh2_packet_require(session, SSH_MSG_NEWKEYS,
+                                     &exchange_state->tmp,
+                                     &exchange_state->tmp_len, 0, NULL, 0,
+                                     &exchange_state->req_state);
+        if(rc == LIBSSH2_ERROR_EAGAIN) {
+            return rc;
+        }
+        else if(rc) {
+            ret = _libssh2_error(session, rc, "Timed out waiting for NEWKEYS");
+            goto clean_exit;
+        }
+        /* The first key exchange has been performed,
+           switch to active crypt/comp/mac mode */
+        session->state |= LIBSSH2_STATE_NEWKEYS;
+        _libssh2_debug(session, LIBSSH2_TRACE_KEX, "Received NEWKEYS message");
+
+        /* This will actually end up being just packet_type(1)
+           for this packet type anyway */
+        LIBSSH2_FREE(session, exchange_state->tmp);
+
+        if(!session->session_id) {
+            session->session_id = LIBSSH2_ALLOC(session, SHA256_DIGEST_LENGTH);
+            if(!session->session_id) {
+                ret = _libssh2_error(session, LIBSSH2_ERROR_ALLOC,
+                                     "Unable to allocate buffer for "
+                                     "SHA digest");
+                goto clean_exit;
+            }
+            memcpy(session->session_id, exchange_state->h_sig_comp,
+                   SHA256_DIGEST_LENGTH);
+            session->session_id_len = SHA256_DIGEST_LENGTH;
+            _libssh2_debug(session, LIBSSH2_TRACE_KEX,
+                           "session_id calculated");
+        }
+
+        /* Cleanup any existing cipher */
+        if(session->local.crypt->dtor) {
+            session->local.crypt->dtor(session,
+                                       &session->local.crypt_abstract);
+        }
+
+        /* Calculate IV/Secret/Key for each direction */
+        if(session->local.crypt->init) {
+            unsigned char *iv = NULL, *secret = NULL;
+            int free_iv = 0, free_secret = 0;
+
+            LIBSSH2_KEX_METHOD_SHA_VALUE_HASH(256, iv,
+                                              session->local.crypt->
+                                              iv_len,
+                                              (const unsigned char *)"A");
+            if(!iv) {
+                ret = -1;
+                goto clean_exit;
+            }
+            LIBSSH2_KEX_METHOD_SHA_VALUE_HASH(256, secret,
+                                              session->local.crypt->
+                                              secret_len,
+                                              (const unsigned char *)"C");
+            if(!secret) {
+                LIBSSH2_FREE(session, iv);
+                ret = LIBSSH2_ERROR_KEX_FAILURE;
+                goto clean_exit;
+            }
+            if(session->local.crypt->
+                init(session, session->local.crypt, iv, &free_iv, secret,
+                     &free_secret, 1, &session->local.crypt_abstract)) {
+                LIBSSH2_FREE(session, iv);
+                LIBSSH2_FREE(session, secret);
+                ret = LIBSSH2_ERROR_KEX_FAILURE;
+                goto clean_exit;
+            }
+
+            if(free_iv) {
+                _libssh2_explicit_zero(iv, session->local.crypt->iv_len);
+                LIBSSH2_FREE(session, iv);
+            }
+
+            if(free_secret) {
+                _libssh2_explicit_zero(secret,
+                                       session->local.crypt->secret_len);
+                LIBSSH2_FREE(session, secret);
+            }
+        }
+        _libssh2_debug(session, LIBSSH2_TRACE_KEX,
+                       "Client to Server IV and Key calculated");
+
+        if(session->remote.crypt->dtor) {
+            /* Cleanup any existing cipher */
+            session->remote.crypt->dtor(session,
+                                        &session->remote.crypt_abstract);
+        }
+
+        if(session->remote.crypt->init) {
+            unsigned char *iv = NULL, *secret = NULL;
+            int free_iv = 0, free_secret = 0;
+
+            LIBSSH2_KEX_METHOD_SHA_VALUE_HASH(256, iv,
+                                              session->remote.crypt->
+                                              iv_len,
+                                              (const unsigned char *)"B");
+            if(!iv) {
+                ret = LIBSSH2_ERROR_KEX_FAILURE;
+                goto clean_exit;
+            }
+            LIBSSH2_KEX_METHOD_SHA_VALUE_HASH(256, secret,
+                                              session->remote.crypt->
+                                              secret_len,
+                                              (const unsigned char *)"D");
+            if(!secret) {
+                LIBSSH2_FREE(session, iv);
+                ret = LIBSSH2_ERROR_KEX_FAILURE;
+                goto clean_exit;
+            }
+            if(session->remote.crypt->
+                init(session, session->remote.crypt, iv, &free_iv, secret,
+                     &free_secret, 0, &session->remote.crypt_abstract)) {
+                LIBSSH2_FREE(session, iv);
+                LIBSSH2_FREE(session, secret);
+                ret = LIBSSH2_ERROR_KEX_FAILURE;
+                goto clean_exit;
+            }
+
+            if(free_iv) {
+                _libssh2_explicit_zero(iv, session->remote.crypt->iv_len);
+                LIBSSH2_FREE(session, iv);
+            }
+
+            if(free_secret) {
+                _libssh2_explicit_zero(secret,
+                                       session->remote.crypt->secret_len);
+                LIBSSH2_FREE(session, secret);
+            }
+        }
+        _libssh2_debug(session, LIBSSH2_TRACE_KEX,
+                       "Server to Client IV and Key calculated");
+
+        if(session->local.mac->dtor) {
+            session->local.mac->dtor(session, &session->local.mac_abstract);
+        }
+
+        if(session->local.mac->init) {
+            unsigned char *key = NULL;
+            int free_key = 0;
+
+            LIBSSH2_KEX_METHOD_SHA_VALUE_HASH(256, key,
+                                              session->local.mac->
+                                              key_len,
+                                              (const unsigned char *)"E");
+            if(!key) {
+                ret = LIBSSH2_ERROR_KEX_FAILURE;
+                goto clean_exit;
+            }
+            session->local.mac->init(session, key, &free_key,
+                                     &session->local.mac_abstract);
+
+            if(free_key) {
+                _libssh2_explicit_zero(key, session->local.mac->key_len);
+                LIBSSH2_FREE(session, key);
+            }
+        }
+        _libssh2_debug(session, LIBSSH2_TRACE_KEX,
+                       "Client to Server HMAC Key calculated");
+
+        if(session->remote.mac->dtor) {
+            session->remote.mac->dtor(session, &session->remote.mac_abstract);
+        }
+
+        if(session->remote.mac->init) {
+            unsigned char *key = NULL;
+            int free_key = 0;
+
+            LIBSSH2_KEX_METHOD_SHA_VALUE_HASH(256, key,
+                                              session->remote.mac->
+                                              key_len,
+                                              (const unsigned char *)"F");
+            if(!key) {
+                ret = LIBSSH2_ERROR_KEX_FAILURE;
+                goto clean_exit;
+            }
+            session->remote.mac->init(session, key, &free_key,
+                                      &session->remote.mac_abstract);
+
+            if(free_key) {
+                _libssh2_explicit_zero(key, session->remote.mac->key_len);
+                LIBSSH2_FREE(session, key);
+            }
+        }
+        _libssh2_debug(session, LIBSSH2_TRACE_KEX,
+                       "Server to Client HMAC Key calculated");
+
+        /* Initialize compression for each direction */
+
+        /* Cleanup any existing compression */
+        if(session->local.comp && session->local.comp->dtor) {
+            session->local.comp->dtor(session, 1,
+                                      &session->local.comp_abstract);
+        }
+
+        if(session->local.comp && session->local.comp->init) {
+            if(session->local.comp->init(session, 1,
+                                          &session->local.comp_abstract)) {
+                ret = LIBSSH2_ERROR_KEX_FAILURE;
+                goto clean_exit;
+            }
+        }
+        _libssh2_debug(session, LIBSSH2_TRACE_KEX,
+                       "Client to Server compression initialized");
+
+        if(session->remote.comp && session->remote.comp->dtor) {
+            session->remote.comp->dtor(session, 0,
+                                       &session->remote.comp_abstract);
+        }
+
+        if(session->remote.comp && session->remote.comp->init) {
+            if(session->remote.comp->init(session, 0,
+                                           &session->remote.comp_abstract)) {
+                ret = LIBSSH2_ERROR_KEX_FAILURE;
+                goto clean_exit;
+            }
+        }
+        _libssh2_debug(session, LIBSSH2_TRACE_KEX,
+                       "Server to Client compression initialized");
+
+    }
+
+  clean_exit:
+    libssh2_dh_dtor(&exchange_state->x);
+    _libssh2_bn_free(exchange_state->e);
+    exchange_state->e = NULL;
+    _libssh2_bn_free(exchange_state->f);
+    exchange_state->f = NULL;
+    _libssh2_bn_free(exchange_state->k);
+    exchange_state->k = NULL;
+    _libssh2_bn_ctx_free(exchange_state->ctx);
+    exchange_state->ctx = NULL;
+
+    if(exchange_state->e_packet) {
+        LIBSSH2_FREE(session, exchange_state->e_packet);
+        exchange_state->e_packet = NULL;
+    }
+
+    if(exchange_state->s_packet) {
+        LIBSSH2_FREE(session, exchange_state->s_packet);
+        exchange_state->s_packet = NULL;
+    }
+
+    if(exchange_state->k_value) {
+        LIBSSH2_FREE(session, exchange_state->k_value);
+        exchange_state->k_value = NULL;
+    }
+
+    exchange_state->state = libssh2_NB_state_idle;
+
+    return ret;
+}
+
+
+
+/* kex_method_diffie_hellman_group1_sha1_key_exchange
+ * Diffie-Hellman Group1 (Actually Group2) Key Exchange using SHA1
+ */
+static int
+kex_method_diffie_hellman_group1_sha1_key_exchange(LIBSSH2_SESSION *session,
+                                                   key_exchange_state_low_t
+                                                   * key_state)
+{
+    static const unsigned char p_value[128] = {
+        0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+        0xC9, 0x0F, 0xDA, 0xA2, 0x21, 0x68, 0xC2, 0x34,
+        0xC4, 0xC6, 0x62, 0x8B, 0x80, 0xDC, 0x1C, 0xD1,
+        0x29, 0x02, 0x4E, 0x08, 0x8A, 0x67, 0xCC, 0x74,
+        0x02, 0x0B, 0xBE, 0xA6, 0x3B, 0x13, 0x9B, 0x22,
+        0x51, 0x4A, 0x08, 0x79, 0x8E, 0x34, 0x04, 0xDD,
+        0xEF, 0x95, 0x19, 0xB3, 0xCD, 0x3A, 0x43, 0x1B,
+        0x30, 0x2B, 0x0A, 0x6D, 0xF2, 0x5F, 0x14, 0x37,
+        0x4F, 0xE1, 0x35, 0x6D, 0x6D, 0x51, 0xC2, 0x45,
+        0xE4, 0x85, 0xB5, 0x76, 0x62, 0x5E, 0x7E, 0xC6,
+        0xF4, 0x4C, 0x42, 0xE9, 0xA6, 0x37, 0xED, 0x6B,
+        0x0B, 0xFF, 0x5C, 0xB6, 0xF4, 0x06, 0xB7, 0xED,
+        0xEE, 0x38, 0x6B, 0xFB, 0x5A, 0x89, 0x9F, 0xA5,
+        0xAE, 0x9F, 0x24, 0x11, 0x7C, 0x4B, 0x1F, 0xE6,
+        0x49, 0x28, 0x66, 0x51, 0xEC, 0xE6, 0x53, 0x81,
+        0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
+    };
+
+    int ret;
+
+    if(key_state->state == libssh2_NB_state_idle) {
+        /* g == 2 */
+        key_state->p = _libssh2_bn_init_from_bin(); /* SSH2 defined value
+                                                       (p_value) */
+        key_state->g = _libssh2_bn_init();      /* SSH2 defined value (2) */
+
+        /* Initialize P and G */
+        _libssh2_bn_set_word(key_state->g, 2);
+        _libssh2_bn_from_bin(key_state->p, 128, p_value);
+
+        _libssh2_debug(session, LIBSSH2_TRACE_KEX,
+                       "Initiating Diffie-Hellman Group1 Key Exchange");
+
+        key_state->state = libssh2_NB_state_created;
+    }
+    ret = diffie_hellman_sha1(session, key_state->g, key_state->p, 128,
+                              SSH_MSG_KEXDH_INIT, SSH_MSG_KEXDH_REPLY,
+                              NULL, 0, &key_state->exchange_state);
+    if(ret == LIBSSH2_ERROR_EAGAIN) {
+        return ret;
+    }
+
+    _libssh2_bn_free(key_state->p);
+    key_state->p = NULL;
+    _libssh2_bn_free(key_state->g);
+    key_state->g = NULL;
+    key_state->state = libssh2_NB_state_idle;
+
+    return ret;
+}
+
+
+
+/* kex_method_diffie_hellman_group14_sha1_key_exchange
+ * Diffie-Hellman Group14 Key Exchange using SHA1
+ */
+static int
+kex_method_diffie_hellman_group14_sha1_key_exchange(LIBSSH2_SESSION *session,
+                                                    key_exchange_state_low_t
+                                                    * key_state)
+{
+    static const unsigned char p_value[256] = {
+        0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+        0xC9, 0x0F, 0xDA, 0xA2, 0x21, 0x68, 0xC2, 0x34,
+        0xC4, 0xC6, 0x62, 0x8B, 0x80, 0xDC, 0x1C, 0xD1,
+        0x29, 0x02, 0x4E, 0x08, 0x8A, 0x67, 0xCC, 0x74,
+        0x02, 0x0B, 0xBE, 0xA6, 0x3B, 0x13, 0x9B, 0x22,
+        0x51, 0x4A, 0x08, 0x79, 0x8E, 0x34, 0x04, 0xDD,
+        0xEF, 0x95, 0x19, 0xB3, 0xCD, 0x3A, 0x43, 0x1B,
+        0x30, 0x2B, 0x0A, 0x6D, 0xF2, 0x5F, 0x14, 0x37,
+        0x4F, 0xE1, 0x35, 0x6D, 0x6D, 0x51, 0xC2, 0x45,
+        0xE4, 0x85, 0xB5, 0x76, 0x62, 0x5E, 0x7E, 0xC6,
+        0xF4, 0x4C, 0x42, 0xE9, 0xA6, 0x37, 0xED, 0x6B,
+        0x0B, 0xFF, 0x5C, 0xB6, 0xF4, 0x06, 0xB7, 0xED,
+        0xEE, 0x38, 0x6B, 0xFB, 0x5A, 0x89, 0x9F, 0xA5,
+        0xAE, 0x9F, 0x24, 0x11, 0x7C, 0x4B, 0x1F, 0xE6,
+        0x49, 0x28, 0x66, 0x51, 0xEC, 0xE4, 0x5B, 0x3D,
+        0xC2, 0x00, 0x7C, 0xB8, 0xA1, 0x63, 0xBF, 0x05,
+        0x98, 0xDA, 0x48, 0x36, 0x1C, 0x55, 0xD3, 0x9A,
+        0x69, 0x16, 0x3F, 0xA8, 0xFD, 0x24, 0xCF, 0x5F,
+        0x83, 0x65, 0x5D, 0x23, 0xDC, 0xA3, 0xAD, 0x96,
+        0x1C, 0x62, 0xF3, 0x56, 0x20, 0x85, 0x52, 0xBB,
+        0x9E, 0xD5, 0x29, 0x07, 0x70, 0x96, 0x96, 0x6D,
+        0x67, 0x0C, 0x35, 0x4E, 0x4A, 0xBC, 0x98, 0x04,
+        0xF1, 0x74, 0x6C, 0x08, 0xCA, 0x18, 0x21, 0x7C,
+        0x32, 0x90, 0x5E, 0x46, 0x2E, 0x36, 0xCE, 0x3B,
+        0xE3, 0x9E, 0x77, 0x2C, 0x18, 0x0E, 0x86, 0x03,
+        0x9B, 0x27, 0x83, 0xA2, 0xEC, 0x07, 0xA2, 0x8F,
+        0xB5, 0xC5, 0x5D, 0xF0, 0x6F, 0x4C, 0x52, 0xC9,
+        0xDE, 0x2B, 0xCB, 0xF6, 0x95, 0x58, 0x17, 0x18,
+        0x39, 0x95, 0x49, 0x7C, 0xEA, 0x95, 0x6A, 0xE5,
+        0x15, 0xD2, 0x26, 0x18, 0x98, 0xFA, 0x05, 0x10,
+        0x15, 0x72, 0x8E, 0x5A, 0x8A, 0xAC, 0xAA, 0x68,
+        0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
+    };
+    int ret;
+
+    if(key_state->state == libssh2_NB_state_idle) {
+        key_state->p = _libssh2_bn_init_from_bin(); /* SSH2 defined value
+                                                       (p_value) */
+        key_state->g = _libssh2_bn_init();      /* SSH2 defined value (2) */
+
+        /* g == 2 */
+        /* Initialize P and G */
+        _libssh2_bn_set_word(key_state->g, 2);
+        _libssh2_bn_from_bin(key_state->p, 256, p_value);
+
+        _libssh2_debug(session, LIBSSH2_TRACE_KEX,
+                       "Initiating Diffie-Hellman Group14 Key Exchange");
+
+        key_state->state = libssh2_NB_state_created;
+    }
+    ret = diffie_hellman_sha1(session, key_state->g, key_state->p,
+                              256, SSH_MSG_KEXDH_INIT, SSH_MSG_KEXDH_REPLY,
+                              NULL, 0, &key_state->exchange_state);
+    if(ret == LIBSSH2_ERROR_EAGAIN) {
+        return ret;
+    }
+
+    key_state->state = libssh2_NB_state_idle;
+    _libssh2_bn_free(key_state->p);
+    key_state->p = NULL;
+    _libssh2_bn_free(key_state->g);
+    key_state->g = NULL;
+
+    return ret;
+}
+
+
+
+/* kex_method_diffie_hellman_group_exchange_sha1_key_exchange
+ * Diffie-Hellman Group Exchange Key Exchange using SHA1
+ * Negotiates random(ish) group for secret derivation
+ */
+static int
+kex_method_diffie_hellman_group_exchange_sha1_key_exchange
+(LIBSSH2_SESSION * session, key_exchange_state_low_t * key_state)
+{
+    int ret = 0;
+    int rc;
+
+    if(key_state->state == libssh2_NB_state_idle) {
+        key_state->p = _libssh2_bn_init_from_bin();
+        key_state->g = _libssh2_bn_init_from_bin();
+        /* Ask for a P and G pair */
+#ifdef LIBSSH2_DH_GEX_NEW
+        key_state->request[0] = SSH_MSG_KEX_DH_GEX_REQUEST;
+        _libssh2_htonu32(key_state->request + 1, LIBSSH2_DH_GEX_MINGROUP);
+        _libssh2_htonu32(key_state->request + 5, LIBSSH2_DH_GEX_OPTGROUP);
+        _libssh2_htonu32(key_state->request + 9, LIBSSH2_DH_GEX_MAXGROUP);
+        key_state->request_len = 13;
+        _libssh2_debug(session, LIBSSH2_TRACE_KEX,
+                       "Initiating Diffie-Hellman Group-Exchange "
+                       "(New Method)");
+#else
+        key_state->request[0] = SSH_MSG_KEX_DH_GEX_REQUEST_OLD;
+        _libssh2_htonu32(key_state->request + 1, LIBSSH2_DH_GEX_OPTGROUP);
+        key_state->request_len = 5;
+        _libssh2_debug(session, LIBSSH2_TRACE_KEX,
+                       "Initiating Diffie-Hellman Group-Exchange "
+                       "(Old Method)");
+#endif
+
+        key_state->state = libssh2_NB_state_created;
+    }
+
+    if(key_state->state == libssh2_NB_state_created) {
+        rc = _libssh2_transport_send(session, key_state->request,
+                                     key_state->request_len, NULL, 0);
+        if(rc == LIBSSH2_ERROR_EAGAIN) {
+            return rc;
+        }
+        else if(rc) {
+            ret = _libssh2_error(session, rc,
+                                 "Unable to send Group Exchange Request");
+            goto dh_gex_clean_exit;
+        }
+
+        key_state->state = libssh2_NB_state_sent;
+    }
+
+    if(key_state->state == libssh2_NB_state_sent) {
+        rc = _libssh2_packet_require(session, SSH_MSG_KEX_DH_GEX_GROUP,
+                                     &key_state->data, &key_state->data_len,
+                                     0, NULL, 0, &key_state->req_state);
+        if(rc == LIBSSH2_ERROR_EAGAIN) {
+            return rc;
+        }
+        else if(rc) {
+            ret = _libssh2_error(session, rc,
+                                 "Timeout waiting for GEX_GROUP reply");
+            goto dh_gex_clean_exit;
+        }
+
+        key_state->state = libssh2_NB_state_sent1;
+    }
+
+    if(key_state->state == libssh2_NB_state_sent1) {
+        size_t p_len, g_len;
+        unsigned char *p, *g;
+        struct string_buf buf;
+
+        if(key_state->data_len < 9) {
+            ret = _libssh2_error(session, LIBSSH2_ERROR_PROTO,
+                                 "Unexpected key length");
+            goto dh_gex_clean_exit;
+        }
+
+        buf.data = key_state->data;
+        buf.dataptr = buf.data;
+        buf.len = key_state->data_len;
+
+        buf.dataptr++; /* increment to big num */
+
+        if(_libssh2_get_bignum_bytes(&buf, &p, &p_len)) {
+            ret = _libssh2_error(session, LIBSSH2_ERROR_PROTO,
+                                 "Unexpected value");
+            goto dh_gex_clean_exit;
+        }
+
+        if(_libssh2_get_bignum_bytes(&buf, &g, &g_len)) {
+            ret = _libssh2_error(session, LIBSSH2_ERROR_PROTO,
+                                 "Unexpected value");
+            goto dh_gex_clean_exit;
+        }
+
+        _libssh2_bn_from_bin(key_state->p, p_len, p);
+        _libssh2_bn_from_bin(key_state->g, g_len, g);
+
+        ret = diffie_hellman_sha1(session, key_state->g, key_state->p, p_len,
+                                  SSH_MSG_KEX_DH_GEX_INIT,
+                                  SSH_MSG_KEX_DH_GEX_REPLY,
+                                  key_state->data + 1,
+                                  key_state->data_len - 1,
+                                  &key_state->exchange_state);
+        if(ret == LIBSSH2_ERROR_EAGAIN) {
+            return ret;
+        }
+
+        LIBSSH2_FREE(session, key_state->data);
+    }
+
+  dh_gex_clean_exit:
+    key_state->state = libssh2_NB_state_idle;
+    _libssh2_bn_free(key_state->g);
+    key_state->g = NULL;
+    _libssh2_bn_free(key_state->p);
+    key_state->p = NULL;
+
+    return ret;
+}
+
+
+
+/* kex_method_diffie_hellman_group_exchange_sha256_key_exchange
+ * Diffie-Hellman Group Exchange Key Exchange using SHA256
+ * Negotiates random(ish) group for secret derivation
+ */
+static int
+kex_method_diffie_hellman_group_exchange_sha256_key_exchange
+(LIBSSH2_SESSION * session, key_exchange_state_low_t * key_state)
+{
+    int ret = 0;
+    int rc;
+
+    if(key_state->state == libssh2_NB_state_idle) {
+        key_state->p = _libssh2_bn_init();
+        key_state->g = _libssh2_bn_init();
+        /* Ask for a P and G pair */
+#ifdef LIBSSH2_DH_GEX_NEW
+        key_state->request[0] = SSH_MSG_KEX_DH_GEX_REQUEST;
+        _libssh2_htonu32(key_state->request + 1, LIBSSH2_DH_GEX_MINGROUP);
+        _libssh2_htonu32(key_state->request + 5, LIBSSH2_DH_GEX_OPTGROUP);
+        _libssh2_htonu32(key_state->request + 9, LIBSSH2_DH_GEX_MAXGROUP);
+        key_state->request_len = 13;
+        _libssh2_debug(session, LIBSSH2_TRACE_KEX,
+                       "Initiating Diffie-Hellman Group-Exchange "
+                       "(New Method SHA256)");
+#else
+        key_state->request[0] = SSH_MSG_KEX_DH_GEX_REQUEST_OLD;
+        _libssh2_htonu32(key_state->request + 1, LIBSSH2_DH_GEX_OPTGROUP);
+        key_state->request_len = 5;
+        _libssh2_debug(session, LIBSSH2_TRACE_KEX,
+                       "Initiating Diffie-Hellman Group-Exchange "
+                       "(Old Method SHA256)");
+#endif
+
+        key_state->state = libssh2_NB_state_created;
+    }
+
+    if(key_state->state == libssh2_NB_state_created) {
+        rc = _libssh2_transport_send(session, key_state->request,
+                                     key_state->request_len, NULL, 0);
+        if(rc == LIBSSH2_ERROR_EAGAIN) {
+            return rc;
+        }
+        else if(rc) {
+            ret = _libssh2_error(session, rc,
+                                 "Unable to send "
+                                 "Group Exchange Request SHA256");
+            goto dh_gex_clean_exit;
+        }
+
+        key_state->state = libssh2_NB_state_sent;
+    }
+
+    if(key_state->state == libssh2_NB_state_sent) {
+        rc = _libssh2_packet_require(session, SSH_MSG_KEX_DH_GEX_GROUP,
+                                     &key_state->data, &key_state->data_len,
+                                     0, NULL, 0, &key_state->req_state);
+        if(rc == LIBSSH2_ERROR_EAGAIN) {
+            return rc;
+        }
+        else if(rc) {
+            ret = _libssh2_error(session, rc,
+                                 "Timeout waiting for GEX_GROUP reply SHA256");
+            goto dh_gex_clean_exit;
+        }
+
+        key_state->state = libssh2_NB_state_sent1;
+    }
+
+    if(key_state->state == libssh2_NB_state_sent1) {
+        unsigned char *p, *g;
+        size_t p_len, g_len;
+        struct string_buf buf;
+
+        if(key_state->data_len < 9) {
+            ret = _libssh2_error(session, LIBSSH2_ERROR_PROTO,
+                                 "Unexpected key length");
+            goto dh_gex_clean_exit;
+        }
+
+        buf.data = key_state->data;
+        buf.dataptr = buf.data;
+        buf.len = key_state->data_len;
+
+        buf.dataptr++; /* increment to big num */
+
+        if(_libssh2_get_bignum_bytes(&buf, &p, &p_len)) {
+            ret = _libssh2_error(session, LIBSSH2_ERROR_PROTO,
+                                 "Unexpected value");
+            goto dh_gex_clean_exit;
+        }
+
+        if(_libssh2_get_bignum_bytes(&buf, &g, &g_len)) {
+            ret = _libssh2_error(session, LIBSSH2_ERROR_PROTO,
+                                 "Unexpected value");
+            goto dh_gex_clean_exit;
+        }
+
+        _libssh2_bn_from_bin(key_state->p, p_len, p);
+        _libssh2_bn_from_bin(key_state->g, g_len, g);
+
+        ret = diffie_hellman_sha256(session, key_state->g, key_state->p, p_len,
+                                    SSH_MSG_KEX_DH_GEX_INIT,
+                                    SSH_MSG_KEX_DH_GEX_REPLY,
+                                    key_state->data + 1,
+                                    key_state->data_len - 1,
+                                    &key_state->exchange_state);
+        if(ret == LIBSSH2_ERROR_EAGAIN) {
+            return ret;
+        }
+
+        LIBSSH2_FREE(session, key_state->data);
+    }
+
+  dh_gex_clean_exit:
+    key_state->state = libssh2_NB_state_idle;
+    _libssh2_bn_free(key_state->g);
+    key_state->g = NULL;
+    _libssh2_bn_free(key_state->p);
+    key_state->p = NULL;
+
+    return ret;
+}
+
+
+#if LIBSSH2_ECDSA
+
+/* kex_session_ecdh_curve_type
+ * returns the EC curve type by name used in key exchange
+ */
+
+static int
+kex_session_ecdh_curve_type(const char *name, libssh2_curve_type *out_type)
+{
+    int ret = 0;
+    libssh2_curve_type type;
+
+    if(name == NULL)
+        return -1;
+
+    if(strcmp(name, "ecdh-sha2-nistp256") == 0)
+        type = LIBSSH2_EC_CURVE_NISTP256;
+    else if(strcmp(name, "ecdh-sha2-nistp384") == 0)
+        type = LIBSSH2_EC_CURVE_NISTP384;
+    else if(strcmp(name, "ecdh-sha2-nistp521") == 0)
+        type = LIBSSH2_EC_CURVE_NISTP521;
+    else {
+        ret = -1;
+    }
+
+    if(ret == 0 && out_type) {
+        *out_type = type;
+    }
+
+    return ret;
+}
+
+
+/* LIBSSH2_KEX_METHOD_EC_SHA_HASH_CREATE_VERIFY
+ *
+ * Macro that create and verifies EC SHA hash with a given digest bytes
+ *
+ * Payload format:
+ *
+ * string   V_C, client's identification string (CR and LF excluded)
+ * string   V_S, server's identification string (CR and LF excluded)
+ * string   I_C, payload of the client's SSH_MSG_KEXINIT
+ * string   I_S, payload of the server's SSH_MSG_KEXINIT
+ * string   K_S, server's public host key
+ * string   Q_C, client's ephemeral public key octet string
+ * string   Q_S, server's ephemeral public key octet string
+ * mpint    K,   shared secret
+ *
+ */
+
+#define LIBSSH2_KEX_METHOD_EC_SHA_HASH_CREATE_VERIFY(digest_type)       \
+{                                                                       \
+    libssh2_sha##digest_type##_ctx ctx;                                 \
+    exchange_state->exchange_hash = (void *)&ctx;                       \
+    libssh2_sha##digest_type##_init(&ctx);                              \
+    if(session->local.banner) {                                         \
+        _libssh2_htonu32(exchange_state->h_sig_comp,                    \
+                         strlen((char *) session->local.banner) - 2);   \
+        libssh2_sha##digest_type##_update(ctx,                          \
+                                          exchange_state->h_sig_comp, 4); \
+        libssh2_sha##digest_type##_update(ctx,                          \
+                                          (char *) session->local.banner, \
+                                          strlen((char *)               \
+                                                 session->local.banner) \
+                                          - 2);                         \
+    }                                                                   \
+    else {                                                              \
+        _libssh2_htonu32(exchange_state->h_sig_comp,                    \
+                         sizeof(LIBSSH2_SSH_DEFAULT_BANNER) - 1);       \
+        libssh2_sha##digest_type##_update(ctx,                          \
+                                          exchange_state->h_sig_comp, 4); \
+        libssh2_sha##digest_type##_update(ctx,                          \
+                                          LIBSSH2_SSH_DEFAULT_BANNER,   \
+                                          sizeof(LIBSSH2_SSH_DEFAULT_BANNER) \
+                                          - 1);                         \
+    }                                                                   \
+                                                                        \
+    _libssh2_htonu32(exchange_state->h_sig_comp,                        \
+                     strlen((char *) session->remote.banner));          \
+    libssh2_sha##digest_type##_update(ctx,                              \
+                                      exchange_state->h_sig_comp, 4);   \
+    libssh2_sha##digest_type##_update(ctx,                              \
+                                      session->remote.banner,           \
+                                      strlen((char *)                   \
+                                             session->remote.banner));  \
+                                                                        \
+    _libssh2_htonu32(exchange_state->h_sig_comp,                        \
+                     session->local.kexinit_len);                       \
+    libssh2_sha##digest_type##_update(ctx,                              \
+                                      exchange_state->h_sig_comp, 4);   \
+    libssh2_sha##digest_type##_update(ctx,                              \
+                                      session->local.kexinit,           \
+                                      session->local.kexinit_len);      \
+                                                                        \
+    _libssh2_htonu32(exchange_state->h_sig_comp,                        \
+                     session->remote.kexinit_len);                      \
+    libssh2_sha##digest_type##_update(ctx,                              \
+                                      exchange_state->h_sig_comp, 4);   \
+    libssh2_sha##digest_type##_update(ctx,                              \
+                                      session->remote.kexinit,          \
+                                      session->remote.kexinit_len);     \
+                                                                        \
+    _libssh2_htonu32(exchange_state->h_sig_comp,                        \
+                     session->server_hostkey_len);                      \
+    libssh2_sha##digest_type##_update(ctx,                              \
+                                      exchange_state->h_sig_comp, 4);   \
+    libssh2_sha##digest_type##_update(ctx,                              \
+                                      session->server_hostkey,          \
+                                      session->server_hostkey_len);     \
+                                                                        \
+    _libssh2_htonu32(exchange_state->h_sig_comp,                        \
+                     public_key_len);                                   \
+    libssh2_sha##digest_type##_update(ctx,                              \
+                                      exchange_state->h_sig_comp, 4);   \
+    libssh2_sha##digest_type##_update(ctx,                              \
+                                      public_key,                       \
+                                      public_key_len);                  \
+                                                                        \
+    _libssh2_htonu32(exchange_state->h_sig_comp,                        \
+                     server_public_key_len);                            \
+    libssh2_sha##digest_type##_update(ctx,                              \
+                                      exchange_state->h_sig_comp, 4);   \
+    libssh2_sha##digest_type##_update(ctx,                              \
+                                      server_public_key,                \
+                                      server_public_key_len);           \
+                                                                        \
+    libssh2_sha##digest_type##_update(ctx,                              \
+                                      exchange_state->k_value,          \
+                                      exchange_state->k_value_len);     \
+                                                                        \
+    libssh2_sha##digest_type##_final(ctx, exchange_state->h_sig_comp);  \
+                                                                        \
+    if(session->hostkey->                                               \
+       sig_verify(session, exchange_state->h_sig,                       \
+                  exchange_state->h_sig_len, exchange_state->h_sig_comp, \
+                  SHA##digest_type##_DIGEST_LENGTH,                     \
+                  &session->server_hostkey_abstract)) {                 \
+        rc = -1;                                                        \
+    }                                                                   \
+}                                                                       \
+
+
+/* ecdh_sha2_nistp
+ * Elliptic Curve Diffie Hellman Key Exchange
+ */
+
+static int ecdh_sha2_nistp(LIBSSH2_SESSION *session, libssh2_curve_type type,
+                           unsigned char *data, size_t data_len,
+                           unsigned char *public_key,
+                           size_t public_key_len, _libssh2_ec_key *private_key,
+                           kmdhgGPshakex_state_t *exchange_state)
+{
+    int ret = 0;
+    int rc;
+
+    if(data_len < 5) {
+        ret = _libssh2_error(session, LIBSSH2_ERROR_HOSTKEY_INIT,
+                            "Host key data is too short");
+        return ret;
+    }
+
+    if(exchange_state->state == libssh2_NB_state_idle) {
+
+        /* Setup initial values */
+        exchange_state->k = _libssh2_bn_init();
+
+        exchange_state->state = libssh2_NB_state_created;
+    }
+
+    if(exchange_state->state == libssh2_NB_state_created) {
+        /* parse INIT reply data */
+
+        /* host key K_S */
+        unsigned char *s = data + 1; /* Advance past packet type */
+        unsigned char *server_public_key;
+        size_t server_public_key_len;
+        size_t host_sig_len;
+
+        session->server_hostkey_len =
+            _libssh2_ntohu32((const unsigned char *)s);
+        s += 4;
+
+        session->server_hostkey = LIBSSH2_ALLOC(session,
+                                                session->server_hostkey_len);
+        if(!session->server_hostkey) {
+            ret = _libssh2_error(session, LIBSSH2_ERROR_ALLOC,
+                                 "Unable to allocate memory for a copy "
+                                 "of the host key");
+            goto clean_exit;
+        }
+
+        memcpy(session->server_hostkey, s, session->server_hostkey_len);
+        s += session->server_hostkey_len;
+
+#if LIBSSH2_MD5
+        {
+            libssh2_md5_ctx fingerprint_ctx;
+
+            if(libssh2_md5_init(&fingerprint_ctx)) {
+                libssh2_md5_update(fingerprint_ctx, session->server_hostkey,
+                                   session->server_hostkey_len);
+                libssh2_md5_final(fingerprint_ctx,
+                                  session->server_hostkey_md5);
+                session->server_hostkey_md5_valid = TRUE;
+            }
+            else {
+                session->server_hostkey_md5_valid = FALSE;
+            }
+        }
+#ifdef LIBSSH2DEBUG
+        {
+            char fingerprint[50], *fprint = fingerprint;
+            int i;
+            for(i = 0; i < 16; i++, fprint += 3) {
+                snprintf(fprint, 4, "%02x:", session->server_hostkey_md5[i]);
+            }
+            *(--fprint) = '\0';
+            _libssh2_debug(session, LIBSSH2_TRACE_KEX,
+                           "Server's MD5 Fingerprint: %s", fingerprint);
+        }
+#endif /* LIBSSH2DEBUG */
+#endif /* ! LIBSSH2_MD5 */
+
+        {
+            libssh2_sha1_ctx fingerprint_ctx;
+
+            if(libssh2_sha1_init(&fingerprint_ctx)) {
+                libssh2_sha1_update(fingerprint_ctx, session->server_hostkey,
+                                    session->server_hostkey_len);
+                libssh2_sha1_final(fingerprint_ctx,
+                                   session->server_hostkey_sha1);
+                session->server_hostkey_sha1_valid = TRUE;
+            }
+            else {
+                session->server_hostkey_sha1_valid = FALSE;
+            }
+        }
+#ifdef LIBSSH2DEBUG
+        {
+            char fingerprint[64], *fprint = fingerprint;
+            int i;
+
+            for(i = 0; i < 20; i++, fprint += 3) {
+                snprintf(fprint, 4, "%02x:", session->server_hostkey_sha1[i]);
+            }
+            *(--fprint) = '\0';
+            _libssh2_debug(session, LIBSSH2_TRACE_KEX,
+                           "Server's SHA1 Fingerprint: %s", fingerprint);
+        }
+#endif /* LIBSSH2DEBUG */
+
+        /* SHA256 */
+        {
+            libssh2_sha256_ctx fingerprint_ctx;
+
+            if(libssh2_sha256_init(&fingerprint_ctx)) {
+                libssh2_sha256_update(fingerprint_ctx, session->server_hostkey,
+                                      session->server_hostkey_len);
+                libssh2_sha256_final(fingerprint_ctx,
+                                     session->server_hostkey_sha256);
+                session->server_hostkey_sha256_valid = TRUE;
+            }
+            else {
+                session->server_hostkey_sha256_valid = FALSE;
+            }
+        }
+#ifdef LIBSSH2DEBUG
+        {
+            char *base64Fingerprint = NULL;
+            _libssh2_base64_encode(session,
+                                   (const char *)
+                                   session->server_hostkey_sha256,
+                                   SHA256_DIGEST_LENGTH, &base64Fingerprint);
+            if(base64Fingerprint != NULL) {
+                _libssh2_debug(session, LIBSSH2_TRACE_KEX,
+                               "Server's SHA256 Fingerprint: %s",
+                               base64Fingerprint);
+                LIBSSH2_FREE(session, base64Fingerprint);
+            }
+        }
+#endif /* LIBSSH2DEBUG */
+
+        if(session->hostkey->init(session, session->server_hostkey,
+                                   session->server_hostkey_len,
+                                   &session->server_hostkey_abstract)) {
+            ret = _libssh2_error(session, LIBSSH2_ERROR_HOSTKEY_INIT,
+                                 "Unable to initialize hostkey importer");
+            goto clean_exit;
+        }
+
+        /* server public key Q_S */
+        server_public_key_len = _libssh2_ntohu32((const unsigned char *)s);
+        s += 4;
+
+        server_public_key = s;
+        s += server_public_key_len;
+
+        /* server signature */
+        host_sig_len = _libssh2_ntohu32((const unsigned char *)s);
+        s += 4;
+
+        exchange_state->h_sig = s;
+        exchange_state->h_sig_len = host_sig_len;
+        s += host_sig_len;
+
+        /* Compute the shared secret K */
+        rc = _libssh2_ecdh_gen_k(&exchange_state->k, private_key,
+                                 server_public_key, server_public_key_len);
+        if(rc != 0) {
+            ret = _libssh2_error(session, LIBSSH2_ERROR_KEX_FAILURE,
+                                 "Unable to create ECDH shared secret");
+            goto clean_exit;
+        }
+
+        exchange_state->k_value_len = _libssh2_bn_bytes(exchange_state->k) + 5;
+        if(_libssh2_bn_bits(exchange_state->k) % 8) {
+            /* don't need leading 00 */
+            exchange_state->k_value_len--;
+        }
+        exchange_state->k_value =
+        LIBSSH2_ALLOC(session, exchange_state->k_value_len);
+        if(!exchange_state->k_value) {
+            ret = _libssh2_error(session, LIBSSH2_ERROR_ALLOC,
+                                 "Unable to allocate buffer for K");
+            goto clean_exit;
+        }
+        _libssh2_htonu32(exchange_state->k_value,
+                         exchange_state->k_value_len - 4);
+        if(_libssh2_bn_bits(exchange_state->k) % 8) {
+            _libssh2_bn_to_bin(exchange_state->k, exchange_state->k_value + 4);
+        }
+        else {
+            exchange_state->k_value[4] = 0;
+            _libssh2_bn_to_bin(exchange_state->k, exchange_state->k_value + 5);
+        }
+
+        /* verify hash */
+
+        switch(type) {
+            case LIBSSH2_EC_CURVE_NISTP256:
+                LIBSSH2_KEX_METHOD_EC_SHA_HASH_CREATE_VERIFY(256);
+                break;
+
+            case LIBSSH2_EC_CURVE_NISTP384:
+                LIBSSH2_KEX_METHOD_EC_SHA_HASH_CREATE_VERIFY(384);
+                break;
+            case LIBSSH2_EC_CURVE_NISTP521:
+                LIBSSH2_KEX_METHOD_EC_SHA_HASH_CREATE_VERIFY(512);
+                break;
+        }
+
+        if(rc != 0) {
+            ret = _libssh2_error(session, LIBSSH2_ERROR_HOSTKEY_SIGN,
+                                 "Unable to verify hostkey signature");
+            goto clean_exit;
+        }
+
+        exchange_state->c = SSH_MSG_NEWKEYS;
+        exchange_state->state = libssh2_NB_state_sent;
+    }
+
+    if(exchange_state->state == libssh2_NB_state_sent) {
+        rc = _libssh2_transport_send(session, &exchange_state->c, 1, NULL, 0);
+        if(rc == LIBSSH2_ERROR_EAGAIN) {
+            return rc;
+        }
+        else if(rc) {
+            ret = _libssh2_error(session, rc,
+                                 "Unable to send NEWKEYS message");
+            goto clean_exit;
+        }
+
+        exchange_state->state = libssh2_NB_state_sent2;
+    }
+
+    if(exchange_state->state == libssh2_NB_state_sent2) {
+        rc = _libssh2_packet_require(session, SSH_MSG_NEWKEYS,
+                                     &exchange_state->tmp,
+                                     &exchange_state->tmp_len, 0, NULL, 0,
+                                     &exchange_state->req_state);
+        if(rc == LIBSSH2_ERROR_EAGAIN) {
+            return rc;
+        }
+        else if(rc) {
+            ret = _libssh2_error(session, rc, "Timed out waiting for NEWKEYS");
+            goto clean_exit;
+        }
+
+        /* The first key exchange has been performed,
+         switch to active crypt/comp/mac mode */
+        session->state |= LIBSSH2_STATE_NEWKEYS;
+        _libssh2_debug(session, LIBSSH2_TRACE_KEX, "Received NEWKEYS message");
+
+        /* This will actually end up being just packet_type(1)
+         for this packet type anyway */
+        LIBSSH2_FREE(session, exchange_state->tmp);
+
+        if(!session->session_id) {
+
+            size_t digest_length = 0;
+
+            if(type == LIBSSH2_EC_CURVE_NISTP256)
+                digest_length = SHA256_DIGEST_LENGTH;
+            else if(type == LIBSSH2_EC_CURVE_NISTP384)
+                digest_length = SHA384_DIGEST_LENGTH;
+            else if(type == LIBSSH2_EC_CURVE_NISTP521)
+                digest_length = SHA512_DIGEST_LENGTH;
+            else{
+                ret = _libssh2_error(session, LIBSSH2_ERROR_KEX_FAILURE,
+                                     "Unknown SHA digest for EC curve");
+                goto clean_exit;
+
+            }
+            session->session_id = LIBSSH2_ALLOC(session, digest_length);
+            if(!session->session_id) {
+                ret = _libssh2_error(session, LIBSSH2_ERROR_ALLOC,
+                                     "Unable to allocate buffer for "
+                                     "SHA digest");
+                goto clean_exit;
+            }
+            memcpy(session->session_id, exchange_state->h_sig_comp,
+                   digest_length);
+             session->session_id_len = digest_length;
+            _libssh2_debug(session, LIBSSH2_TRACE_KEX,
+                           "session_id calculated");
+        }
+
+        /* Cleanup any existing cipher */
+        if(session->local.crypt->dtor) {
+            session->local.crypt->dtor(session,
+                                       &session->local.crypt_abstract);
+        }
+
+        /* Calculate IV/Secret/Key for each direction */
+        if(session->local.crypt->init) {
+            unsigned char *iv = NULL, *secret = NULL;
+            int free_iv = 0, free_secret = 0;
+
+            LIBSSH2_KEX_METHOD_EC_SHA_VALUE_HASH(iv,
+                                                 session->local.crypt->
+                                                 iv_len, "A");
+            if(!iv) {
+                ret = -1;
+                goto clean_exit;
+            }
+
+            LIBSSH2_KEX_METHOD_EC_SHA_VALUE_HASH(secret,
+                                                session->local.crypt->
+                                                secret_len, "C");
+
+            if(!secret) {
+                LIBSSH2_FREE(session, iv);
+                ret = LIBSSH2_ERROR_KEX_FAILURE;
+                goto clean_exit;
+            }
+            if(session->local.crypt->
+                init(session, session->local.crypt, iv, &free_iv, secret,
+                     &free_secret, 1, &session->local.crypt_abstract)) {
+                    LIBSSH2_FREE(session, iv);
+                    LIBSSH2_FREE(session, secret);
+                    ret = LIBSSH2_ERROR_KEX_FAILURE;
+                    goto clean_exit;
+                }
+
+            if(free_iv) {
+                _libssh2_explicit_zero(iv, session->local.crypt->iv_len);
+                LIBSSH2_FREE(session, iv);
+            }
+
+            if(free_secret) {
+                _libssh2_explicit_zero(secret,
+                                       session->local.crypt->secret_len);
+                LIBSSH2_FREE(session, secret);
+            }
+        }
+        _libssh2_debug(session, LIBSSH2_TRACE_KEX,
+                       "Client to Server IV and Key calculated");
+
+        if(session->remote.crypt->dtor) {
+            /* Cleanup any existing cipher */
+            session->remote.crypt->dtor(session,
+                                        &session->remote.crypt_abstract);
+        }
+
+        if(session->remote.crypt->init) {
+            unsigned char *iv = NULL, *secret = NULL;
+            int free_iv = 0, free_secret = 0;
+
+            LIBSSH2_KEX_METHOD_EC_SHA_VALUE_HASH(iv,
+                                                 session->remote.crypt->
+                                                 iv_len, "B");
+
+            if(!iv) {
+                ret = LIBSSH2_ERROR_KEX_FAILURE;
+                goto clean_exit;
+            }
+            LIBSSH2_KEX_METHOD_EC_SHA_VALUE_HASH(secret,
+                                                 session->remote.crypt->
+                                                 secret_len, "D");
+
+            if(!secret) {
+                LIBSSH2_FREE(session, iv);
+                ret = LIBSSH2_ERROR_KEX_FAILURE;
+                goto clean_exit;
+            }
+            if(session->remote.crypt->
+                init(session, session->remote.crypt, iv, &free_iv, secret,
+                     &free_secret, 0, &session->remote.crypt_abstract)) {
+                    LIBSSH2_FREE(session, iv);
+                    LIBSSH2_FREE(session, secret);
+                    ret = LIBSSH2_ERROR_KEX_FAILURE;
+                    goto clean_exit;
+                }
+
+            if(free_iv) {
+                _libssh2_explicit_zero(iv, session->remote.crypt->iv_len);
+                LIBSSH2_FREE(session, iv);
+            }
+
+            if(free_secret) {
+                _libssh2_explicit_zero(secret,
+                                       session->remote.crypt->secret_len);
+                LIBSSH2_FREE(session, secret);
+            }
+        }
+        _libssh2_debug(session, LIBSSH2_TRACE_KEX,
+                       "Server to Client IV and Key calculated");
+
+        if(session->local.mac->dtor) {
+            session->local.mac->dtor(session, &session->local.mac_abstract);
+        }
+
+        if(session->local.mac->init) {
+            unsigned char *key = NULL;
+            int free_key = 0;
+
+            LIBSSH2_KEX_METHOD_EC_SHA_VALUE_HASH(key,
+                                                 session->local.mac->
+                                                 key_len, "E");
+
+            if(!key) {
+                ret = LIBSSH2_ERROR_KEX_FAILURE;
+                goto clean_exit;
+            }
+            session->local.mac->init(session, key, &free_key,
+                                     &session->local.mac_abstract);
+
+            if(free_key) {
+                _libssh2_explicit_zero(key, session->local.mac->key_len);
+                LIBSSH2_FREE(session, key);
+            }
+        }
+        _libssh2_debug(session, LIBSSH2_TRACE_KEX,
+                       "Client to Server HMAC Key calculated");
+
+        if(session->remote.mac->dtor) {
+            session->remote.mac->dtor(session, &session->remote.mac_abstract);
+        }
+
+        if(session->remote.mac->init) {
+            unsigned char *key = NULL;
+            int free_key = 0;
+
+            LIBSSH2_KEX_METHOD_EC_SHA_VALUE_HASH(key,
+                                                 session->remote.mac->
+                                                 key_len, "F");
+
+            if(!key) {
+                ret = LIBSSH2_ERROR_KEX_FAILURE;
+                goto clean_exit;
+            }
+            session->remote.mac->init(session, key, &free_key,
+                                      &session->remote.mac_abstract);
+
+            if(free_key) {
+                _libssh2_explicit_zero(key, session->remote.mac->key_len);
+                LIBSSH2_FREE(session, key);
+            }
+        }
+        _libssh2_debug(session, LIBSSH2_TRACE_KEX,
+                       "Server to Client HMAC Key calculated");
+
+        /* Initialize compression for each direction */
+
+        /* Cleanup any existing compression */
+        if(session->local.comp && session->local.comp->dtor) {
+            session->local.comp->dtor(session, 1,
+                                      &session->local.comp_abstract);
+        }
+
+        if(session->local.comp && session->local.comp->init) {
+            if(session->local.comp->init(session, 1,
+                                          &session->local.comp_abstract)) {
+                ret = LIBSSH2_ERROR_KEX_FAILURE;
+                goto clean_exit;
+            }
+        }
+        _libssh2_debug(session, LIBSSH2_TRACE_KEX,
+                       "Client to Server compression initialized");
+
+        if(session->remote.comp && session->remote.comp->dtor) {
+            session->remote.comp->dtor(session, 0,
+                                       &session->remote.comp_abstract);
+        }
+
+        if(session->remote.comp && session->remote.comp->init) {
+            if(session->remote.comp->init(session, 0,
+                                           &session->remote.comp_abstract)) {
+                ret = LIBSSH2_ERROR_KEX_FAILURE;
+                goto clean_exit;
+            }
+        }
+        _libssh2_debug(session, LIBSSH2_TRACE_KEX,
+                       "Server to Client compression initialized");
+
+    }
+
+clean_exit:
+    _libssh2_bn_free(exchange_state->k);
+    exchange_state->k = NULL;
+
+    if(exchange_state->k_value) {
+        LIBSSH2_FREE(session, exchange_state->k_value);
+        exchange_state->k_value = NULL;
+    }
+
+    exchange_state->state = libssh2_NB_state_idle;
+
+    return ret;
+}
+
+/* kex_method_ecdh_key_exchange
+ *
+ * Elliptic Curve Diffie Hellman Key Exchange
+ * supports SHA256/384/512 hashes based on negotated ecdh method
+ *
+ */
+
+static int
+kex_method_ecdh_key_exchange
+(LIBSSH2_SESSION * session, key_exchange_state_low_t * key_state)
+{
+    int ret = 0;
+    int rc = 0;
+    unsigned char *s;
+    libssh2_curve_type type;
+
+    if(key_state->state == libssh2_NB_state_idle) {
+
+        key_state->public_key_oct = NULL;
+        key_state->state = libssh2_NB_state_created;
+    }
+
+    if(key_state->state == libssh2_NB_state_created) {
+        rc = kex_session_ecdh_curve_type(session->kex->name, &type);
+
+        if(rc != 0) {
+            ret = _libssh2_error(session, -1,
+                                 "Unknown KEX nistp curve type");
+            goto ecdh_clean_exit;
+        }
+
+        rc = _libssh2_ecdsa_create_key(session, &key_state->private_key,
+                                       &key_state->public_key_oct,
+                                       &key_state->public_key_oct_len, type);
+
+        if(rc != 0) {
+            ret = _libssh2_error(session, rc,
+                                 "Unable to create private key");
+            goto ecdh_clean_exit;
+        }
+
+        key_state->request[0] = SSH2_MSG_KEX_ECDH_INIT;
+        s = key_state->request + 1;
+        _libssh2_store_str(&s, (const char *)key_state->public_key_oct,
+                           key_state->public_key_oct_len);
+        key_state->request_len = key_state->public_key_oct_len + 5;
+
+        _libssh2_debug(session, LIBSSH2_TRACE_KEX,
+                       "Initiating ECDH SHA2 NISTP256");
+
+        key_state->state = libssh2_NB_state_sent;
+    }
+
+    if(key_state->state == libssh2_NB_state_sent) {
+        rc = _libssh2_transport_send(session, key_state->request,
+                                     key_state->request_len, NULL, 0);
+        if(rc == LIBSSH2_ERROR_EAGAIN) {
+            return rc;
+        }
+        else if(rc) {
+            ret = _libssh2_error(session, rc,
+                                 "Unable to send ECDH_INIT");
+            goto ecdh_clean_exit;
+        }
+
+        key_state->state = libssh2_NB_state_sent1;
+    }
+
+    if(key_state->state == libssh2_NB_state_sent1) {
+        rc = _libssh2_packet_require(session, SSH2_MSG_KEX_ECDH_REPLY,
+                                     &key_state->data, &key_state->data_len,
+                                     0, NULL, 0, &key_state->req_state);
+        if(rc == LIBSSH2_ERROR_EAGAIN) {
+            return rc;
+        }
+        else if(rc) {
+            ret = _libssh2_error(session, rc,
+                                 "Timeout waiting for ECDH_REPLY reply");
+            goto ecdh_clean_exit;
+        }
+
+        key_state->state = libssh2_NB_state_sent2;
+    }
+
+    if(key_state->state == libssh2_NB_state_sent2) {
+
+        (void)kex_session_ecdh_curve_type(session->kex->name, &type);
+
+        ret = ecdh_sha2_nistp(session, type, key_state->data,
+                              key_state->data_len,
+                              (unsigned char *)key_state->public_key_oct,
+                              key_state->public_key_oct_len,
+                              key_state->private_key,
+                              &key_state->exchange_state);
+
+        if(ret == LIBSSH2_ERROR_EAGAIN) {
+            return ret;
+        }
+
+        LIBSSH2_FREE(session, key_state->data);
+    }
+
+ecdh_clean_exit:
+
+    if(key_state->public_key_oct) {
+        LIBSSH2_FREE(session, key_state->public_key_oct);
+        key_state->public_key_oct = NULL;
+    }
+
+    if(key_state->private_key) {
+        _libssh2_ecdsa_free(key_state->private_key);
+        key_state->private_key = NULL;
+    }
+
+    key_state->state = libssh2_NB_state_idle;
+
+    return ret;
+}
+
+#endif /*LIBSSH2_ECDSA*/
+
+
+#if LIBSSH2_ED25519
+
+/* curve25519_sha256
+ * Elliptic Curve Key Exchange
+ */
+
+static int
+curve25519_sha256(LIBSSH2_SESSION *session, unsigned char *data,
+                  size_t data_len,
+                  unsigned char public_key[LIBSSH2_ED25519_KEY_LEN],
+                  unsigned char private_key[LIBSSH2_ED25519_KEY_LEN],
+                  kmdhgGPshakex_state_t *exchange_state)
+{
+    int ret = 0;
+    int rc;
+    int public_key_len = LIBSSH2_ED25519_KEY_LEN;
+
+    if(data_len < 5) {
+        return _libssh2_error(session, LIBSSH2_ERROR_HOSTKEY_INIT,
+                              "Data is too short");
+    }
+
+    if(exchange_state->state == libssh2_NB_state_idle) {
+
+        /* Setup initial values */
+        exchange_state->k = _libssh2_bn_init();
+
+        exchange_state->state = libssh2_NB_state_created;
+    }
+
+    if(exchange_state->state == libssh2_NB_state_created) {
+        /* parse INIT reply data */
+        unsigned char *server_public_key, *server_host_key;
+        size_t server_public_key_len, hostkey_len;
+        struct string_buf buf;
+
+        if(data_len < 5) {
+            ret = _libssh2_error(session, LIBSSH2_ERROR_PROTO,
+                                 "Unexpected key length");
+            goto clean_exit;
+        }
+
+        buf.data = data;
+        buf.len = data_len;
+        buf.dataptr = buf.data;
+        buf.dataptr++; /* advance past packet type */
+
+        if(_libssh2_get_string(&buf, &server_host_key, &hostkey_len)) {
+            ret = _libssh2_error(session, LIBSSH2_ERROR_PROTO,
+                                 "Unexpected key length");
+            goto clean_exit;
+        }
+
+        session->server_hostkey_len = (uint32_t)hostkey_len;
+        session->server_hostkey = LIBSSH2_ALLOC(session,
+                                                session->server_hostkey_len);
+        if(!session->server_hostkey) {
+            ret = _libssh2_error(session, LIBSSH2_ERROR_ALLOC,
+                                 "Unable to allocate memory for a copy "
+                                 "of the host key");
+            goto clean_exit;
+        }
+
+        memcpy(session->server_hostkey, server_host_key,
+               session->server_hostkey_len);
+
+#if LIBSSH2_MD5
+        {
+            libssh2_md5_ctx fingerprint_ctx;
+
+            if(libssh2_md5_init(&fingerprint_ctx)) {
+                libssh2_md5_update(fingerprint_ctx, session->server_hostkey,
+                                   session->server_hostkey_len);
+                libssh2_md5_final(fingerprint_ctx,
+                                  session->server_hostkey_md5);
+                session->server_hostkey_md5_valid = TRUE;
+            }
+            else {
+                session->server_hostkey_md5_valid = FALSE;
+            }
+        }
+#ifdef LIBSSH2DEBUG
+        {
+            char fingerprint[50], *fprint = fingerprint;
+            int i;
+            for(i = 0; i < 16; i++, fprint += 3) {
+                snprintf(fprint, 4, "%02x:", session->server_hostkey_md5[i]);
+            }
+            *(--fprint) = '\0';
+            _libssh2_debug(session, LIBSSH2_TRACE_KEX,
+                             "Server's MD5 Fingerprint: %s", fingerprint);
+        }
+#endif /* LIBSSH2DEBUG */
+#endif /* ! LIBSSH2_MD5 */
+
+        {
+            libssh2_sha1_ctx fingerprint_ctx;
+
+            if(libssh2_sha1_init(&fingerprint_ctx)) {
+                libssh2_sha1_update(fingerprint_ctx, session->server_hostkey,
+                                    session->server_hostkey_len);
+                libssh2_sha1_final(fingerprint_ctx,
+                                   session->server_hostkey_sha1);
+                session->server_hostkey_sha1_valid = TRUE;
+            }
+            else {
+                session->server_hostkey_sha1_valid = FALSE;
+            }
+        }
+#ifdef LIBSSH2DEBUG
+        {
+            char fingerprint[64], *fprint = fingerprint;
+            int i;
+
+            for(i = 0; i < 20; i++, fprint += 3) {
+                snprintf(fprint, 4, "%02x:", session->server_hostkey_sha1[i]);
+            }
+            *(--fprint) = '\0';
+            _libssh2_debug(session, LIBSSH2_TRACE_KEX,
+                             "Server's SHA1 Fingerprint: %s", fingerprint);
+        }
+#endif /* LIBSSH2DEBUG */
+
+        /* SHA256 */
+        {
+            libssh2_sha256_ctx fingerprint_ctx;
+
+            if(libssh2_sha256_init(&fingerprint_ctx)) {
+                libssh2_sha256_update(fingerprint_ctx, session->server_hostkey,
+                                      session->server_hostkey_len);
+                libssh2_sha256_final(fingerprint_ctx,
+                                     session->server_hostkey_sha256);
+                session->server_hostkey_sha256_valid = TRUE;
+            }
+            else {
+                session->server_hostkey_sha256_valid = FALSE;
+            }
+        }
+#ifdef LIBSSH2DEBUG
+        {
+            char *base64Fingerprint = NULL;
+            _libssh2_base64_encode(session,
+                                   (const char *)
+                                   session->server_hostkey_sha256,
+                                   SHA256_DIGEST_LENGTH, &base64Fingerprint);
+            if(base64Fingerprint != NULL) {
+                _libssh2_debug(session, LIBSSH2_TRACE_KEX,
+                               "Server's SHA256 Fingerprint: %s",
+                               base64Fingerprint);
+                LIBSSH2_FREE(session, base64Fingerprint);
+            }
+        }
+#endif /* LIBSSH2DEBUG */
+
+        if(session->hostkey->init(session, session->server_hostkey,
+                                   session->server_hostkey_len,
+                                   &session->server_hostkey_abstract)) {
+            ret = _libssh2_error(session, LIBSSH2_ERROR_HOSTKEY_INIT,
+                                 "Unable to initialize hostkey importer");
+            goto clean_exit;
+        }
+
+        /* server public key Q_S */
+        if(_libssh2_get_string(&buf, &server_public_key,
+                               &server_public_key_len)) {
+            ret = _libssh2_error(session, LIBSSH2_ERROR_PROTO,
+                                     "Unexpected key length");
+            goto clean_exit;
+        }
+
+        if(server_public_key_len != LIBSSH2_ED25519_KEY_LEN) {
+            ret = _libssh2_error(session, LIBSSH2_ERROR_HOSTKEY_INIT,
+                                 "Unexpected curve25519 server "
+                                 "public key length");
+            goto clean_exit;
+        }
+
+        /* server signature */
+        if(_libssh2_get_string(&buf, &exchange_state->h_sig,
+           &(exchange_state->h_sig_len))) {
+            ret = _libssh2_error(session, LIBSSH2_ERROR_HOSTKEY_INIT,
+                                 "Unexpected curve25519 server sig length");
+            goto clean_exit;
+        }
+
+        /* Compute the shared secret K */
+        rc = _libssh2_curve25519_gen_k(&exchange_state->k, private_key,
+                                       server_public_key);
+        if(rc != 0) {
+            ret = _libssh2_error(session, LIBSSH2_ERROR_KEX_FAILURE,
+                                 "Unable to create ECDH shared secret");
+            goto clean_exit;
+        }
+
+        exchange_state->k_value_len = _libssh2_bn_bytes(exchange_state->k) + 5;
+        if(_libssh2_bn_bits(exchange_state->k) % 8) {
+            /* don't need leading 00 */
+            exchange_state->k_value_len--;
+        }
+        exchange_state->k_value =
+        LIBSSH2_ALLOC(session, exchange_state->k_value_len);
+        if(!exchange_state->k_value) {
+            ret = _libssh2_error(session, LIBSSH2_ERROR_ALLOC,
+                                 "Unable to allocate buffer for K");
+            goto clean_exit;
+        }
+        _libssh2_htonu32(exchange_state->k_value,
+                         exchange_state->k_value_len - 4);
+        if(_libssh2_bn_bits(exchange_state->k) % 8) {
+            _libssh2_bn_to_bin(exchange_state->k, exchange_state->k_value + 4);
+        }
+        else {
+            exchange_state->k_value[4] = 0;
+            _libssh2_bn_to_bin(exchange_state->k, exchange_state->k_value + 5);
+        }
+
+        /*/ verify hash */
+        LIBSSH2_KEX_METHOD_EC_SHA_HASH_CREATE_VERIFY(256);
+
+        if(rc != 0) {
+            ret = _libssh2_error(session, LIBSSH2_ERROR_HOSTKEY_SIGN,
+                                 "Unable to verify hostkey signature");
+            goto clean_exit;
+        }
+
+        exchange_state->c = SSH_MSG_NEWKEYS;
+        exchange_state->state = libssh2_NB_state_sent;
+    }
+
+    if(exchange_state->state == libssh2_NB_state_sent) {
+        rc = _libssh2_transport_send(session, &exchange_state->c, 1, NULL, 0);
+        if(rc == LIBSSH2_ERROR_EAGAIN) {
+            return rc;
+        }
+        else if(rc) {
+            ret = _libssh2_error(session, rc,
+                                 "Unable to send NEWKEYS message");
+            goto clean_exit;
+        }
+
+        exchange_state->state = libssh2_NB_state_sent2;
+    }
+
+    if(exchange_state->state == libssh2_NB_state_sent2) {
+        rc = _libssh2_packet_require(session, SSH_MSG_NEWKEYS,
+                                     &exchange_state->tmp,
+                                     &exchange_state->tmp_len, 0, NULL, 0,
+                                     &exchange_state->req_state);
+        if(rc == LIBSSH2_ERROR_EAGAIN) {
+            return rc;
+        }
+        else if(rc) {
+            ret = _libssh2_error(session, rc, "Timed out waiting for NEWKEYS");
+            goto clean_exit;
+        }
+
+        /* The first key exchange has been performed, switch to active
+           crypt/comp/mac mode */
+
+        session->state |= LIBSSH2_STATE_NEWKEYS;
+        _libssh2_debug(session, LIBSSH2_TRACE_KEX, "Received NEWKEYS message");
+
+        /* This will actually end up being just packet_type(1) for this packet
+           type anyway */
+        LIBSSH2_FREE(session, exchange_state->tmp);
+
+        if(!session->session_id) {
+
+            size_t digest_length = SHA256_DIGEST_LENGTH;
+            session->session_id = LIBSSH2_ALLOC(session, digest_length);
+            if(!session->session_id) {
+                ret = _libssh2_error(session, LIBSSH2_ERROR_ALLOC,
+                                     "Unable to allxcocate buffer for "
+                                     "SHA digest");
+                goto clean_exit;
+            }
+            memcpy(session->session_id, exchange_state->h_sig_comp,
+                   digest_length);
+            session->session_id_len = digest_length;
+            _libssh2_debug(session, LIBSSH2_TRACE_KEX,
+                           "session_id calculated");
+        }
+
+        /* Cleanup any existing cipher */
+        if(session->local.crypt->dtor) {
+            session->local.crypt->dtor(session,
+                                        &session->local.crypt_abstract);
+        }
+
+        /* Calculate IV/Secret/Key for each direction */
+        if(session->local.crypt->init) {
+            unsigned char *iv = NULL, *secret = NULL;
+            int free_iv = 0, free_secret = 0;
+
+            LIBSSH2_KEX_METHOD_SHA_VALUE_HASH(256, iv,
+                                              session->local.crypt->
+                                              iv_len, "A");
+            if(!iv) {
+                ret = -1;
+                goto clean_exit;
+            }
+
+            LIBSSH2_KEX_METHOD_SHA_VALUE_HASH(256, secret,
+                                              session->local.crypt->
+                                              secret_len, "C");
+
+            if(!secret) {
+                LIBSSH2_FREE(session, iv);
+                ret = LIBSSH2_ERROR_KEX_FAILURE;
+                goto clean_exit;
+            }
+            if(session->local.crypt->
+                init(session, session->local.crypt, iv, &free_iv, secret,
+                     &free_secret, 1, &session->local.crypt_abstract)) {
+                    LIBSSH2_FREE(session, iv);
+                    LIBSSH2_FREE(session, secret);
+                    ret = LIBSSH2_ERROR_KEX_FAILURE;
+                    goto clean_exit;
+                }
+
+            if(free_iv) {
+                _libssh2_explicit_zero(iv, session->local.crypt->iv_len);
+                LIBSSH2_FREE(session, iv);
+            }
+
+            if(free_secret) {
+                _libssh2_explicit_zero(secret,
+                                       session->local.crypt->secret_len);
+                LIBSSH2_FREE(session, secret);
+            }
+        }
+        _libssh2_debug(session, LIBSSH2_TRACE_KEX,
+                        "Client to Server IV and Key calculated");
+
+        if(session->remote.crypt->dtor) {
+            /* Cleanup any existing cipher */
+            session->remote.crypt->dtor(session,
+                                        &session->remote.crypt_abstract);
+        }
+
+        if(session->remote.crypt->init) {
+            unsigned char *iv = NULL, *secret = NULL;
+            int free_iv = 0, free_secret = 0;
+
+            LIBSSH2_KEX_METHOD_SHA_VALUE_HASH(256, iv,
+                                              session->remote.crypt->
+                                              iv_len, "B");
+
+            if(!iv) {
+                ret = LIBSSH2_ERROR_KEX_FAILURE;
+                goto clean_exit;
+            }
+            LIBSSH2_KEX_METHOD_SHA_VALUE_HASH(256, secret,
+                                              session->remote.crypt->
+                                              secret_len, "D");
+
+            if(!secret) {
+                LIBSSH2_FREE(session, iv);
+                ret = LIBSSH2_ERROR_KEX_FAILURE;
+                goto clean_exit;
+            }
+            if(session->remote.crypt->
+                init(session, session->remote.crypt, iv, &free_iv, secret,
+                     &free_secret, 0, &session->remote.crypt_abstract)) {
+                    LIBSSH2_FREE(session, iv);
+                    LIBSSH2_FREE(session, secret);
+                    ret = LIBSSH2_ERROR_KEX_FAILURE;
+                    goto clean_exit;
+                }
+
+            if(free_iv) {
+                _libssh2_explicit_zero(iv, session->remote.crypt->iv_len);
+                LIBSSH2_FREE(session, iv);
+            }
+
+            if(free_secret) {
+                _libssh2_explicit_zero(secret,
+                                       session->remote.crypt->secret_len);
+                LIBSSH2_FREE(session, secret);
+            }
+        }
+        _libssh2_debug(session, LIBSSH2_TRACE_KEX,
+                        "Server to Client IV and Key calculated");
+
+        if(session->local.mac->dtor) {
+            session->local.mac->dtor(session, &session->local.mac_abstract);
+        }
+
+        if(session->local.mac->init) {
+            unsigned char *key = NULL;
+            int free_key = 0;
+
+            LIBSSH2_KEX_METHOD_SHA_VALUE_HASH(256, key,
+                                              session->local.mac->
+                                              key_len, "E");
+
+            if(!key) {
+                ret = LIBSSH2_ERROR_KEX_FAILURE;
+                goto clean_exit;
+            }
+            session->local.mac->init(session, key, &free_key,
+                                     &session->local.mac_abstract);
+
+            if(free_key) {
+                _libssh2_explicit_zero(key, session->local.mac->key_len);
+                LIBSSH2_FREE(session, key);
+            }
+        }
+        _libssh2_debug(session, LIBSSH2_TRACE_KEX,
+                        "Client to Server HMAC Key calculated");
+
+        if(session->remote.mac->dtor) {
+            session->remote.mac->dtor(session, &session->remote.mac_abstract);
+        }
+
+        if(session->remote.mac->init) {
+            unsigned char *key = NULL;
+            int free_key = 0;
+
+            LIBSSH2_KEX_METHOD_SHA_VALUE_HASH(256, key,
+                                              session->remote.mac->
+                                              key_len, "F");
+
+            if(!key) {
+                ret = LIBSSH2_ERROR_KEX_FAILURE;
+                goto clean_exit;
+            }
+            session->remote.mac->init(session, key, &free_key,
+                                      &session->remote.mac_abstract);
+
+            if(free_key) {
+                _libssh2_explicit_zero(key, session->remote.mac->key_len);
+                LIBSSH2_FREE(session, key);
+            }
+        }
+        _libssh2_debug(session, LIBSSH2_TRACE_KEX,
+                        "Server to Client HMAC Key calculated");
+
+        /* Initialize compression for each direction */
+
+        /* Cleanup any existing compression */
+        if(session->local.comp && session->local.comp->dtor) {
+            session->local.comp->dtor(session, 1,
+                                      &session->local.comp_abstract);
+        }
+
+        if(session->local.comp && session->local.comp->init) {
+            if(session->local.comp->init(session, 1,
+                                            &session->local.comp_abstract)) {
+                ret = LIBSSH2_ERROR_KEX_FAILURE;
+                goto clean_exit;
+            }
+        }
+        _libssh2_debug(session, LIBSSH2_TRACE_KEX,
+                        "Client to Server compression initialized");
+
+        if(session->remote.comp && session->remote.comp->dtor) {
+            session->remote.comp->dtor(session, 0,
+                                        &session->remote.comp_abstract);
+        }
+
+        if(session->remote.comp && session->remote.comp->init) {
+            if(session->remote.comp->init(session, 0,
+                                             &session->remote.comp_abstract)) {
+                ret = LIBSSH2_ERROR_KEX_FAILURE;
+                goto clean_exit;
+            }
+        }
+        _libssh2_debug(session, LIBSSH2_TRACE_KEX,
+                        "Server to Client compression initialized");
+    }
+
+clean_exit:
+    _libssh2_bn_free(exchange_state->k);
+    exchange_state->k = NULL;
+
+    if(exchange_state->k_value) {
+        LIBSSH2_FREE(session, exchange_state->k_value);
+        exchange_state->k_value = NULL;
+    }
+
+    exchange_state->state = libssh2_NB_state_idle;
+
+    return ret;
+}
+
+/* kex_method_curve25519_key_exchange
+ *
+ * Elliptic Curve X25519 Key Exchange with SHA256 hash
+ *
+ */
+
+static int
+kex_method_curve25519_key_exchange
+(LIBSSH2_SESSION * session, key_exchange_state_low_t * key_state)
+{
+    int ret = 0;
+    int rc = 0;
+
+    if(key_state->state == libssh2_NB_state_idle) {
+
+        key_state->public_key_oct = NULL;
+        key_state->state = libssh2_NB_state_created;
+    }
+
+    if(key_state->state == libssh2_NB_state_created) {
+        unsigned char *s = NULL;
+
+        rc = strcmp(session->kex->name, "curve25519-sha256@libssh.org");
+        if(rc != 0)
+            rc = strcmp(session->kex->name, "curve25519-sha256");
+
+        if(rc != 0) {
+            ret = _libssh2_error(session, -1,
+                                 "Unknown KEX curve25519 curve type");
+            goto clean_exit;
+        }
+
+        rc = _libssh2_curve25519_new(session, NULL,
+                                     &key_state->curve25519_public_key,
+                                     &key_state->curve25519_private_key);
+
+        if(rc != 0) {
+            ret = _libssh2_error(session, rc,
+                                 "Unable to create private key");
+            goto clean_exit;
+        }
+
+        key_state->request[0] = SSH2_MSG_KEX_ECDH_INIT;
+        s = key_state->request + 1;
+        _libssh2_store_str(&s, (const char *)key_state->curve25519_public_key,
+                           LIBSSH2_ED25519_KEY_LEN);
+        key_state->request_len = LIBSSH2_ED25519_KEY_LEN + 5;
+
+        _libssh2_debug(session, LIBSSH2_TRACE_KEX,
+                        "Initiating curve25519 SHA2");
+
+        key_state->state = libssh2_NB_state_sent;
+    }
+
+    if(key_state->state == libssh2_NB_state_sent) {
+        rc = _libssh2_transport_send(session, key_state->request,
+                                     key_state->request_len, NULL, 0);
+        if(rc == LIBSSH2_ERROR_EAGAIN) {
+            return rc;
+        }
+        else if(rc) {
+            ret = _libssh2_error(session, rc,
+                                 "Unable to send ECDH_INIT");
+            goto clean_exit;
+        }
+
+        key_state->state = libssh2_NB_state_sent1;
+    }
+
+    if(key_state->state == libssh2_NB_state_sent1) {
+        rc = _libssh2_packet_require(session, SSH2_MSG_KEX_ECDH_REPLY,
+                                     &key_state->data, &key_state->data_len,
+                                     0, NULL, 0, &key_state->req_state);
+        if(rc == LIBSSH2_ERROR_EAGAIN) {
+            return rc;
+        }
+        else if(rc) {
+            ret = _libssh2_error(session, rc,
+                                 "Timeout waiting for ECDH_REPLY reply");
+            goto clean_exit;
+        }
+
+        key_state->state = libssh2_NB_state_sent2;
+    }
+
+    if(key_state->state == libssh2_NB_state_sent2) {
+
+        ret = curve25519_sha256(session, key_state->data, key_state->data_len,
+                                key_state->curve25519_public_key,
+                                key_state->curve25519_private_key,
+                                &key_state->exchange_state);
+
+        if(ret == LIBSSH2_ERROR_EAGAIN) {
+            return ret;
+        }
+
+        LIBSSH2_FREE(session, key_state->data);
+    }
+
+clean_exit:
+
+    if(key_state->curve25519_public_key) {
+        _libssh2_explicit_zero(key_state->curve25519_public_key,
+                               LIBSSH2_ED25519_KEY_LEN);
+        LIBSSH2_FREE(session, key_state->curve25519_public_key);
+        key_state->curve25519_public_key = NULL;
+    }
+
+    if(key_state->curve25519_private_key) {
+        _libssh2_explicit_zero(key_state->curve25519_private_key,
+                               LIBSSH2_ED25519_KEY_LEN);
+        LIBSSH2_FREE(session, key_state->curve25519_private_key);
+        key_state->curve25519_private_key = NULL;
+    }
+
+    key_state->state = libssh2_NB_state_idle;
+
+    return ret;
+}
+
+
+#endif /*LIBSSH2_ED25519*/
+
+
+#define LIBSSH2_KEX_METHOD_FLAG_REQ_ENC_HOSTKEY     0x0001
+#define LIBSSH2_KEX_METHOD_FLAG_REQ_SIGN_HOSTKEY    0x0002
+
+static const LIBSSH2_KEX_METHOD kex_method_diffie_helman_group1_sha1 = {
+    "diffie-hellman-group1-sha1",
+    kex_method_diffie_hellman_group1_sha1_key_exchange,
+    LIBSSH2_KEX_METHOD_FLAG_REQ_SIGN_HOSTKEY,
+};
+
+static const LIBSSH2_KEX_METHOD kex_method_diffie_helman_group14_sha1 = {
+    "diffie-hellman-group14-sha1",
+    kex_method_diffie_hellman_group14_sha1_key_exchange,
+    LIBSSH2_KEX_METHOD_FLAG_REQ_SIGN_HOSTKEY,
+};
+
+static const LIBSSH2_KEX_METHOD
+kex_method_diffie_helman_group_exchange_sha1 = {
+    "diffie-hellman-group-exchange-sha1",
+    kex_method_diffie_hellman_group_exchange_sha1_key_exchange,
+    LIBSSH2_KEX_METHOD_FLAG_REQ_SIGN_HOSTKEY,
+};
+
+static const LIBSSH2_KEX_METHOD
+kex_method_diffie_helman_group_exchange_sha256 = {
+    "diffie-hellman-group-exchange-sha256",
+    kex_method_diffie_hellman_group_exchange_sha256_key_exchange,
+    LIBSSH2_KEX_METHOD_FLAG_REQ_SIGN_HOSTKEY,
+};
+
+#if LIBSSH2_ECDSA
+static const LIBSSH2_KEX_METHOD
+kex_method_ecdh_sha2_nistp256 = {
+    "ecdh-sha2-nistp256",
+    kex_method_ecdh_key_exchange,
+    LIBSSH2_KEX_METHOD_FLAG_REQ_SIGN_HOSTKEY,
+};
+
+static const LIBSSH2_KEX_METHOD
+kex_method_ecdh_sha2_nistp384 = {
+    "ecdh-sha2-nistp384",
+    kex_method_ecdh_key_exchange,
+    LIBSSH2_KEX_METHOD_FLAG_REQ_SIGN_HOSTKEY,
+};
+
+static const LIBSSH2_KEX_METHOD
+kex_method_ecdh_sha2_nistp521 = {
+    "ecdh-sha2-nistp521",
+    kex_method_ecdh_key_exchange,
+    LIBSSH2_KEX_METHOD_FLAG_REQ_SIGN_HOSTKEY,
+};
+#endif
+
+#if LIBSSH2_ED25519
+static const LIBSSH2_KEX_METHOD
+kex_method_ssh_curve25519_sha256_libssh = {
+    "curve25519-sha256@libssh.org",
+    kex_method_curve25519_key_exchange,
+    LIBSSH2_KEX_METHOD_FLAG_REQ_SIGN_HOSTKEY,
+};
+static const LIBSSH2_KEX_METHOD
+kex_method_ssh_curve25519_sha256 = {
+    "curve25519-sha256",
+    kex_method_curve25519_key_exchange,
+    LIBSSH2_KEX_METHOD_FLAG_REQ_SIGN_HOSTKEY,
+};
+#endif
+
+static const LIBSSH2_KEX_METHOD *libssh2_kex_methods[] = {
+#if LIBSSH2_ECDSA
+    &kex_method_ecdh_sha2_nistp256,
+    &kex_method_ecdh_sha2_nistp384,
+    &kex_method_ecdh_sha2_nistp521,
+#endif
+#if LIBSSH2_ED25519
+    &kex_method_ssh_curve25519_sha256,
+    &kex_method_ssh_curve25519_sha256_libssh,
+#endif
+    &kex_method_diffie_helman_group_exchange_sha256,
+    &kex_method_diffie_helman_group_exchange_sha1,
+    &kex_method_diffie_helman_group14_sha1,
+    &kex_method_diffie_helman_group1_sha1,
+    NULL
+};
+
+typedef struct _LIBSSH2_COMMON_METHOD
+{
+    const char *name;
+} LIBSSH2_COMMON_METHOD;
+
+/* kex_method_strlen
+ * Calculate the length of a particular method list's resulting string
+ * Includes SUM(strlen() of each individual method plus 1 (for coma)) - 1
+ * (because the last coma isn't used)
+ * Another sign of bad coding practices gone mad.  Pretend you don't see this.
+ */
+static size_t
+kex_method_strlen(LIBSSH2_COMMON_METHOD ** method)
+{
+    size_t len = 0;
+
+    if(!method || !*method) {
+        return 0;
+    }
+
+    while(*method && (*method)->name) {
+        len += strlen((*method)->name) + 1;
+        method++;
+    }
+
+    return len - 1;
+}
+
+
+
+/* kex_method_list
+ * Generate formatted preference list in buf
+ */
+static size_t
+kex_method_list(unsigned char *buf, size_t list_strlen,
+                LIBSSH2_COMMON_METHOD ** method)
+{
+    _libssh2_htonu32(buf, list_strlen);
+    buf += 4;
+
+    if(!method || !*method) {
+        return 4;
+    }
+
+    while(*method && (*method)->name) {
+        int mlen = strlen((*method)->name);
+        memcpy(buf, (*method)->name, mlen);
+        buf += mlen;
+        *(buf++) = ',';
+        method++;
+    }
+
+    return list_strlen + 4;
+}
+
+
+
+#define LIBSSH2_METHOD_PREFS_LEN(prefvar, defaultvar)           \
+    ((prefvar) ? strlen(prefvar) :                              \
+     kex_method_strlen((LIBSSH2_COMMON_METHOD**)(defaultvar)))
+
+#define LIBSSH2_METHOD_PREFS_STR(buf, prefvarlen, prefvar, defaultvar)  \
+    if(prefvar) {                                                       \
+        _libssh2_htonu32((buf), (prefvarlen));                          \
+        buf += 4;                                                       \
+        memcpy((buf), (prefvar), (prefvarlen));                         \
+        buf += (prefvarlen);                                            \
+    }                                                                   \
+    else {                                                              \
+        buf += kex_method_list((buf), (prefvarlen),                     \
+                               (LIBSSH2_COMMON_METHOD**)(defaultvar));  \
+    }
+
+/* kexinit
+ * Send SSH_MSG_KEXINIT packet
+ */
+static int kexinit(LIBSSH2_SESSION * session)
+{
+    /* 62 = packet_type(1) + cookie(16) + first_packet_follows(1) +
+       reserved(4) + length longs(40) */
+    size_t data_len = 62;
+    size_t kex_len, hostkey_len = 0;
+    size_t crypt_cs_len, crypt_sc_len;
+    size_t comp_cs_len, comp_sc_len;
+    size_t mac_cs_len, mac_sc_len;
+    size_t lang_cs_len, lang_sc_len;
+    unsigned char *data, *s;
+    int rc;
+
+    if(session->kexinit_state == libssh2_NB_state_idle) {
+        kex_len =
+            LIBSSH2_METHOD_PREFS_LEN(session->kex_prefs, libssh2_kex_methods);
+        hostkey_len =
+            LIBSSH2_METHOD_PREFS_LEN(session->hostkey_prefs,
+                                     libssh2_hostkey_methods());
+        crypt_cs_len =
+            LIBSSH2_METHOD_PREFS_LEN(session->local.crypt_prefs,
+                                     libssh2_crypt_methods());
+        crypt_sc_len =
+            LIBSSH2_METHOD_PREFS_LEN(session->remote.crypt_prefs,
+                                     libssh2_crypt_methods());
+        mac_cs_len =
+            LIBSSH2_METHOD_PREFS_LEN(session->local.mac_prefs,
+                                     _libssh2_mac_methods());
+        mac_sc_len =
+            LIBSSH2_METHOD_PREFS_LEN(session->remote.mac_prefs,
+                                     _libssh2_mac_methods());
+        comp_cs_len =
+            LIBSSH2_METHOD_PREFS_LEN(session->local.comp_prefs,
+                                     _libssh2_comp_methods(session));
+        comp_sc_len =
+            LIBSSH2_METHOD_PREFS_LEN(session->remote.comp_prefs,
+                                     _libssh2_comp_methods(session));
+        lang_cs_len =
+            LIBSSH2_METHOD_PREFS_LEN(session->local.lang_prefs, NULL);
+        lang_sc_len =
+            LIBSSH2_METHOD_PREFS_LEN(session->remote.lang_prefs, NULL);
+
+        data_len += kex_len + hostkey_len + crypt_cs_len + crypt_sc_len +
+            comp_cs_len + comp_sc_len + mac_cs_len + mac_sc_len +
+            lang_cs_len + lang_sc_len;
+
+        s = data = LIBSSH2_ALLOC(session, data_len);
+        if(!data) {
+            return _libssh2_error(session, LIBSSH2_ERROR_ALLOC,
+                                  "Unable to allocate memory");
+        }
+
+        *(s++) = SSH_MSG_KEXINIT;
+
+        _libssh2_random(s, 16);
+        s += 16;
+
+        /* Ennumerating through these lists twice is probably (certainly?)
+           inefficient from a CPU standpoint, but it saves multiple
+           malloc/realloc calls */
+        LIBSSH2_METHOD_PREFS_STR(s, kex_len, session->kex_prefs,
+                                 libssh2_kex_methods);
+        LIBSSH2_METHOD_PREFS_STR(s, hostkey_len, session->hostkey_prefs,
+                                 libssh2_hostkey_methods());
+        LIBSSH2_METHOD_PREFS_STR(s, crypt_cs_len, session->local.crypt_prefs,
+                                 libssh2_crypt_methods());
+        LIBSSH2_METHOD_PREFS_STR(s, crypt_sc_len, session->remote.crypt_prefs,
+                                 libssh2_crypt_methods());
+        LIBSSH2_METHOD_PREFS_STR(s, mac_cs_len, session->local.mac_prefs,
+                                 _libssh2_mac_methods());
+        LIBSSH2_METHOD_PREFS_STR(s, mac_sc_len, session->remote.mac_prefs,
+                                 _libssh2_mac_methods());
+        LIBSSH2_METHOD_PREFS_STR(s, comp_cs_len, session->local.comp_prefs,
+                                 _libssh2_comp_methods(session));
+        LIBSSH2_METHOD_PREFS_STR(s, comp_sc_len, session->remote.comp_prefs,
+                                 _libssh2_comp_methods(session));
+        LIBSSH2_METHOD_PREFS_STR(s, lang_cs_len, session->local.lang_prefs,
+                                 NULL);
+        LIBSSH2_METHOD_PREFS_STR(s, lang_sc_len, session->remote.lang_prefs,
+                                 NULL);
+
+        /* No optimistic KEX packet follows */
+        /* Deal with optimistic packets
+         * session->flags |= KEXINIT_OPTIMISTIC
+         * session->flags |= KEXINIT_METHODSMATCH
+         */
+        *(s++) = 0;
+
+        /* Reserved == 0 */
+        _libssh2_htonu32(s, 0);
+
+#ifdef LIBSSH2DEBUG
+        {
+            /* Funnily enough, they'll all "appear" to be '\0' terminated */
+            unsigned char *p = data + 21;   /* type(1) + cookie(16) + len(4) */
+
+            _libssh2_debug(session, LIBSSH2_TRACE_KEX, "Sent KEX: %s", p);
+            p += kex_len + 4;
+            _libssh2_debug(session, LIBSSH2_TRACE_KEX, "Sent HOSTKEY: %s", p);
+            p += hostkey_len + 4;
+            _libssh2_debug(session, LIBSSH2_TRACE_KEX, "Sent CRYPT_CS: %s", p);
+            p += crypt_cs_len + 4;
+            _libssh2_debug(session, LIBSSH2_TRACE_KEX, "Sent CRYPT_SC: %s", p);
+            p += crypt_sc_len + 4;
+            _libssh2_debug(session, LIBSSH2_TRACE_KEX, "Sent MAC_CS: %s", p);
+            p += mac_cs_len + 4;
+            _libssh2_debug(session, LIBSSH2_TRACE_KEX, "Sent MAC_SC: %s", p);
+            p += mac_sc_len + 4;
+            _libssh2_debug(session, LIBSSH2_TRACE_KEX, "Sent COMP_CS: %s", p);
+            p += comp_cs_len + 4;
+            _libssh2_debug(session, LIBSSH2_TRACE_KEX, "Sent COMP_SC: %s", p);
+            p += comp_sc_len + 4;
+            _libssh2_debug(session, LIBSSH2_TRACE_KEX, "Sent LANG_CS: %s", p);
+            p += lang_cs_len + 4;
+            _libssh2_debug(session, LIBSSH2_TRACE_KEX, "Sent LANG_SC: %s", p);
+            p += lang_sc_len + 4;
+        }
+#endif /* LIBSSH2DEBUG */
+
+        session->kexinit_state = libssh2_NB_state_created;
+    }
+    else {
+        data = session->kexinit_data;
+        data_len = session->kexinit_data_len;
+        /* zap the variables to ensure there is NOT a double free later */
+        session->kexinit_data = NULL;
+        session->kexinit_data_len = 0;
+    }
+
+    rc = _libssh2_transport_send(session, data, data_len, NULL, 0);
+    if(rc == LIBSSH2_ERROR_EAGAIN) {
+        session->kexinit_data = data;
+        session->kexinit_data_len = data_len;
+        return rc;
+    }
+    else if(rc) {
+        LIBSSH2_FREE(session, data);
+        session->kexinit_state = libssh2_NB_state_idle;
+        return _libssh2_error(session, rc,
+                              "Unable to send KEXINIT packet to remote host");
+
+    }
+
+    if(session->local.kexinit) {
+        LIBSSH2_FREE(session, session->local.kexinit);
+    }
+
+    session->local.kexinit = data;
+    session->local.kexinit_len = data_len;
+
+    session->kexinit_state = libssh2_NB_state_idle;
+
+    return 0;
+}
+
+/* kex_agree_instr
+ * Kex specific variant of strstr()
+ * Needle must be precede by BOL or ',', and followed by ',' or EOL
+ */
+static unsigned char *
+kex_agree_instr(unsigned char *haystack, unsigned long haystack_len,
+                const unsigned char *needle, unsigned long needle_len)
+{
+    unsigned char *s;
+
+    /* Haystack too short to bother trying */
+    if(haystack_len < needle_len) {
+        return NULL;
+    }
+
+    /* Needle at start of haystack */
+    if((strncmp((char *) haystack, (char *) needle, needle_len) == 0) &&
+        (needle_len == haystack_len || haystack[needle_len] == ',')) {
+        return haystack;
+    }
+
+    s = haystack;
+    /* Search until we run out of comas or we run out of haystack,
+       whichever comes first */
+    while((s = (unsigned char *) strchr((char *) s, ','))
+           && ((haystack_len - (s - haystack)) > needle_len)) {
+        s++;
+        /* Needle at X position */
+        if((strncmp((char *) s, (char *) needle, needle_len) == 0) &&
+            (((s - haystack) + needle_len) == haystack_len
+             || s[needle_len] == ',')) {
+            return s;
+        }
+    }
+
+    return NULL;
+}
+
+
+
+/* kex_get_method_by_name
+ */
+static const LIBSSH2_COMMON_METHOD *
+kex_get_method_by_name(const char *name, size_t name_len,
+                       const LIBSSH2_COMMON_METHOD ** methodlist)
+{
+    while(*methodlist) {
+        if((strlen((*methodlist)->name) == name_len) &&
+            (strncmp((*methodlist)->name, name, name_len) == 0)) {
+            return *methodlist;
+        }
+        methodlist++;
+    }
+    return NULL;
+}
+
+
+
+/* kex_agree_hostkey
+ * Agree on a Hostkey which works with this kex
+ */
+static int kex_agree_hostkey(LIBSSH2_SESSION * session,
+                             unsigned long kex_flags,
+                             unsigned char *hostkey, unsigned long hostkey_len)
+{
+    const LIBSSH2_HOSTKEY_METHOD **hostkeyp = libssh2_hostkey_methods();
+    unsigned char *s;
+
+    if(session->hostkey_prefs) {
+        s = (unsigned char *) session->hostkey_prefs;
+
+        while(s && *s) {
+            unsigned char *p = (unsigned char *) strchr((char *) s, ',');
+            size_t method_len = (p ? (size_t)(p - s) : strlen((char *) s));
+            if(kex_agree_instr(hostkey, hostkey_len, s, method_len)) {
+                const LIBSSH2_HOSTKEY_METHOD *method =
+                    (const LIBSSH2_HOSTKEY_METHOD *)
+                    kex_get_method_by_name((char *) s, method_len,
+                                           (const LIBSSH2_COMMON_METHOD **)
+                                           hostkeyp);
+
+                if(!method) {
+                    /* Invalid method -- Should never be reached */
+                    return -1;
+                }
+
+                /* So far so good, but does it suit our purposes? (Encrypting
+                   vs Signing) */
+                if(((kex_flags & LIBSSH2_KEX_METHOD_FLAG_REQ_ENC_HOSTKEY) ==
+                     0) || (method->encrypt)) {
+                    /* Either this hostkey can do encryption or this kex just
+                       doesn't require it */
+                    if(((kex_flags & LIBSSH2_KEX_METHOD_FLAG_REQ_SIGN_HOSTKEY)
+                         == 0) || (method->sig_verify)) {
+                        /* Either this hostkey can do signing or this kex just
+                           doesn't require it */
+                        session->hostkey = method;
+                        return 0;
+                    }
+                }
+            }
+
+            s = p ? p + 1 : NULL;
+        }
+        return -1;
+    }
+
+    while(hostkeyp && (*hostkeyp) && (*hostkeyp)->name) {
+        s = kex_agree_instr(hostkey, hostkey_len,
+                            (unsigned char *) (*hostkeyp)->name,
+                            strlen((*hostkeyp)->name));
+        if(s) {
+            /* So far so good, but does it suit our purposes? (Encrypting vs
+               Signing) */
+            if(((kex_flags & LIBSSH2_KEX_METHOD_FLAG_REQ_ENC_HOSTKEY) == 0) ||
+                ((*hostkeyp)->encrypt)) {
+                /* Either this hostkey can do encryption or this kex just
+                   doesn't require it */
+                if(((kex_flags & LIBSSH2_KEX_METHOD_FLAG_REQ_SIGN_HOSTKEY) ==
+                     0) || ((*hostkeyp)->sig_verify)) {
+                    /* Either this hostkey can do signing or this kex just
+                       doesn't require it */
+                    session->hostkey = *hostkeyp;
+                    return 0;
+                }
+            }
+        }
+        hostkeyp++;
+    }
+
+    return -1;
+}
+
+
+
+/* kex_agree_kex_hostkey
+ * Agree on a Key Exchange method and a hostkey encoding type
+ */
+static int kex_agree_kex_hostkey(LIBSSH2_SESSION * session, unsigned char *kex,
+                                 unsigned long kex_len, unsigned char *hostkey,
+                                 unsigned long hostkey_len)
+{
+    const LIBSSH2_KEX_METHOD **kexp = libssh2_kex_methods;
+    unsigned char *s;
+
+    if(session->kex_prefs) {
+        s = (unsigned char *) session->kex_prefs;
+
+        while(s && *s) {
+            unsigned char *q, *p = (unsigned char *) strchr((char *) s, ',');
+            size_t method_len = (p ? (size_t)(p - s) : strlen((char *) s));
+            q = kex_agree_instr(kex, kex_len, s, method_len);
+            if(q) {
+                const LIBSSH2_KEX_METHOD *method = (const LIBSSH2_KEX_METHOD *)
+                    kex_get_method_by_name((char *) s, method_len,
+                                           (const LIBSSH2_COMMON_METHOD **)
+                                           kexp);
+
+                if(!method) {
+                    /* Invalid method -- Should never be reached */
+                    return -1;
+                }
+
+                /* We've agreed on a key exchange method,
+                 * Can we agree on a hostkey that works with this kex?
+                 */
+                if(kex_agree_hostkey(session, method->flags, hostkey,
+                                      hostkey_len) == 0) {
+                    session->kex = method;
+                    if(session->burn_optimistic_kexinit && (kex == q)) {
+                        /* Server sent an optimistic packet, and client agrees
+                         * with preference cancel burning the first KEX_INIT
+                         * packet that comes in */
+                        session->burn_optimistic_kexinit = 0;
+                    }
+                    return 0;
+                }
+            }
+
+            s = p ? p + 1 : NULL;
+        }
+        return -1;
+    }
+
+    while(*kexp && (*kexp)->name) {
+        s = kex_agree_instr(kex, kex_len,
+                            (unsigned char *) (*kexp)->name,
+                            strlen((*kexp)->name));
+        if(s) {
+            /* We've agreed on a key exchange method,
+             * Can we agree on a hostkey that works with this kex?
+             */
+            if(kex_agree_hostkey(session, (*kexp)->flags, hostkey,
+                                  hostkey_len) == 0) {
+                session->kex = *kexp;
+                if(session->burn_optimistic_kexinit && (kex == s)) {
+                    /* Server sent an optimistic packet, and client agrees
+                     * with preference cancel burning the first KEX_INIT
+                     * packet that comes in */
+                    session->burn_optimistic_kexinit = 0;
+                }
+                return 0;
+            }
+        }
+        kexp++;
+    }
+    return -1;
+}
+
+
+
+/* kex_agree_crypt
+ * Agree on a cipher algo
+ */
+static int kex_agree_crypt(LIBSSH2_SESSION * session,
+                           libssh2_endpoint_data *endpoint,
+                           unsigned char *crypt,
+                           unsigned long crypt_len)
+{
+    const LIBSSH2_CRYPT_METHOD **cryptp = libssh2_crypt_methods();
+    unsigned char *s;
+
+    (void) session;
+
+    if(endpoint->crypt_prefs) {
+        s = (unsigned char *) endpoint->crypt_prefs;
+
+        while(s && *s) {
+            unsigned char *p = (unsigned char *) strchr((char *) s, ',');
+            size_t method_len = (p ? (size_t)(p - s) : strlen((char *) s));
+
+            if(kex_agree_instr(crypt, crypt_len, s, method_len)) {
+                const LIBSSH2_CRYPT_METHOD *method =
+                    (const LIBSSH2_CRYPT_METHOD *)
+                    kex_get_method_by_name((char *) s, method_len,
+                                           (const LIBSSH2_COMMON_METHOD **)
+                                           cryptp);
+
+                if(!method) {
+                    /* Invalid method -- Should never be reached */
+                    return -1;
+                }
+
+                endpoint->crypt = method;
+                return 0;
+            }
+
+            s = p ? p + 1 : NULL;
+        }
+        return -1;
+    }
+
+    while(*cryptp && (*cryptp)->name) {
+        s = kex_agree_instr(crypt, crypt_len,
+                            (unsigned char *) (*cryptp)->name,
+                            strlen((*cryptp)->name));
+        if(s) {
+            endpoint->crypt = *cryptp;
+            return 0;
+        }
+        cryptp++;
+    }
+
+    return -1;
+}
+
+
+
+/* kex_agree_mac
+ * Agree on a message authentication hash
+ */
+static int kex_agree_mac(LIBSSH2_SESSION * session,
+                         libssh2_endpoint_data * endpoint, unsigned char *mac,
+                         unsigned long mac_len)
+{
+    const LIBSSH2_MAC_METHOD **macp = _libssh2_mac_methods();
+    unsigned char *s;
+    (void) session;
+
+    if(endpoint->mac_prefs) {
+        s = (unsigned char *) endpoint->mac_prefs;
+
+        while(s && *s) {
+            unsigned char *p = (unsigned char *) strchr((char *) s, ',');
+            size_t method_len = (p ? (size_t)(p - s) : strlen((char *) s));
+
+            if(kex_agree_instr(mac, mac_len, s, method_len)) {
+                const LIBSSH2_MAC_METHOD *method = (const LIBSSH2_MAC_METHOD *)
+                    kex_get_method_by_name((char *) s, method_len,
+                                           (const LIBSSH2_COMMON_METHOD **)
+                                           macp);
+
+                if(!method) {
+                    /* Invalid method -- Should never be reached */
+                    return -1;
+                }
+
+                endpoint->mac = method;
+                return 0;
+            }
+
+            s = p ? p + 1 : NULL;
+        }
+        return -1;
+    }
+
+    while(*macp && (*macp)->name) {
+        s = kex_agree_instr(mac, mac_len, (unsigned char *) (*macp)->name,
+                            strlen((*macp)->name));
+        if(s) {
+            endpoint->mac = *macp;
+            return 0;
+        }
+        macp++;
+    }
+
+    return -1;
+}
+
+
+
+/* kex_agree_comp
+ * Agree on a compression scheme
+ */
+static int kex_agree_comp(LIBSSH2_SESSION *session,
+                          libssh2_endpoint_data *endpoint, unsigned char *comp,
+                          unsigned long comp_len)
+{
+    const LIBSSH2_COMP_METHOD **compp = _libssh2_comp_methods(session);
+    unsigned char *s;
+    (void) session;
+
+    if(endpoint->comp_prefs) {
+        s = (unsigned char *) endpoint->comp_prefs;
+
+        while(s && *s) {
+            unsigned char *p = (unsigned char *) strchr((char *) s, ',');
+            size_t method_len = (p ? (size_t)(p - s) : strlen((char *) s));
+
+            if(kex_agree_instr(comp, comp_len, s, method_len)) {
+                const LIBSSH2_COMP_METHOD *method =
+                    (const LIBSSH2_COMP_METHOD *)
+                    kex_get_method_by_name((char *) s, method_len,
+                                           (const LIBSSH2_COMMON_METHOD **)
+                                           compp);
+
+                if(!method) {
+                    /* Invalid method -- Should never be reached */
+                    return -1;
+                }
+
+                endpoint->comp = method;
+                return 0;
+            }
+
+            s = p ? p + 1 : NULL;
+        }
+        return -1;
+    }
+
+    while(*compp && (*compp)->name) {
+        s = kex_agree_instr(comp, comp_len, (unsigned char *) (*compp)->name,
+                            strlen((*compp)->name));
+        if(s) {
+            endpoint->comp = *compp;
+            return 0;
+        }
+        compp++;
+    }
+
+    return -1;
+}
+
+
+
+/* TODO: When in server mode we need to turn this logic on its head
+ * The Client gets to make the final call on "agreed methods"
+ */
+
+/*
+ * kex_string_pair() extracts a string from the packet and makes sure it fits
+ * within the given packet.
+ */
+static int kex_string_pair(unsigned char **sp,   /* parsing position */
+                           unsigned char *data,  /* start pointer to packet */
+                           size_t data_len,      /* size of total packet */
+                           size_t *lenp,         /* length of the string */
+                           unsigned char **strp) /* pointer to string start */
+{
+    unsigned char *s = *sp;
+    *lenp = _libssh2_ntohu32(s);
+
+    /* the length of the string must fit within the current pointer and the
+       end of the packet */
+    if(*lenp > (data_len - (s - data) -4))
+        return 1;
+    *strp = s + 4;
+    s += 4 + *lenp;
+
+    *sp = s;
+    return 0;
+}
+
+/* kex_agree_methods
+ * Decide which specific method to use of the methods offered by each party
+ */
+static int kex_agree_methods(LIBSSH2_SESSION * session, unsigned char *data,
+                             unsigned data_len)
+{
+    unsigned char *kex, *hostkey, *crypt_cs, *crypt_sc, *comp_cs, *comp_sc,
+        *mac_cs, *mac_sc;
+    size_t kex_len, hostkey_len, crypt_cs_len, crypt_sc_len, comp_cs_len;
+    size_t comp_sc_len, mac_cs_len, mac_sc_len;
+    unsigned char *s = data;
+
+    /* Skip packet_type, we know it already */
+    s++;
+
+    /* Skip cookie, don't worry, it's preserved in the kexinit field */
+    s += 16;
+
+    /* Locate each string */
+    if(kex_string_pair(&s, data, data_len, &kex_len, &kex))
+        return -1;
+    if(kex_string_pair(&s, data, data_len, &hostkey_len, &hostkey))
+        return -1;
+    if(kex_string_pair(&s, data, data_len, &crypt_cs_len, &crypt_cs))
+        return -1;
+    if(kex_string_pair(&s, data, data_len, &crypt_sc_len, &crypt_sc))
+        return -1;
+    if(kex_string_pair(&s, data, data_len, &mac_cs_len, &mac_cs))
+        return -1;
+    if(kex_string_pair(&s, data, data_len, &mac_sc_len, &mac_sc))
+        return -1;
+    if(kex_string_pair(&s, data, data_len, &comp_cs_len, &comp_cs))
+        return -1;
+    if(kex_string_pair(&s, data, data_len, &comp_sc_len, &comp_sc))
+        return -1;
+
+    /* If the server sent an optimistic packet, assume that it guessed wrong.
+     * If the guess is determined to be right (by kex_agree_kex_hostkey)
+     * This flag will be reset to zero so that it's not ignored */
+    session->burn_optimistic_kexinit = *(s++);
+    /* Next uint32 in packet is all zeros (reserved) */
+
+    if(data_len < (unsigned) (s - data))
+        return -1;              /* short packet */
+
+    if(kex_agree_kex_hostkey(session, kex, kex_len, hostkey, hostkey_len)) {
+        return -1;
+    }
+
+    if(kex_agree_crypt(session, &session->local, crypt_cs, crypt_cs_len)
+       || kex_agree_crypt(session, &session->remote, crypt_sc,
+                          crypt_sc_len)) {
+        return -1;
+    }
+
+    if(kex_agree_mac(session, &session->local, mac_cs, mac_cs_len) ||
+        kex_agree_mac(session, &session->remote, mac_sc, mac_sc_len)) {
+        return -1;
+    }
+
+    if(kex_agree_comp(session, &session->local, comp_cs, comp_cs_len) ||
+        kex_agree_comp(session, &session->remote, comp_sc, comp_sc_len)) {
+        return -1;
+    }
+
+#if 0
+    if(libssh2_kex_agree_lang(session, &session->local, lang_cs, lang_cs_len)
+        || libssh2_kex_agree_lang(session, &session->remote, lang_sc,
+                                  lang_sc_len)) {
+        return -1;
+    }
+#endif
+
+    _libssh2_debug(session, LIBSSH2_TRACE_KEX, "Agreed on KEX method: %s",
+                   session->kex->name);
+    _libssh2_debug(session, LIBSSH2_TRACE_KEX, "Agreed on HOSTKEY method: %s",
+                   session->hostkey->name);
+    _libssh2_debug(session, LIBSSH2_TRACE_KEX, "Agreed on CRYPT_CS method: %s",
+                   session->local.crypt->name);
+    _libssh2_debug(session, LIBSSH2_TRACE_KEX, "Agreed on CRYPT_SC method: %s",
+                   session->remote.crypt->name);
+    _libssh2_debug(session, LIBSSH2_TRACE_KEX, "Agreed on MAC_CS method: %s",
+                   session->local.mac->name);
+    _libssh2_debug(session, LIBSSH2_TRACE_KEX, "Agreed on MAC_SC method: %s",
+                   session->remote.mac->name);
+    _libssh2_debug(session, LIBSSH2_TRACE_KEX, "Agreed on COMP_CS method: %s",
+                   session->local.comp->name);
+    _libssh2_debug(session, LIBSSH2_TRACE_KEX, "Agreed on COMP_SC method: %s",
+                   session->remote.comp->name);
+
+    return 0;
+}
+
+
+
+/* _libssh2_kex_exchange
+ * Exchange keys
+ * Returns 0 on success, non-zero on failure
+ *
+ * Returns some errors without _libssh2_error()
+ */
+int
+_libssh2_kex_exchange(LIBSSH2_SESSION * session, int reexchange,
+                      key_exchange_state_t * key_state)
+{
+    int rc = 0;
+    int retcode;
+
+    session->state |= LIBSSH2_STATE_KEX_ACTIVE;
+
+    if(key_state->state == libssh2_NB_state_idle) {
+        /* Prevent loop in packet_add() */
+        session->state |= LIBSSH2_STATE_EXCHANGING_KEYS;
+
+        if(reexchange) {
+            session->kex = NULL;
+
+            if(session->hostkey && session->hostkey->dtor) {
+                session->hostkey->dtor(session,
+                                       &session->server_hostkey_abstract);
+            }
+            session->hostkey = NULL;
+        }
+
+        key_state->state = libssh2_NB_state_created;
+    }
+
+    if(!session->kex || !session->hostkey) {
+        if(key_state->state == libssh2_NB_state_created) {
+            /* Preserve in case of failure */
+            key_state->oldlocal = session->local.kexinit;
+            key_state->oldlocal_len = session->local.kexinit_len;
+
+            session->local.kexinit = NULL;
+
+            key_state->state = libssh2_NB_state_sent;
+        }
+
+        if(key_state->state == libssh2_NB_state_sent) {
+            retcode = kexinit(session);
+            if(retcode == LIBSSH2_ERROR_EAGAIN) {
+                session->state &= ~LIBSSH2_STATE_KEX_ACTIVE;
+                return retcode;
+            }
+            else if(retcode) {
+                session->local.kexinit = key_state->oldlocal;
+                session->local.kexinit_len = key_state->oldlocal_len;
+                key_state->state = libssh2_NB_state_idle;
+                session->state &= ~LIBSSH2_STATE_KEX_ACTIVE;
+                session->state &= ~LIBSSH2_STATE_EXCHANGING_KEYS;
+                return -1;
+            }
+
+            key_state->state = libssh2_NB_state_sent1;
+        }
+
+        if(key_state->state == libssh2_NB_state_sent1) {
+            retcode =
+                _libssh2_packet_require(session, SSH_MSG_KEXINIT,
+                                        &key_state->data,
+                                        &key_state->data_len, 0, NULL, 0,
+                                        &key_state->req_state);
+            if(retcode == LIBSSH2_ERROR_EAGAIN) {
+                session->state &= ~LIBSSH2_STATE_KEX_ACTIVE;
+                return retcode;
+            }
+            else if(retcode) {
+                if(session->local.kexinit) {
+                    LIBSSH2_FREE(session, session->local.kexinit);
+                }
+                session->local.kexinit = key_state->oldlocal;
+                session->local.kexinit_len = key_state->oldlocal_len;
+                key_state->state = libssh2_NB_state_idle;
+                session->state &= ~LIBSSH2_STATE_KEX_ACTIVE;
+                session->state &= ~LIBSSH2_STATE_EXCHANGING_KEYS;
+                return -1;
+            }
+
+            if(session->remote.kexinit) {
+                LIBSSH2_FREE(session, session->remote.kexinit);
+            }
+            session->remote.kexinit = key_state->data;
+            session->remote.kexinit_len = key_state->data_len;
+
+            if(kex_agree_methods(session, key_state->data,
+                                  key_state->data_len))
+                rc = LIBSSH2_ERROR_KEX_FAILURE;
+
+            key_state->state = libssh2_NB_state_sent2;
+        }
+    }
+    else {
+        key_state->state = libssh2_NB_state_sent2;
+    }
+
+    if(rc == 0 && session->kex) {
+        if(key_state->state == libssh2_NB_state_sent2) {
+            retcode = session->kex->exchange_keys(session,
+                                                  &key_state->key_state_low);
+            if(retcode == LIBSSH2_ERROR_EAGAIN) {
+                session->state &= ~LIBSSH2_STATE_KEX_ACTIVE;
+                return retcode;
+            }
+            else if(retcode) {
+                rc = _libssh2_error(session,
+                                    LIBSSH2_ERROR_KEY_EXCHANGE_FAILURE,
+                                    "Unrecoverable error exchanging keys");
+            }
+        }
+    }
+
+    /* Done with kexinit buffers */
+    if(session->local.kexinit) {
+        LIBSSH2_FREE(session, session->local.kexinit);
+        session->local.kexinit = NULL;
+    }
+    if(session->remote.kexinit) {
+        LIBSSH2_FREE(session, session->remote.kexinit);
+        session->remote.kexinit = NULL;
+    }
+
+    session->state &= ~LIBSSH2_STATE_KEX_ACTIVE;
+    session->state &= ~LIBSSH2_STATE_EXCHANGING_KEYS;
+
+    key_state->state = libssh2_NB_state_idle;
+
+    return rc;
+}
+
+
+
+/* libssh2_session_method_pref
+ * Set preferred method
+ */
+LIBSSH2_API int
+libssh2_session_method_pref(LIBSSH2_SESSION * session, int method_type,
+                            const char *prefs)
+{
+    char **prefvar, *s, *newprefs;
+    int prefs_len = strlen(prefs);
+    const LIBSSH2_COMMON_METHOD **mlist;
+
+    switch(method_type) {
+    case LIBSSH2_METHOD_KEX:
+        prefvar = &session->kex_prefs;
+        mlist = (const LIBSSH2_COMMON_METHOD **) libssh2_kex_methods;
+        break;
+
+    case LIBSSH2_METHOD_HOSTKEY:
+        prefvar = &session->hostkey_prefs;
+        mlist = (const LIBSSH2_COMMON_METHOD **) libssh2_hostkey_methods();
+        break;
+
+    case LIBSSH2_METHOD_CRYPT_CS:
+        prefvar = &session->local.crypt_prefs;
+        mlist = (const LIBSSH2_COMMON_METHOD **) libssh2_crypt_methods();
+        break;
+
+    case LIBSSH2_METHOD_CRYPT_SC:
+        prefvar = &session->remote.crypt_prefs;
+        mlist = (const LIBSSH2_COMMON_METHOD **) libssh2_crypt_methods();
+        break;
+
+    case LIBSSH2_METHOD_MAC_CS:
+        prefvar = &session->local.mac_prefs;
+        mlist = (const LIBSSH2_COMMON_METHOD **) _libssh2_mac_methods();
+        break;
+
+    case LIBSSH2_METHOD_MAC_SC:
+        prefvar = &session->remote.mac_prefs;
+        mlist = (const LIBSSH2_COMMON_METHOD **) _libssh2_mac_methods();
+        break;
+
+    case LIBSSH2_METHOD_COMP_CS:
+        prefvar = &session->local.comp_prefs;
+        mlist = (const LIBSSH2_COMMON_METHOD **)
+            _libssh2_comp_methods(session);
+        break;
+
+    case LIBSSH2_METHOD_COMP_SC:
+        prefvar = &session->remote.comp_prefs;
+        mlist = (const LIBSSH2_COMMON_METHOD **)
+            _libssh2_comp_methods(session);
+        break;
+
+    case LIBSSH2_METHOD_LANG_CS:
+        prefvar = &session->local.lang_prefs;
+        mlist = NULL;
+        break;
+
+    case LIBSSH2_METHOD_LANG_SC:
+        prefvar = &session->remote.lang_prefs;
+        mlist = NULL;
+        break;
+
+    default:
+        return _libssh2_error(session, LIBSSH2_ERROR_INVAL,
+                              "Invalid parameter specified for method_type");
+    }
+
+    s = newprefs = LIBSSH2_ALLOC(session, prefs_len + 1);
+    if(!newprefs) {
+        return _libssh2_error(session, LIBSSH2_ERROR_ALLOC,
+                              "Error allocated space for method preferences");
+    }
+    memcpy(s, prefs, prefs_len + 1);
+
+    while(s && *s && mlist) {
+        char *p = strchr(s, ',');
+        int method_len = p ? (p - s) : (int) strlen(s);
+
+        if(!kex_get_method_by_name(s, method_len, mlist)) {
+            /* Strip out unsupported method */
+            if(p) {
+                memcpy(s, p + 1, strlen(s) - method_len);
+            }
+            else {
+                if(s > newprefs) {
+                    *(--s) = '\0';
+                }
+                else {
+                    *s = '\0';
+                }
+            }
+        }
+        else {
+            s = p ? (p + 1) : NULL;
+        }
+    }
+
+    if(strlen(newprefs) == 0) {
+        LIBSSH2_FREE(session, newprefs);
+        return _libssh2_error(session, LIBSSH2_ERROR_METHOD_NOT_SUPPORTED,
+                              "The requested method(s) are not currently "
+                              "supported");
+    }
+
+    if(*prefvar) {
+        LIBSSH2_FREE(session, *prefvar);
+    }
+    *prefvar = newprefs;
+
+    return 0;
+}
+
+/*
+ * libssh2_session_supported_algs()
+ * returns a number of returned algorithms (a positive number) on success,
+ * a negative number on failure
+ */
+
+LIBSSH2_API int libssh2_session_supported_algs(LIBSSH2_SESSION* session,
+                                               int method_type,
+                                               const char ***algs)
+{
+    unsigned int i;
+    unsigned int j;
+    unsigned int ialg;
+    const LIBSSH2_COMMON_METHOD **mlist;
+
+    /* to prevent coredumps due to dereferencing of NULL */
+    if(NULL == algs)
+        return _libssh2_error(session, LIBSSH2_ERROR_BAD_USE,
+                              "algs must not be NULL");
+
+    switch(method_type) {
+    case LIBSSH2_METHOD_KEX:
+        mlist = (const LIBSSH2_COMMON_METHOD **) libssh2_kex_methods;
+        break;
+
+    case LIBSSH2_METHOD_HOSTKEY:
+        mlist = (const LIBSSH2_COMMON_METHOD **) libssh2_hostkey_methods();
+        break;
+
+    case LIBSSH2_METHOD_CRYPT_CS:
+    case LIBSSH2_METHOD_CRYPT_SC:
+        mlist = (const LIBSSH2_COMMON_METHOD **) libssh2_crypt_methods();
+        break;
+
+    case LIBSSH2_METHOD_MAC_CS:
+    case LIBSSH2_METHOD_MAC_SC:
+        mlist = (const LIBSSH2_COMMON_METHOD **) _libssh2_mac_methods();
+        break;
+
+    case LIBSSH2_METHOD_COMP_CS:
+    case LIBSSH2_METHOD_COMP_SC:
+        mlist = (const LIBSSH2_COMMON_METHOD **)
+            _libssh2_comp_methods(session);
+        break;
+
+    default:
+        return _libssh2_error(session, LIBSSH2_ERROR_METHOD_NOT_SUPPORTED,
+                              "Unknown method type");
+    }  /* switch */
+
+    /* weird situation */
+    if(NULL == mlist)
+        return _libssh2_error(session, LIBSSH2_ERROR_INVAL,
+                              "No algorithm found");
+
+    /*
+      mlist is looped through twice. The first time to find the number od
+      supported algorithms (needed to allocate the proper size of array) and
+      the second time to actually copy the pointers.  Typically this function
+      will not be called often (typically at the beginning of a session) and
+      the number of algorithms (i.e. niumber of iterations in one loop) will
+      not be high (typically it will not exceed 20) for quite a long time.
+
+      So double looping really shouldn't be an issue and it is definitely a
+      better solution than reallocation several times.
+    */
+
+    /* count the number of supported algorithms */
+    for(i = 0, ialg = 0; NULL != mlist[i]; i++) {
+        /* do not count fields with NULL name */
+        if(mlist[i]->name)
+            ialg++;
+    }
+
+    /* weird situation, no algorithm found */
+    if(0 == ialg)
+        return _libssh2_error(session, LIBSSH2_ERROR_INVAL,
+                              "No algorithm found");
+
+    /* allocate buffer */
+    *algs = (const char **) LIBSSH2_ALLOC(session, ialg*sizeof(const char *));
+    if(NULL == *algs) {
+        return _libssh2_error(session, LIBSSH2_ERROR_ALLOC,
+                              "Memory allocation failed");
+    }
+    /* Past this point *algs must be deallocated in case of an error!! */
+
+    /* copy non-NULL pointers only */
+    for(i = 0, j = 0; NULL != mlist[i] && j < ialg; i++) {
+        if(NULL == mlist[i]->name) {
+            /* maybe a weird situation but if it occurs, do not include NULL
+               pointers */
+            continue;
+        }
+
+        /* note that [] has higher priority than * (dereferencing) */
+        (*algs)[j++] = mlist[i]->name;
+    }
+
+    /* correct number of pointers copied? (test the code above) */
+    if(j != ialg) {
+        /* deallocate buffer */
+        LIBSSH2_FREE(session, (void *)*algs);
+        *algs = NULL;
+
+        return _libssh2_error(session, LIBSSH2_ERROR_BAD_USE,
+                              "Internal error");
+    }
+
+    return ialg;
+}

+ 1271 - 0
libssh2/libssh2/src/knownhost.c

@@ -0,0 +1,1271 @@
+/*
+ * Copyright (c) 2009-2019 by Daniel Stenberg
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms,
+ * with or without modification, are permitted provided
+ * that the following conditions are met:
+ *
+ *   Redistributions of source code must retain the above
+ *   copyright notice, this list of conditions and the
+ *   following disclaimer.
+ *
+ *   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.
+ *
+ *   Neither the name of the copyright holder nor the names
+ *   of any other contributors may be used to endorse or
+ *   promote products derived from this software without
+ *   specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+ * CONTRIBUTORS "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 COPYRIGHT OWNER OR
+ * CONTRIBUTORS 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 "libssh2_priv.h"
+#include "misc.h"
+
+struct known_host {
+    struct list_node node;
+    char *name;      /* points to the name or the hash (allocated) */
+    size_t name_len; /* needed for hashed data */
+    int port;        /* if non-zero, a specific port this key is for on this
+                        host */
+    int typemask;    /* plain, sha1, custom, ... */
+    char *salt;      /* points to binary salt (allocated) */
+    size_t salt_len; /* size of salt */
+    char *key;       /* the (allocated) associated key. This is kept base64
+                        encoded in memory. */
+    char *key_type_name; /* the (allocated) key type name */
+    size_t key_type_len; /* size of key_type_name */
+    char *comment;       /* the (allocated) optional comment text, may be
+                            NULL */
+    size_t comment_len;  /* the size of comment */
+
+    /* this is the struct we expose externally */
+    struct libssh2_knownhost external;
+};
+
+struct _LIBSSH2_KNOWNHOSTS
+{
+    LIBSSH2_SESSION *session;  /* the session this "belongs to" */
+    struct list_head head;
+};
+
+static void free_host(LIBSSH2_SESSION *session, struct known_host *entry)
+{
+    if(entry) {
+        if(entry->comment)
+            LIBSSH2_FREE(session, entry->comment);
+        if(entry->key_type_name)
+            LIBSSH2_FREE(session, entry->key_type_name);
+        if(entry->key)
+            LIBSSH2_FREE(session, entry->key);
+        if(entry->salt)
+            LIBSSH2_FREE(session, entry->salt);
+        if(entry->name)
+            LIBSSH2_FREE(session, entry->name);
+        LIBSSH2_FREE(session, entry);
+    }
+}
+
+/*
+ * libssh2_knownhost_init
+ *
+ * Init a collection of known hosts. Returns the pointer to a collection.
+ *
+ */
+LIBSSH2_API LIBSSH2_KNOWNHOSTS *
+libssh2_knownhost_init(LIBSSH2_SESSION *session)
+{
+    LIBSSH2_KNOWNHOSTS *knh =
+        LIBSSH2_ALLOC(session, sizeof(struct _LIBSSH2_KNOWNHOSTS));
+
+    if(!knh) {
+        _libssh2_error(session, LIBSSH2_ERROR_ALLOC,
+                       "Unable to allocate memory for known-hosts "
+                       "collection");
+        return NULL;
+    }
+
+    knh->session = session;
+
+    _libssh2_list_init(&knh->head);
+
+    return knh;
+}
+
+#define KNOWNHOST_MAGIC 0xdeadcafe
+/*
+ * knownhost_to_external()
+ *
+ * Copies data from the internal to the external representation struct.
+ *
+ */
+static struct libssh2_knownhost *knownhost_to_external(struct known_host *node)
+{
+    struct libssh2_knownhost *ext = &node->external;
+
+    ext->magic = KNOWNHOST_MAGIC;
+    ext->node = node;
+    ext->name = ((node->typemask & LIBSSH2_KNOWNHOST_TYPE_MASK) ==
+                 LIBSSH2_KNOWNHOST_TYPE_PLAIN)? node->name:NULL;
+    ext->key = node->key;
+    ext->typemask = node->typemask;
+
+    return ext;
+}
+
+static int
+knownhost_add(LIBSSH2_KNOWNHOSTS *hosts,
+              const char *host, const char *salt,
+              const char *key_type_name, size_t key_type_len,
+              const char *key, size_t keylen,
+              const char *comment, size_t commentlen,
+              int typemask, struct libssh2_knownhost **store)
+{
+    struct known_host *entry;
+    size_t hostlen = strlen(host);
+    int rc;
+    char *ptr;
+    unsigned int ptrlen;
+
+    /* make sure we have a key type set */
+    if(!(typemask & LIBSSH2_KNOWNHOST_KEY_MASK))
+        return _libssh2_error(hosts->session, LIBSSH2_ERROR_INVAL,
+                              "No key type set");
+
+    entry = LIBSSH2_CALLOC(hosts->session, sizeof(struct known_host));
+    if(!entry)
+        return _libssh2_error(hosts->session, LIBSSH2_ERROR_ALLOC,
+                              "Unable to allocate memory for known host "
+                              "entry");
+
+    entry->typemask = typemask;
+
+    switch(entry->typemask  & LIBSSH2_KNOWNHOST_TYPE_MASK) {
+    case LIBSSH2_KNOWNHOST_TYPE_PLAIN:
+    case LIBSSH2_KNOWNHOST_TYPE_CUSTOM:
+        entry->name = LIBSSH2_ALLOC(hosts->session, hostlen + 1);
+        if(!entry->name) {
+            rc = _libssh2_error(hosts->session, LIBSSH2_ERROR_ALLOC,
+                                "Unable to allocate memory for host name");
+            goto error;
+        }
+        memcpy(entry->name, host, hostlen + 1);
+        entry->name_len = hostlen;
+        break;
+    case LIBSSH2_KNOWNHOST_TYPE_SHA1:
+        rc = libssh2_base64_decode(hosts->session, &ptr, &ptrlen,
+                                   host, hostlen);
+        if(rc)
+            goto error;
+        entry->name = ptr;
+        entry->name_len = ptrlen;
+
+        rc = libssh2_base64_decode(hosts->session, &ptr, &ptrlen,
+                                   salt, strlen(salt));
+        if(rc)
+            goto error;
+        entry->salt = ptr;
+        entry->salt_len = ptrlen;
+        break;
+    default:
+        rc = _libssh2_error(hosts->session, LIBSSH2_ERROR_METHOD_NOT_SUPPORTED,
+                            "Unknown host name type");
+        goto error;
+    }
+
+    if(typemask & LIBSSH2_KNOWNHOST_KEYENC_BASE64) {
+        /* the provided key is base64 encoded already */
+        if(!keylen)
+            keylen = strlen(key);
+        entry->key = LIBSSH2_ALLOC(hosts->session, keylen + 1);
+        if(!entry->key) {
+            rc = _libssh2_error(hosts->session, LIBSSH2_ERROR_ALLOC,
+                                "Unable to allocate memory for key");
+            goto error;
+        }
+        memcpy(entry->key, key, keylen + 1);
+        entry->key[keylen] = 0; /* force a terminating zero trailer */
+    }
+    else {
+        /* key is raw, we base64 encode it and store it as such */
+        size_t nlen = _libssh2_base64_encode(hosts->session, key, keylen,
+                                             &ptr);
+        if(!nlen) {
+            rc = _libssh2_error(hosts->session, LIBSSH2_ERROR_ALLOC,
+                                "Unable to allocate memory for "
+                                "base64-encoded key");
+            goto error;
+        }
+
+        entry->key = ptr;
+    }
+
+    if(key_type_name && ((typemask & LIBSSH2_KNOWNHOST_KEY_MASK) ==
+                          LIBSSH2_KNOWNHOST_KEY_UNKNOWN)) {
+        entry->key_type_name = LIBSSH2_ALLOC(hosts->session, key_type_len + 1);
+        if(!entry->key_type_name) {
+            rc = _libssh2_error(hosts->session, LIBSSH2_ERROR_ALLOC,
+                                "Unable to allocate memory for key type");
+            goto error;
+        }
+        memcpy(entry->key_type_name, key_type_name, key_type_len);
+        entry->key_type_name[key_type_len] = 0;
+        entry->key_type_len = key_type_len;
+    }
+
+    if(comment) {
+        entry->comment = LIBSSH2_ALLOC(hosts->session, commentlen + 1);
+        if(!entry->comment) {
+            rc = _libssh2_error(hosts->session, LIBSSH2_ERROR_ALLOC,
+                                "Unable to allocate memory for comment");
+            goto error;
+        }
+        memcpy(entry->comment, comment, commentlen + 1);
+        entry->comment[commentlen] = 0; /* force a terminating zero trailer */
+        entry->comment_len = commentlen;
+    }
+    else {
+        entry->comment = NULL;
+    }
+
+    /* add this new host to the big list of known hosts */
+    _libssh2_list_add(&hosts->head, &entry->node);
+
+    if(store)
+        *store = knownhost_to_external(entry);
+
+    return LIBSSH2_ERROR_NONE;
+  error:
+    free_host(hosts->session, entry);
+    return rc;
+}
+
+/*
+ * libssh2_knownhost_add
+ *
+ * Add a host and its associated key to the collection of known hosts.
+ *
+ * The 'type' argument specifies on what format the given host and keys are:
+ *
+ * plain  - ascii "hostname.domain.tld"
+ * sha1   - SHA1(<salt> <host>) base64-encoded!
+ * custom - another hash
+ *
+ * If 'sha1' is selected as type, the salt must be provided to the salt
+ * argument. This too base64 encoded.
+ *
+ * The SHA-1 hash is what OpenSSH can be told to use in known_hosts files.  If
+ * a custom type is used, salt is ignored and you must provide the host
+ * pre-hashed when checking for it in the libssh2_knownhost_check() function.
+ *
+ * The keylen parameter may be omitted (zero) if the key is provided as a
+ * NULL-terminated base64-encoded string.
+ */
+
+LIBSSH2_API int
+libssh2_knownhost_add(LIBSSH2_KNOWNHOSTS *hosts,
+                      const char *host, const char *salt,
+                      const char *key, size_t keylen,
+                      int typemask, struct libssh2_knownhost **store)
+{
+    return knownhost_add(hosts, host, salt, NULL, 0, key, keylen, NULL,
+                         0, typemask, store);
+}
+
+
+/*
+ * libssh2_knownhost_addc
+ *
+ * Add a host and its associated key to the collection of known hosts.
+ *
+ * Takes a comment argument that may be NULL.  A NULL comment indicates
+ * there is no comment and the entry will end directly after the key
+ * when written out to a file.  An empty string "" comment will indicate an
+ * empty comment which will cause a single space to be written after the key.
+ *
+ * The 'type' argument specifies on what format the given host and keys are:
+ *
+ * plain  - ascii "hostname.domain.tld"
+ * sha1   - SHA1(<salt> <host>) base64-encoded!
+ * custom - another hash
+ *
+ * If 'sha1' is selected as type, the salt must be provided to the salt
+ * argument. This too base64 encoded.
+ *
+ * The SHA-1 hash is what OpenSSH can be told to use in known_hosts files.  If
+ * a custom type is used, salt is ignored and you must provide the host
+ * pre-hashed when checking for it in the libssh2_knownhost_check() function.
+ *
+ * The keylen parameter may be omitted (zero) if the key is provided as a
+ * NULL-terminated base64-encoded string.
+ */
+
+LIBSSH2_API int
+libssh2_knownhost_addc(LIBSSH2_KNOWNHOSTS *hosts,
+                       const char *host, const char *salt,
+                       const char *key, size_t keylen,
+                       const char *comment, size_t commentlen,
+                       int typemask, struct libssh2_knownhost **store)
+{
+    return knownhost_add(hosts, host, salt, NULL, 0, key, keylen,
+                         comment, commentlen, typemask, store);
+}
+
+/*
+ * knownhost_check
+ *
+ * Check a host and its associated key against the collection of known hosts.
+ *
+ * The typemask is the type/format of the given host name and key
+ *
+ * plain  - ascii "hostname.domain.tld"
+ * sha1   - NOT SUPPORTED AS INPUT
+ * custom - prehashed base64 encoded. Note that this cannot use any salts.
+ *
+ * Returns:
+ *
+ * LIBSSH2_KNOWNHOST_CHECK_FAILURE
+ * LIBSSH2_KNOWNHOST_CHECK_NOTFOUND
+ * LIBSSH2_KNOWNHOST_CHECK_MATCH
+ * LIBSSH2_KNOWNHOST_CHECK_MISMATCH
+ */
+static int
+knownhost_check(LIBSSH2_KNOWNHOSTS *hosts,
+                const char *hostp, int port,
+                const char *key, size_t keylen,
+                int typemask,
+                struct libssh2_knownhost **ext)
+{
+    struct known_host *node;
+    struct known_host *badkey = NULL;
+    int type = typemask & LIBSSH2_KNOWNHOST_TYPE_MASK;
+    char *keyalloc = NULL;
+    int rc = LIBSSH2_KNOWNHOST_CHECK_NOTFOUND;
+    char hostbuff[270]; /* most host names can't be longer than like 256 */
+    const char *host;
+    int numcheck; /* number of host combos to check */
+    int match = 0;
+
+    if(type == LIBSSH2_KNOWNHOST_TYPE_SHA1)
+        /* we can't work with a sha1 as given input */
+        return LIBSSH2_KNOWNHOST_CHECK_MISMATCH;
+
+    /* if a port number is given, check for a '[host]:port' first before the
+       plain 'host' */
+    if(port >= 0) {
+        int len = snprintf(hostbuff, sizeof(hostbuff), "[%s]:%d", hostp, port);
+        if(len < 0 || len >= (int)sizeof(hostbuff)) {
+            _libssh2_error(hosts->session,
+                           LIBSSH2_ERROR_BUFFER_TOO_SMALL,
+                           "Known-host write buffer too small");
+            return LIBSSH2_KNOWNHOST_CHECK_FAILURE;
+        }
+        host = hostbuff;
+        numcheck = 2; /* check both combos, start with this */
+    }
+    else {
+        host = hostp;
+        numcheck = 1; /* only check this host version */
+    }
+
+    if(!(typemask & LIBSSH2_KNOWNHOST_KEYENC_BASE64)) {
+        /* we got a raw key input, convert it to base64 for the checks below */
+        size_t nlen = _libssh2_base64_encode(hosts->session, key, keylen,
+                                             &keyalloc);
+        if(!nlen) {
+            _libssh2_error(hosts->session, LIBSSH2_ERROR_ALLOC,
+                           "Unable to allocate memory for base64-encoded "
+                           "key");
+            return LIBSSH2_KNOWNHOST_CHECK_FAILURE;
+        }
+
+        /* make the key point to this */
+        key = keyalloc;
+    }
+
+    do {
+        node = _libssh2_list_first(&hosts->head);
+        while(node) {
+            switch(node->typemask & LIBSSH2_KNOWNHOST_TYPE_MASK) {
+            case LIBSSH2_KNOWNHOST_TYPE_PLAIN:
+                if(type == LIBSSH2_KNOWNHOST_TYPE_PLAIN)
+                    match = !strcmp(host, node->name);
+                break;
+            case LIBSSH2_KNOWNHOST_TYPE_CUSTOM:
+                if(type == LIBSSH2_KNOWNHOST_TYPE_CUSTOM)
+                    match = !strcmp(host, node->name);
+                break;
+            case LIBSSH2_KNOWNHOST_TYPE_SHA1:
+                if(type == LIBSSH2_KNOWNHOST_TYPE_PLAIN) {
+                    /* when we have the sha1 version stored, we can use a
+                       plain input to produce a hash to compare with the
+                       stored hash.
+                    */
+                    unsigned char hash[SHA_DIGEST_LENGTH];
+                    libssh2_hmac_ctx ctx;
+                    libssh2_hmac_ctx_init(ctx);
+
+                    if(SHA_DIGEST_LENGTH != node->name_len) {
+                        /* the name hash length must be the sha1 size or
+                           we can't match it */
+                        break;
+                    }
+                    libssh2_hmac_sha1_init(&ctx, (unsigned char *)node->salt,
+                                           node->salt_len);
+                    libssh2_hmac_update(ctx, (unsigned char *)host,
+                                        strlen(host));
+                    libssh2_hmac_final(ctx, hash);
+                    libssh2_hmac_cleanup(&ctx);
+
+                    if(!memcmp(hash, node->name, SHA_DIGEST_LENGTH))
+                        /* this is a node we're interested in */
+                        match = 1;
+                }
+                break;
+            default: /* unsupported type */
+                break;
+            }
+            if(match) {
+                int host_key_type = typemask & LIBSSH2_KNOWNHOST_KEY_MASK;
+                int known_key_type =
+                    node->typemask & LIBSSH2_KNOWNHOST_KEY_MASK;
+                /* match on key type as follows:
+                   - never match on an unknown key type
+                   - if key_type is set to zero, ignore it an match always
+                   - otherwise match when both key types are equal
+                */
+                if(host_key_type != LIBSSH2_KNOWNHOST_KEY_UNKNOWN &&
+                     (host_key_type == 0 ||
+                      host_key_type == known_key_type)) {
+                    /* host name and key type match, now compare the keys */
+                    if(!strcmp(key, node->key)) {
+                        /* they match! */
+                        if(ext)
+                            *ext = knownhost_to_external(node);
+                        badkey = NULL;
+                        rc = LIBSSH2_KNOWNHOST_CHECK_MATCH;
+                        break;
+                    }
+                    else {
+                        /* remember the first node that had a host match but a
+                           failed key match since we continue our search from
+                           here */
+                        if(!badkey)
+                            badkey = node;
+                    }
+                }
+                match = 0; /* don't count this as a match anymore */
+            }
+            node = _libssh2_list_next(&node->node);
+        }
+        host = hostp;
+    } while(!match && --numcheck);
+
+    if(badkey) {
+        /* key mismatch */
+        if(ext)
+            *ext = knownhost_to_external(badkey);
+        rc = LIBSSH2_KNOWNHOST_CHECK_MISMATCH;
+    }
+
+    if(keyalloc)
+        LIBSSH2_FREE(hosts->session, keyalloc);
+
+    return rc;
+}
+
+/*
+ * libssh2_knownhost_check
+ *
+ * Check a host and its associated key against the collection of known hosts.
+ *
+ * The typemask is the type/format of the given host name and key
+ *
+ * plain  - ascii "hostname.domain.tld"
+ * sha1   - NOT SUPPORTED AS INPUT
+ * custom - prehashed base64 encoded. Note that this cannot use any salts.
+ *
+ * Returns:
+ *
+ * LIBSSH2_KNOWNHOST_CHECK_FAILURE
+ * LIBSSH2_KNOWNHOST_CHECK_NOTFOUND
+ * LIBSSH2_KNOWNHOST_CHECK_MATCH
+ * LIBSSH2_KNOWNHOST_CHECK_MISMATCH
+ */
+LIBSSH2_API int
+libssh2_knownhost_check(LIBSSH2_KNOWNHOSTS *hosts,
+                        const char *hostp, const char *key, size_t keylen,
+                        int typemask,
+                        struct libssh2_knownhost **ext)
+{
+    return knownhost_check(hosts, hostp, -1, key, keylen,
+                           typemask, ext);
+}
+
+/*
+ * libssh2_knownhost_checkp
+ *
+ * Check a host+port and its associated key against the collection of known
+ * hosts.
+ *
+ * Note that if 'port' is specified as greater than zero, the check function
+ * will be able to check for a dedicated key for this particular host+port
+ * combo, and if 'port' is negative it only checks for the generic host key.
+ *
+ * The typemask is the type/format of the given host name and key
+ *
+ * plain  - ascii "hostname.domain.tld"
+ * sha1   - NOT SUPPORTED AS INPUT
+ * custom - prehashed base64 encoded. Note that this cannot use any salts.
+ *
+ * Returns:
+ *
+ * LIBSSH2_KNOWNHOST_CHECK_FAILURE
+ * LIBSSH2_KNOWNHOST_CHECK_NOTFOUND
+ * LIBSSH2_KNOWNHOST_CHECK_MATCH
+ * LIBSSH2_KNOWNHOST_CHECK_MISMATCH
+ */
+LIBSSH2_API int
+libssh2_knownhost_checkp(LIBSSH2_KNOWNHOSTS *hosts,
+                         const char *hostp, int port,
+                         const char *key, size_t keylen,
+                         int typemask,
+                         struct libssh2_knownhost **ext)
+{
+    return knownhost_check(hosts, hostp, port, key, keylen,
+                           typemask, ext);
+}
+
+
+/*
+ * libssh2_knownhost_del
+ *
+ * Remove a host from the collection of known hosts.
+ *
+ */
+LIBSSH2_API int
+libssh2_knownhost_del(LIBSSH2_KNOWNHOSTS *hosts,
+                      struct libssh2_knownhost *entry)
+{
+    struct known_host *node;
+
+    /* check that this was retrieved the right way or get out */
+    if(!entry || (entry->magic != KNOWNHOST_MAGIC))
+        return _libssh2_error(hosts->session, LIBSSH2_ERROR_INVAL,
+                              "Invalid host information");
+
+    /* get the internal node pointer */
+    node = entry->node;
+
+    /* unlink from the list of all hosts */
+    _libssh2_list_remove(&node->node);
+
+    /* clear the struct now since the memory in which it is allocated is
+       about to be freed! */
+    memset(entry, 0, sizeof(struct libssh2_knownhost));
+
+    /* free all resources */
+    free_host(hosts->session, node);
+
+    return 0;
+}
+
+/*
+ * libssh2_knownhost_free
+ *
+ * Free an entire collection of known hosts.
+ *
+ */
+LIBSSH2_API void
+libssh2_knownhost_free(LIBSSH2_KNOWNHOSTS *hosts)
+{
+    struct known_host *node;
+    struct known_host *next;
+
+    for(node = _libssh2_list_first(&hosts->head); node; node = next) {
+        next = _libssh2_list_next(&node->node);
+        free_host(hosts->session, node);
+    }
+    LIBSSH2_FREE(hosts->session, hosts);
+}
+
+
+/* old style plain text: [name]([,][name])*
+
+   for the sake of simplicity, we add them as separate hosts with the same
+   key
+*/
+static int oldstyle_hostline(LIBSSH2_KNOWNHOSTS *hosts,
+                             const char *host, size_t hostlen,
+                             const char *key_type_name, size_t key_type_len,
+                             const char *key, size_t keylen, int key_type,
+                             const char *comment, size_t commentlen)
+{
+    int rc = 0;
+    size_t namelen = 0;
+    const char *name = host + hostlen;
+
+    if(hostlen < 1)
+        return _libssh2_error(hosts->session,
+                              LIBSSH2_ERROR_METHOD_NOT_SUPPORTED,
+                              "Failed to parse known_hosts line "
+                              "(no host names)");
+
+    while(name > host) {
+        --name;
+        ++namelen;
+
+        /* when we get the the start or see a comma coming up, add the host
+           name to the collection */
+        if((name == host) || (*(name-1) == ',')) {
+
+            char hostbuf[256];
+
+            /* make sure we don't overflow the buffer */
+            if(namelen >= sizeof(hostbuf)-1)
+                return _libssh2_error(hosts->session,
+                                      LIBSSH2_ERROR_METHOD_NOT_SUPPORTED,
+                                      "Failed to parse known_hosts line "
+                                      "(unexpected length)");
+
+            /* copy host name to the temp buffer and zero terminate */
+            memcpy(hostbuf, name, namelen);
+            hostbuf[namelen] = 0;
+
+            rc = knownhost_add(hosts, hostbuf, NULL,
+                               key_type_name, key_type_len,
+                               key, keylen,
+                               comment, commentlen,
+                               key_type | LIBSSH2_KNOWNHOST_TYPE_PLAIN |
+                               LIBSSH2_KNOWNHOST_KEYENC_BASE64, NULL);
+            if(rc)
+                return rc;
+
+            if(name > host) {
+                namelen = 0;
+                --name; /* skip comma */
+            }
+        }
+    }
+
+    return rc;
+}
+
+/* |1|[salt]|[hash] */
+static int hashed_hostline(LIBSSH2_KNOWNHOSTS *hosts,
+                           const char *host, size_t hostlen,
+                           const char *key_type_name, size_t key_type_len,
+                           const char *key, size_t keylen, int key_type,
+                           const char *comment, size_t commentlen)
+{
+    const char *p;
+    char saltbuf[32];
+    char hostbuf[256];
+
+    const char *salt = &host[3]; /* skip the magic marker */
+    hostlen -= 3;    /* deduct the marker */
+
+    /* this is where the salt starts, find the end of it */
+    for(p = salt; *p && (*p != '|'); p++)
+        ;
+
+    if(*p == '|') {
+        const char *hash = NULL;
+        size_t saltlen = p - salt;
+        if(saltlen >= (sizeof(saltbuf)-1)) /* weird length */
+            return _libssh2_error(hosts->session,
+                                  LIBSSH2_ERROR_METHOD_NOT_SUPPORTED,
+                                  "Failed to parse known_hosts line "
+                                  "(unexpectedly long salt)");
+
+        memcpy(saltbuf, salt, saltlen);
+        saltbuf[saltlen] = 0; /* zero terminate */
+        salt = saltbuf; /* point to the stack based buffer */
+
+        hash = p + 1; /* the host hash is after the separator */
+
+        /* now make the host point to the hash */
+        host = hash;
+        hostlen -= saltlen + 1; /* deduct the salt and separator */
+
+        /* check that the lengths seem sensible */
+        if(hostlen >= sizeof(hostbuf)-1)
+            return _libssh2_error(hosts->session,
+                                  LIBSSH2_ERROR_METHOD_NOT_SUPPORTED,
+                                  "Failed to parse known_hosts line "
+                                  "(unexpected length)");
+
+        memcpy(hostbuf, host, hostlen);
+        hostbuf[hostlen] = 0;
+
+        return knownhost_add(hosts, hostbuf, salt,
+                             key_type_name, key_type_len,
+                             key, keylen,
+                             comment, commentlen,
+                             key_type | LIBSSH2_KNOWNHOST_TYPE_SHA1 |
+                             LIBSSH2_KNOWNHOST_KEYENC_BASE64, NULL);
+    }
+    else
+        return 0; /* XXX: This should be an error, shouldn't it? */
+}
+
+/*
+ * hostline()
+ *
+ * Parse a single known_host line pre-split into host and key.
+ *
+ * The key part may include an optional comment which will be parsed here
+ * for ssh-rsa and ssh-dsa keys.  Comments in other key types aren't handled.
+ *
+ * The function assumes new-lines have already been removed from the arguments.
+ */
+static int hostline(LIBSSH2_KNOWNHOSTS *hosts,
+                    const char *host, size_t hostlen,
+                    const char *key, size_t keylen)
+{
+    const char *comment = NULL;
+    const char *key_type_name = NULL;
+    size_t commentlen = 0;
+    size_t key_type_len = 0;
+    int key_type;
+
+    /* make some checks that the lengths seem sensible */
+    if(keylen < 20)
+        return _libssh2_error(hosts->session,
+                              LIBSSH2_ERROR_METHOD_NOT_SUPPORTED,
+                              "Failed to parse known_hosts line "
+                              "(key too short)");
+
+    switch(key[0]) {
+    case '0': case '1': case '2': case '3': case '4':
+    case '5': case '6': case '7': case '8': case '9':
+        key_type = LIBSSH2_KNOWNHOST_KEY_RSA1;
+
+        /* Note that the old-style keys (RSA1) aren't truly base64, but we
+         * claim it is for now since we can get away with strcmp()ing the
+         * entire anything anyway! We need to check and fix these to make them
+         * work properly.
+         */
+        break;
+
+    default:
+        key_type_name = key;
+        while(keylen && *key &&
+               (*key != ' ') && (*key != '\t')) {
+            key++;
+            keylen--;
+        }
+        key_type_len = key - key_type_name;
+
+        if(!strncmp(key_type_name, "ssh-dss", key_type_len))
+            key_type = LIBSSH2_KNOWNHOST_KEY_SSHDSS;
+        else if(!strncmp(key_type_name, "ssh-rsa", key_type_len))
+            key_type = LIBSSH2_KNOWNHOST_KEY_SSHRSA;
+        else if(!strncmp(key_type_name, "ecdsa-sha2-nistp256", key_type_len))
+            key_type = LIBSSH2_KNOWNHOST_KEY_ECDSA_256;
+        else if(!strncmp(key_type_name, "ecdsa-sha2-nistp384", key_type_len))
+            key_type = LIBSSH2_KNOWNHOST_KEY_ECDSA_384;
+        else if(!strncmp(key_type_name, "ecdsa-sha2-nistp521", key_type_len))
+            key_type = LIBSSH2_KNOWNHOST_KEY_ECDSA_521;
+        else if(!strncmp(key_type_name, "ssh-ed25519", key_type_len))
+            key_type = LIBSSH2_KNOWNHOST_KEY_ED25519;
+        else
+            key_type = LIBSSH2_KNOWNHOST_KEY_UNKNOWN;
+
+        /* skip whitespaces */
+        while((*key ==' ') || (*key == '\t')) {
+            key++;
+            keylen--;
+        }
+
+        comment = key;
+        commentlen = keylen;
+
+        /* move over key */
+        while(commentlen && *comment &&
+              (*comment != ' ') && (*comment != '\t')) {
+            comment++;
+            commentlen--;
+        }
+
+        /* reduce key by comment length */
+        keylen -= commentlen;
+
+        /* Distinguish empty comment (a space) from no comment (no space) */
+        if(commentlen == 0)
+            comment = NULL;
+
+        /* skip whitespaces */
+        while(commentlen && *comment &&
+              ((*comment ==' ') || (*comment == '\t'))) {
+            comment++;
+            commentlen--;
+        }
+        break;
+    }
+
+    /* Figure out host format */
+    if((hostlen >2) && memcmp(host, "|1|", 3)) {
+        /* old style plain text: [name]([,][name])*
+
+           for the sake of simplicity, we add them as separate hosts with the
+           same key
+        */
+        return oldstyle_hostline(hosts, host, hostlen, key_type_name,
+                                 key_type_len, key, keylen, key_type,
+                                 comment, commentlen);
+    }
+    else {
+        /* |1|[salt]|[hash] */
+        return hashed_hostline(hosts, host, hostlen, key_type_name,
+                               key_type_len, key, keylen, key_type,
+                               comment, commentlen);
+    }
+}
+
+/*
+ * libssh2_knownhost_readline()
+ *
+ * Pass in a line of a file of 'type'.
+ *
+ * LIBSSH2_KNOWNHOST_FILE_OPENSSH is the only supported type.
+ *
+ * OpenSSH line format:
+ *
+ * <host> <key>
+ *
+ * Where the two parts can be created like:
+ *
+ * <host> can be either
+ * <name> or <hash>
+ *
+ * <name> consists of
+ * [name] optionally followed by [,name] one or more times
+ *
+ * <hash> consists of
+ * |1|<salt>|hash
+ *
+ * <key> can be one of:
+ * [RSA bits] [e] [n as a decimal number]
+ * 'ssh-dss' [base64-encoded-key]
+ * 'ssh-rsa' [base64-encoded-key]
+ *
+ */
+LIBSSH2_API int
+libssh2_knownhost_readline(LIBSSH2_KNOWNHOSTS *hosts,
+                           const char *line, size_t len, int type)
+{
+    const char *cp;
+    const char *hostp;
+    const char *keyp;
+    size_t hostlen;
+    size_t keylen;
+    int rc;
+
+    if(type != LIBSSH2_KNOWNHOST_FILE_OPENSSH)
+        return _libssh2_error(hosts->session,
+                              LIBSSH2_ERROR_METHOD_NOT_SUPPORTED,
+                              "Unsupported type of known-host information "
+                              "store");
+
+    cp = line;
+
+    /* skip leading whitespaces */
+    while(len && ((*cp == ' ') || (*cp == '\t'))) {
+        cp++;
+        len--;
+    }
+
+    if(!len || !*cp || (*cp == '#') || (*cp == '\n'))
+        /* comment or empty line */
+        return LIBSSH2_ERROR_NONE;
+
+    /* the host part starts here */
+    hostp = cp;
+
+    /* move over the host to the separator */
+    while(len && *cp && (*cp != ' ') && (*cp != '\t')) {
+        cp++;
+        len--;
+    }
+
+    hostlen = cp - hostp;
+
+    /* the key starts after the whitespaces */
+    while(len && *cp && ((*cp == ' ') || (*cp == '\t'))) {
+        cp++;
+        len--;
+    }
+
+    if(!*cp || !len) /* illegal line */
+        return _libssh2_error(hosts->session,
+                              LIBSSH2_ERROR_METHOD_NOT_SUPPORTED,
+                              "Failed to parse known_hosts line");
+
+    keyp = cp; /* the key starts here */
+    keylen = len;
+
+    /* check if the line (key) ends with a newline and if so kill it */
+    while(len && *cp && (*cp != '\n')) {
+        cp++;
+        len--;
+    }
+
+    /* zero terminate where the newline is */
+    if(*cp == '\n')
+        keylen--; /* don't include this in the count */
+
+    /* deal with this one host+key line */
+    rc = hostline(hosts, hostp, hostlen, keyp, keylen);
+    if(rc)
+        return rc; /* failed */
+
+    return LIBSSH2_ERROR_NONE; /* success */
+}
+
+/*
+ * libssh2_knownhost_readfile
+ *
+ * Read hosts+key pairs from a given file.
+ *
+ * Returns a negative value for error or number of successfully added hosts.
+ *
+ */
+
+LIBSSH2_API int
+libssh2_knownhost_readfile(LIBSSH2_KNOWNHOSTS *hosts,
+                           const char *filename, int type)
+{
+    FILE *file;
+    int num = 0;
+    char buf[2048];
+
+    if(type != LIBSSH2_KNOWNHOST_FILE_OPENSSH)
+        return _libssh2_error(hosts->session,
+                              LIBSSH2_ERROR_METHOD_NOT_SUPPORTED,
+                              "Unsupported type of known-host information "
+                              "store");
+
+    file = fopen(filename, FOPEN_READTEXT);
+    if(file) {
+        while(fgets(buf, sizeof(buf), file)) {
+            if(libssh2_knownhost_readline(hosts, buf, strlen(buf), type)) {
+                num = _libssh2_error(hosts->session, LIBSSH2_ERROR_KNOWN_HOSTS,
+                                     "Failed to parse known hosts file");
+                break;
+            }
+            num++;
+        }
+        fclose(file);
+    }
+    else
+        return _libssh2_error(hosts->session, LIBSSH2_ERROR_FILE,
+                              "Failed to open file");
+
+    return num;
+}
+
+/*
+ * knownhost_writeline()
+ *
+ * Ask libssh2 to convert a known host to an output line for storage.
+ *
+ * Note that this function returns LIBSSH2_ERROR_BUFFER_TOO_SMALL if the given
+ * output buffer is too small to hold the desired output. The 'outlen' field
+ * will then contain the size libssh2 wanted to store, which then is the
+ * smallest sufficient buffer it would require.
+ *
+ */
+static int
+knownhost_writeline(LIBSSH2_KNOWNHOSTS *hosts,
+                    struct known_host *node,
+                    char *buf, size_t buflen,
+                    size_t *outlen, int type)
+{
+    size_t required_size;
+
+    const char *key_type_name;
+    size_t key_type_len;
+
+    /* we only support this single file type for now, bail out on all other
+       attempts */
+    if(type != LIBSSH2_KNOWNHOST_FILE_OPENSSH)
+        return _libssh2_error(hosts->session,
+                              LIBSSH2_ERROR_METHOD_NOT_SUPPORTED,
+                              "Unsupported type of known-host information "
+                              "store");
+
+    switch(node->typemask & LIBSSH2_KNOWNHOST_KEY_MASK) {
+    case LIBSSH2_KNOWNHOST_KEY_RSA1:
+        key_type_name = NULL;
+        key_type_len = 0;
+        break;
+    case LIBSSH2_KNOWNHOST_KEY_SSHRSA:
+        key_type_name = "ssh-rsa";
+        key_type_len = 7;
+        break;
+    case LIBSSH2_KNOWNHOST_KEY_SSHDSS:
+        key_type_name = "ssh-dss";
+        key_type_len = 7;
+        break;
+    case LIBSSH2_KNOWNHOST_KEY_ECDSA_256:
+        key_type_name = "ecdsa-sha2-nistp256";
+        key_type_len = 19;
+        break;
+    case LIBSSH2_KNOWNHOST_KEY_ECDSA_384:
+        key_type_name = "ecdsa-sha2-nistp384";
+        key_type_len = 19;
+        break;
+    case LIBSSH2_KNOWNHOST_KEY_ECDSA_521:
+        key_type_name = "ecdsa-sha2-nistp521";
+        key_type_len = 19;
+        break;
+    case LIBSSH2_KNOWNHOST_KEY_ED25519:
+        key_type_name = "ssh-ed25519";
+        key_type_len = 11;
+        break;
+    case LIBSSH2_KNOWNHOST_KEY_UNKNOWN:
+        key_type_name = node->key_type_name;
+        if(key_type_name) {
+            key_type_len = node->key_type_len;
+            break;
+        }
+        /* otherwise fallback to default and error */
+        /* FALL-THROUGH */
+    default:
+        return _libssh2_error(hosts->session,
+                              LIBSSH2_ERROR_METHOD_NOT_SUPPORTED,
+                              "Unsupported type of known-host entry");
+    }
+
+    /* When putting together the host line there are three aspects to consider:
+       - Hashed (SHA1) or unhashed hostname
+       - key name or no key name (RSA1)
+       - comment or no comment
+
+       This means there are 2^3 different formats:
+       ("|1|%s|%s %s %s %s\n", salt, hashed_host, key_name, key, comment)
+       ("|1|%s|%s %s %s\n", salt, hashed_host, key_name, key)
+       ("|1|%s|%s %s %s\n", salt, hashed_host, key, comment)
+       ("|1|%s|%s %s\n", salt, hashed_host, key)
+       ("%s %s %s %s\n", host, key_name, key, comment)
+       ("%s %s %s\n", host, key_name, key)
+       ("%s %s %s\n", host, key, comment)
+       ("%s %s\n", host, key)
+
+       Even if the buffer is too small, we have to set outlen to the number of
+       characters the complete line would have taken.  We also don't write
+       anything to the buffer unless we are sure we can write everything to the
+       buffer. */
+
+    required_size = strlen(node->key);
+
+    if(key_type_len)
+        required_size += key_type_len + 1; /* ' ' = 1 */
+    if(node->comment)
+        required_size += node->comment_len + 1; /* ' ' = 1 */
+
+    if((node->typemask & LIBSSH2_KNOWNHOST_TYPE_MASK) ==
+       LIBSSH2_KNOWNHOST_TYPE_SHA1) {
+        char *namealloc;
+        size_t name_base64_len;
+        char *saltalloc;
+        size_t salt_base64_len;
+
+        name_base64_len = _libssh2_base64_encode(hosts->session, node->name,
+                                                 node->name_len, &namealloc);
+        if(!name_base64_len)
+            return _libssh2_error(hosts->session, LIBSSH2_ERROR_ALLOC,
+                                  "Unable to allocate memory for "
+                                  "base64-encoded host name");
+
+        salt_base64_len = _libssh2_base64_encode(hosts->session,
+                                                 node->salt, node->salt_len,
+                                                 &saltalloc);
+        if(!salt_base64_len) {
+            LIBSSH2_FREE(hosts->session, namealloc);
+            return _libssh2_error(hosts->session, LIBSSH2_ERROR_ALLOC,
+                                  "Unable to allocate memory for "
+                                  "base64-encoded salt");
+        }
+
+        required_size += salt_base64_len + name_base64_len + 7;
+        /* |1| + | + ' ' + \n + \0 = 7 */
+
+        if(required_size <= buflen) {
+            if(node->comment && key_type_len)
+                snprintf(buf, buflen, "|1|%s|%s %s %s %s\n", saltalloc,
+                         namealloc, key_type_name, node->key, node->comment);
+            else if(node->comment)
+                snprintf(buf, buflen, "|1|%s|%s %s %s\n", saltalloc, namealloc,
+                         node->key, node->comment);
+            else if(key_type_len)
+                snprintf(buf, buflen, "|1|%s|%s %s %s\n", saltalloc, namealloc,
+                         key_type_name, node->key);
+            else
+                snprintf(buf, buflen, "|1|%s|%s %s\n", saltalloc, namealloc,
+                         node->key);
+        }
+
+        LIBSSH2_FREE(hosts->session, namealloc);
+        LIBSSH2_FREE(hosts->session, saltalloc);
+    }
+    else {
+        required_size += node->name_len + 3;
+        /* ' ' + '\n' + \0 = 3 */
+
+        if(required_size <= buflen) {
+            if(node->comment && key_type_len)
+                snprintf(buf, buflen, "%s %s %s %s\n", node->name,
+                         key_type_name, node->key, node->comment);
+            else if(node->comment)
+                snprintf(buf, buflen, "%s %s %s\n", node->name, node->key,
+                         node->comment);
+            else if(key_type_len)
+                snprintf(buf, buflen, "%s %s %s\n", node->name, key_type_name,
+                         node->key);
+            else
+                snprintf(buf, buflen, "%s %s\n", node->name, node->key);
+        }
+    }
+
+    /* we report the full length of the data with the trailing zero excluded */
+    *outlen = required_size-1;
+
+    if(required_size <= buflen)
+        return LIBSSH2_ERROR_NONE;
+    else
+        return _libssh2_error(hosts->session, LIBSSH2_ERROR_BUFFER_TOO_SMALL,
+                              "Known-host write buffer too small");
+}
+
+/*
+ * libssh2_knownhost_writeline()
+ *
+ * Ask libssh2 to convert a known host to an output line for storage.
+ *
+ * Note that this function returns LIBSSH2_ERROR_BUFFER_TOO_SMALL if the given
+ * output buffer is too small to hold the desired output.
+ */
+LIBSSH2_API int
+libssh2_knownhost_writeline(LIBSSH2_KNOWNHOSTS *hosts,
+                            struct libssh2_knownhost *known,
+                            char *buffer, size_t buflen,
+                            size_t *outlen, /* the amount of written data */
+                            int type)
+{
+    struct known_host *node;
+
+    if(known->magic != KNOWNHOST_MAGIC)
+        return _libssh2_error(hosts->session, LIBSSH2_ERROR_INVAL,
+                              "Invalid host information");
+
+    node = known->node;
+
+    return knownhost_writeline(hosts, node, buffer, buflen, outlen, type);
+}
+
+/*
+ * libssh2_knownhost_writefile()
+ *
+ * Write hosts+key pairs to the given file.
+ */
+LIBSSH2_API int
+libssh2_knownhost_writefile(LIBSSH2_KNOWNHOSTS *hosts,
+                            const char *filename, int type)
+{
+    struct known_host *node;
+    FILE *file;
+    int rc = LIBSSH2_ERROR_NONE;
+    char buffer[2048];
+
+    /* we only support this single file type for now, bail out on all other
+       attempts */
+    if(type != LIBSSH2_KNOWNHOST_FILE_OPENSSH)
+        return _libssh2_error(hosts->session,
+                              LIBSSH2_ERROR_METHOD_NOT_SUPPORTED,
+                              "Unsupported type of known-host information "
+                              "store");
+
+    file = fopen(filename, FOPEN_WRITETEXT);
+    if(!file)
+        return _libssh2_error(hosts->session, LIBSSH2_ERROR_FILE,
+                              "Failed to open file");
+
+    for(node = _libssh2_list_first(&hosts->head);
+        node;
+        node = _libssh2_list_next(&node->node)) {
+        size_t wrote = 0;
+        size_t nwrote;
+        rc = knownhost_writeline(hosts, node, buffer, sizeof(buffer), &wrote,
+                                 type);
+        if(rc)
+            break;
+
+        nwrote = fwrite(buffer, 1, wrote, file);
+        if(nwrote != wrote) {
+            /* failed to write the whole thing, bail out */
+            rc = _libssh2_error(hosts->session, LIBSSH2_ERROR_FILE,
+                                "Write failed");
+            break;
+        }
+    }
+    fclose(file);
+
+    return rc;
+}
+
+
+/*
+ * libssh2_knownhost_get()
+ *
+ * Traverse the internal list of known hosts. Pass NULL to 'prev' to get
+ * the first one.
+ *
+ * Returns:
+ * 0 if a fine host was stored in 'store'
+ * 1 if end of hosts
+ * [negative] on errors
+ */
+LIBSSH2_API int
+libssh2_knownhost_get(LIBSSH2_KNOWNHOSTS *hosts,
+                      struct libssh2_knownhost **ext,
+                      struct libssh2_knownhost *oprev)
+{
+    struct known_host *node;
+    if(oprev && oprev->node) {
+        /* we have a starting point */
+        struct known_host *prev = oprev->node;
+
+        /* get the next node in the list */
+        node = _libssh2_list_next(&prev->node);
+
+    }
+    else
+        node = _libssh2_list_first(&hosts->head);
+
+    if(!node)
+        /* no (more) node */
+        return 1;
+
+    *ext = knownhost_to_external(node);
+
+    return 0;
+}

+ 667 - 0
libssh2/libssh2/src/libgcrypt.c

@@ -0,0 +1,667 @@
+/* Copyright (C) 2008, 2009, Simon Josefsson
+ * Copyright (C) 2006, 2007, The Written Word, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms,
+ * with or without modification, are permitted provided
+ * that the following conditions are met:
+ *
+ *   Redistributions of source code must retain the above
+ *   copyright notice, this list of conditions and the
+ *   following disclaimer.
+ *
+ *   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.
+ *
+ *   Neither the name of the copyright holder nor the names
+ *   of any other contributors may be used to endorse or
+ *   promote products derived from this software without
+ *   specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+ * CONTRIBUTORS "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 COPYRIGHT OWNER OR
+ * CONTRIBUTORS 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 "libssh2_priv.h"
+
+#ifdef LIBSSH2_LIBGCRYPT /* compile only if we build with libgcrypt */
+
+#include <string.h>
+
+int
+_libssh2_rsa_new(libssh2_rsa_ctx ** rsa,
+                 const unsigned char *edata,
+                 unsigned long elen,
+                 const unsigned char *ndata,
+                 unsigned long nlen,
+                 const unsigned char *ddata,
+                 unsigned long dlen,
+                 const unsigned char *pdata,
+                 unsigned long plen,
+                 const unsigned char *qdata,
+                 unsigned long qlen,
+                 const unsigned char *e1data,
+                 unsigned long e1len,
+                 const unsigned char *e2data,
+                 unsigned long e2len,
+                 const unsigned char *coeffdata, unsigned long coefflen)
+{
+    int rc;
+    (void) e1data;
+    (void) e1len;
+    (void) e2data;
+    (void) e2len;
+
+    if(ddata) {
+        rc = gcry_sexp_build
+            (rsa, NULL,
+             "(private-key(rsa(n%b)(e%b)(d%b)(q%b)(p%b)(u%b)))",
+             nlen, ndata, elen, edata, dlen, ddata, plen, pdata,
+             qlen, qdata, coefflen, coeffdata);
+    }
+    else {
+        rc = gcry_sexp_build(rsa, NULL, "(public-key(rsa(n%b)(e%b)))",
+                             nlen, ndata, elen, edata);
+    }
+    if(rc) {
+        *rsa = NULL;
+        return -1;
+    }
+
+    return 0;
+}
+
+int
+_libssh2_rsa_sha1_verify(libssh2_rsa_ctx * rsa,
+                         const unsigned char *sig,
+                         unsigned long sig_len,
+                         const unsigned char *m, unsigned long m_len)
+{
+    unsigned char hash[SHA_DIGEST_LENGTH];
+    gcry_sexp_t s_sig, s_hash;
+    int rc = -1;
+
+    libssh2_sha1(m, m_len, hash);
+
+    rc = gcry_sexp_build(&s_hash, NULL,
+                         "(data (flags pkcs1) (hash sha1 %b))",
+                         SHA_DIGEST_LENGTH, hash);
+    if(rc != 0) {
+        return -1;
+    }
+
+    rc = gcry_sexp_build(&s_sig, NULL, "(sig-val(rsa(s %b)))", sig_len, sig);
+    if(rc != 0) {
+        gcry_sexp_release(s_hash);
+        return -1;
+    }
+
+    rc = gcry_pk_verify(s_sig, s_hash, rsa);
+    gcry_sexp_release(s_sig);
+    gcry_sexp_release(s_hash);
+
+    return (rc == 0) ? 0 : -1;
+}
+
+int
+_libssh2_dsa_new(libssh2_dsa_ctx ** dsactx,
+                 const unsigned char *p,
+                 unsigned long p_len,
+                 const unsigned char *q,
+                 unsigned long q_len,
+                 const unsigned char *g,
+                 unsigned long g_len,
+                 const unsigned char *y,
+                 unsigned long y_len,
+                 const unsigned char *x, unsigned long x_len)
+{
+    int rc;
+
+    if(x_len) {
+        rc = gcry_sexp_build
+            (dsactx, NULL,
+             "(private-key(dsa(p%b)(q%b)(g%b)(y%b)(x%b)))",
+             p_len, p, q_len, q, g_len, g, y_len, y, x_len, x);
+    }
+    else {
+        rc = gcry_sexp_build(dsactx, NULL,
+                             "(public-key(dsa(p%b)(q%b)(g%b)(y%b)))",
+                             p_len, p, q_len, q, g_len, g, y_len, y);
+    }
+
+    if(rc) {
+        *dsactx = NULL;
+        return -1;
+    }
+
+    return 0;
+}
+
+int
+_libssh2_rsa_new_private_frommemory(libssh2_rsa_ctx ** rsa,
+                                    LIBSSH2_SESSION * session,
+                                    const char *filedata, size_t filedata_len,
+                                    unsigned const char *passphrase)
+{
+    return _libssh2_error(session, LIBSSH2_ERROR_METHOD_NOT_SUPPORTED,
+                         "Unable to extract private key from memory: "
+                         "Method unimplemented in libgcrypt backend");
+}
+
+int
+_libssh2_rsa_new_private(libssh2_rsa_ctx ** rsa,
+                         LIBSSH2_SESSION * session,
+                         const char *filename, unsigned const char *passphrase)
+{
+    FILE *fp;
+    unsigned char *data, *save_data;
+    unsigned int datalen;
+    int ret;
+    unsigned char *n, *e, *d, *p, *q, *e1, *e2, *coeff;
+    unsigned int nlen, elen, dlen, plen, qlen, e1len, e2len, coefflen;
+
+    fp = fopen(filename, FOPEN_READTEXT);
+    if(!fp) {
+        return -1;
+    }
+
+    ret = _libssh2_pem_parse(session,
+                             "-----BEGIN RSA PRIVATE KEY-----",
+                             "-----END RSA PRIVATE KEY-----",
+                             passphrase,
+                             fp, &data, &datalen);
+    fclose(fp);
+    if(ret) {
+        return -1;
+    }
+
+    save_data = data;
+
+    if(_libssh2_pem_decode_sequence(&data, &datalen)) {
+        ret = -1;
+        goto fail;
+    }
+/* First read Version field (should be 0). */
+    ret = _libssh2_pem_decode_integer(&data, &datalen, &n, &nlen);
+    if(ret != 0 || (nlen != 1 && *n != '\0')) {
+        ret = -1;
+        goto fail;
+    }
+
+    ret = _libssh2_pem_decode_integer(&data, &datalen, &n, &nlen);
+    if(ret != 0) {
+        ret = -1;
+        goto fail;
+    }
+
+    ret = _libssh2_pem_decode_integer(&data, &datalen, &e, &elen);
+    if(ret != 0) {
+        ret = -1;
+        goto fail;
+    }
+
+    ret = _libssh2_pem_decode_integer(&data, &datalen, &d, &dlen);
+    if(ret != 0) {
+        ret = -1;
+        goto fail;
+    }
+
+    ret = _libssh2_pem_decode_integer(&data, &datalen, &p, &plen);
+    if(ret != 0) {
+        ret = -1;
+        goto fail;
+    }
+
+    ret = _libssh2_pem_decode_integer(&data, &datalen, &q, &qlen);
+    if(ret != 0) {
+        ret = -1;
+        goto fail;
+    }
+
+    ret = _libssh2_pem_decode_integer(&data, &datalen, &e1, &e1len);
+    if(ret != 0) {
+        ret = -1;
+        goto fail;
+    }
+
+    ret = _libssh2_pem_decode_integer(&data, &datalen, &e2, &e2len);
+    if(ret != 0) {
+        ret = -1;
+        goto fail;
+    }
+
+    ret = _libssh2_pem_decode_integer(&data, &datalen, &coeff, &coefflen);
+    if(ret != 0) {
+        ret = -1;
+        goto fail;
+    }
+
+    if(_libssh2_rsa_new(rsa, e, elen, n, nlen, d, dlen, p, plen,
+                         q, qlen, e1, e1len, e2, e2len, coeff, coefflen)) {
+        ret = -1;
+        goto fail;
+    }
+
+    ret = 0;
+
+  fail:
+    LIBSSH2_FREE(session, save_data);
+    return ret;
+}
+
+int
+_libssh2_dsa_new_private_frommemory(libssh2_dsa_ctx ** dsa,
+                                    LIBSSH2_SESSION * session,
+                                    const char *filedata, size_t filedata_len,
+                                    unsigned const char *passphrase)
+{
+    return _libssh2_error(session, LIBSSH2_ERROR_METHOD_NOT_SUPPORTED,
+                         "Unable to extract private key from memory: "
+                         "Method unimplemented in libgcrypt backend");
+}
+
+int
+_libssh2_dsa_new_private(libssh2_dsa_ctx ** dsa,
+                         LIBSSH2_SESSION * session,
+                         const char *filename, unsigned const char *passphrase)
+{
+    FILE *fp;
+    unsigned char *data, *save_data;
+    unsigned int datalen;
+    int ret;
+    unsigned char *p, *q, *g, *y, *x;
+    unsigned int plen, qlen, glen, ylen, xlen;
+
+    fp = fopen(filename, FOPEN_READTEXT);
+    if(!fp) {
+        return -1;
+    }
+
+    ret = _libssh2_pem_parse(session,
+                             "-----BEGIN DSA PRIVATE KEY-----",
+                             "-----END DSA PRIVATE KEY-----",
+                             passphrase,
+                             fp, &data, &datalen);
+    fclose(fp);
+    if(ret) {
+        return -1;
+    }
+
+    save_data = data;
+
+    if(_libssh2_pem_decode_sequence(&data, &datalen)) {
+        ret = -1;
+        goto fail;
+    }
+
+/* First read Version field (should be 0). */
+    ret = _libssh2_pem_decode_integer(&data, &datalen, &p, &plen);
+    if(ret != 0 || (plen != 1 && *p != '\0')) {
+        ret = -1;
+        goto fail;
+    }
+
+    ret = _libssh2_pem_decode_integer(&data, &datalen, &p, &plen);
+    if(ret != 0) {
+        ret = -1;
+        goto fail;
+    }
+
+    ret = _libssh2_pem_decode_integer(&data, &datalen, &q, &qlen);
+    if(ret != 0) {
+        ret = -1;
+        goto fail;
+    }
+
+    ret = _libssh2_pem_decode_integer(&data, &datalen, &g, &glen);
+    if(ret != 0) {
+        ret = -1;
+        goto fail;
+    }
+
+    ret = _libssh2_pem_decode_integer(&data, &datalen, &y, &ylen);
+    if(ret != 0) {
+        ret = -1;
+        goto fail;
+    }
+
+    ret = _libssh2_pem_decode_integer(&data, &datalen, &x, &xlen);
+    if(ret != 0) {
+        ret = -1;
+        goto fail;
+    }
+
+    if(datalen != 0) {
+        ret = -1;
+        goto fail;
+    }
+
+    if(_libssh2_dsa_new(dsa, p, plen, q, qlen, g, glen, y, ylen, x, xlen)) {
+        ret = -1;
+        goto fail;
+    }
+
+    ret = 0;
+
+  fail:
+    LIBSSH2_FREE(session, save_data);
+    return ret;
+}
+
+int
+_libssh2_rsa_sha1_sign(LIBSSH2_SESSION * session,
+                       libssh2_rsa_ctx * rsactx,
+                       const unsigned char *hash,
+                       size_t hash_len,
+                       unsigned char **signature, size_t *signature_len)
+{
+    gcry_sexp_t sig_sexp;
+    gcry_sexp_t data;
+    int rc;
+    const char *tmp;
+    size_t size;
+
+    if(hash_len != SHA_DIGEST_LENGTH) {
+        return -1;
+    }
+
+    if(gcry_sexp_build(&data, NULL,
+                        "(data (flags pkcs1) (hash sha1 %b))",
+                        hash_len, hash)) {
+        return -1;
+    }
+
+    rc = gcry_pk_sign(&sig_sexp, data, rsactx);
+
+    gcry_sexp_release(data);
+
+    if(rc != 0) {
+        return -1;
+    }
+
+    data = gcry_sexp_find_token(sig_sexp, "s", 0);
+    if(!data) {
+        return -1;
+    }
+
+    tmp = gcry_sexp_nth_data(data, 1, &size);
+    if(!tmp) {
+        gcry_sexp_release(data);
+        return -1;
+    }
+
+    if(tmp[0] == '\0') {
+        tmp++;
+        size--;
+    }
+
+    *signature = LIBSSH2_ALLOC(session, size);
+    if(!*signature) {
+        gcry_sexp_release(data);
+        return -1;
+    }
+    memcpy(*signature, tmp, size);
+    *signature_len = size;
+
+    gcry_sexp_release(data);
+
+    return rc;
+}
+
+int
+_libssh2_dsa_sha1_sign(libssh2_dsa_ctx * dsactx,
+                       const unsigned char *hash,
+                       unsigned long hash_len, unsigned char *sig)
+{
+    unsigned char zhash[SHA_DIGEST_LENGTH + 1];
+    gcry_sexp_t sig_sexp;
+    gcry_sexp_t data;
+    int ret;
+    const char *tmp;
+    size_t size;
+
+    if(hash_len != SHA_DIGEST_LENGTH) {
+        return -1;
+    }
+
+    memcpy(zhash + 1, hash, hash_len);
+    zhash[0] = 0;
+
+    if(gcry_sexp_build(&data, NULL, "(data (value %b))",
+                       hash_len + 1, zhash)) {
+        return -1;
+    }
+
+    ret = gcry_pk_sign(&sig_sexp, data, dsactx);
+
+    gcry_sexp_release(data);
+
+    if(ret != 0) {
+        return -1;
+    }
+
+    memset(sig, 0, 40);
+
+/* Extract R. */
+
+    data = gcry_sexp_find_token(sig_sexp, "r", 0);
+    if(!data)
+        goto err;
+
+    tmp = gcry_sexp_nth_data(data, 1, &size);
+    if(!tmp)
+        goto err;
+
+    if(tmp[0] == '\0') {
+        tmp++;
+        size--;
+    }
+
+    if(size < 1 || size > 20)
+        goto err;
+
+    memcpy(sig + (20 - size), tmp, size);
+
+    gcry_sexp_release(data);
+
+/* Extract S. */
+
+    data = gcry_sexp_find_token(sig_sexp, "s", 0);
+    if(!data)
+        goto err;
+
+    tmp = gcry_sexp_nth_data(data, 1, &size);
+    if(!tmp)
+        goto err;
+
+    if(tmp[0] == '\0') {
+        tmp++;
+        size--;
+    }
+
+    if(size < 1 || size > 20)
+        goto err;
+
+    memcpy(sig + 20 + (20 - size), tmp, size);
+    goto out;
+
+  err:
+    ret = -1;
+
+  out:
+    if(sig_sexp) {
+        gcry_sexp_release(sig_sexp);
+    }
+    if(data) {
+        gcry_sexp_release(data);
+    }
+    return ret;
+}
+
+int
+_libssh2_dsa_sha1_verify(libssh2_dsa_ctx * dsactx,
+                         const unsigned char *sig,
+                         const unsigned char *m, unsigned long m_len)
+{
+    unsigned char hash[SHA_DIGEST_LENGTH + 1];
+    gcry_sexp_t s_sig, s_hash;
+    int rc = -1;
+
+    libssh2_sha1(m, m_len, hash + 1);
+    hash[0] = 0;
+
+    if(gcry_sexp_build(&s_hash, NULL, "(data(flags raw)(value %b))",
+                        SHA_DIGEST_LENGTH + 1, hash)) {
+        return -1;
+    }
+
+    if(gcry_sexp_build(&s_sig, NULL, "(sig-val(dsa(r %b)(s %b)))",
+                        20, sig, 20, sig + 20)) {
+        gcry_sexp_release(s_hash);
+        return -1;
+    }
+
+    rc = gcry_pk_verify(s_sig, s_hash, dsactx);
+    gcry_sexp_release(s_sig);
+    gcry_sexp_release(s_hash);
+
+    return (rc == 0) ? 0 : -1;
+}
+
+int
+_libssh2_cipher_init(_libssh2_cipher_ctx * h,
+                     _libssh2_cipher_type(algo),
+                     unsigned char *iv, unsigned char *secret, int encrypt)
+{
+    int ret;
+    int cipher = _libssh2_gcry_cipher(algo);
+    int mode = _libssh2_gcry_mode(algo);
+    int keylen = gcry_cipher_get_algo_keylen(cipher);
+
+    (void) encrypt;
+
+    ret = gcry_cipher_open(h, cipher, mode, 0);
+    if(ret) {
+        return -1;
+    }
+
+    ret = gcry_cipher_setkey(*h, secret, keylen);
+    if(ret) {
+        gcry_cipher_close(*h);
+        return -1;
+    }
+
+    if(mode != GCRY_CIPHER_MODE_STREAM) {
+        int blklen = gcry_cipher_get_algo_blklen(cipher);
+        if(mode == GCRY_CIPHER_MODE_CTR)
+            ret = gcry_cipher_setctr(*h, iv, blklen);
+        else
+            ret = gcry_cipher_setiv(*h, iv, blklen);
+        if(ret) {
+            gcry_cipher_close(*h);
+            return -1;
+        }
+    }
+
+    return 0;
+}
+
+int
+_libssh2_cipher_crypt(_libssh2_cipher_ctx * ctx,
+                      _libssh2_cipher_type(algo),
+                      int encrypt, unsigned char *block, size_t blklen)
+{
+    int cipher = _libssh2_gcry_cipher(algo);
+    int ret;
+
+    if(encrypt) {
+        ret = gcry_cipher_encrypt(*ctx, block, blklen, block, blklen);
+    }
+    else {
+        ret = gcry_cipher_decrypt(*ctx, block, blklen, block, blklen);
+    }
+    return ret;
+}
+
+int
+_libssh2_pub_priv_keyfilememory(LIBSSH2_SESSION *session,
+                                unsigned char **method,
+                                size_t *method_len,
+                                unsigned char **pubkeydata,
+                                size_t *pubkeydata_len,
+                                const char *privatekeydata,
+                                size_t privatekeydata_len,
+                                const char *passphrase)
+{
+    return _libssh2_error(session, LIBSSH2_ERROR_METHOD_NOT_SUPPORTED,
+                          "Unable to extract public key from private "
+                          "key in memory: "
+                          "Method unimplemented in libgcrypt backend");
+}
+
+int
+_libssh2_pub_priv_keyfile(LIBSSH2_SESSION *session,
+                          unsigned char **method,
+                          size_t *method_len,
+                          unsigned char **pubkeydata,
+                          size_t *pubkeydata_len,
+                          const char *privatekey,
+                          const char *passphrase)
+{
+    return _libssh2_error(session, LIBSSH2_ERROR_FILE,
+                         "Unable to extract public key from private key file: "
+                         "Method unimplemented in libgcrypt backend");
+}
+
+void _libssh2_init_aes_ctr(void)
+{
+    /* no implementation */
+}
+
+void
+_libssh2_dh_init(_libssh2_dh_ctx *dhctx)
+{
+    *dhctx = gcry_mpi_new(0);                   /* Random from client */
+}
+
+int
+_libssh2_dh_key_pair(_libssh2_dh_ctx *dhctx, _libssh2_bn *public,
+                     _libssh2_bn *g, _libssh2_bn *p, int group_order)
+{
+    /* Generate x and e */
+    gcry_mpi_randomize(*dhctx, group_order * 8 - 1, GCRY_WEAK_RANDOM);
+    gcry_mpi_powm(public, g, *dhctx, p);
+    return 0;
+}
+
+int
+_libssh2_dh_secret(_libssh2_dh_ctx *dhctx, _libssh2_bn *secret,
+                   _libssh2_bn *f, _libssh2_bn *p)
+{
+    /* Compute the shared secret */
+    gcry_mpi_powm(secret, f, *dhctx, p);
+    return 0;
+}
+
+void
+_libssh2_dh_dtor(_libssh2_dh_ctx *dhctx)
+{
+    gcry_mpi_release(*dhctx);
+    *dhctx = NULL;
+}
+
+#endif /* LIBSSH2_LIBGCRYPT */

+ 234 - 0
libssh2/libssh2/src/libgcrypt.h

@@ -0,0 +1,234 @@
+/*
+ * Copyright (C) 2008, 2009, 2010 Simon Josefsson
+ * Copyright (C) 2006, 2007, The Written Word, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms,
+ * with or without modification, are permitted provided
+ * that the following conditions are met:
+ *
+ *   Redistributions of source code must retain the above
+ *   copyright notice, this list of conditions and the
+ *   following disclaimer.
+ *
+ *   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.
+ *
+ *   Neither the name of the copyright holder nor the names
+ *   of any other contributors may be used to endorse or
+ *   promote products derived from this software without
+ *   specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+ * CONTRIBUTORS "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 COPYRIGHT OWNER OR
+ * CONTRIBUTORS 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 <gcrypt.h>
+
+#define LIBSSH2_MD5 1
+
+#define LIBSSH2_HMAC_RIPEMD 1
+#define LIBSSH2_HMAC_SHA256 1
+#define LIBSSH2_HMAC_SHA512 1
+
+#define LIBSSH2_AES 1
+#define LIBSSH2_AES_CTR 1
+#define LIBSSH2_BLOWFISH 1
+#define LIBSSH2_RC4 1
+#define LIBSSH2_CAST 1
+#define LIBSSH2_3DES 1
+
+#define LIBSSH2_RSA 1
+#define LIBSSH2_DSA 1
+#define LIBSSH2_ECDSA 0
+#define LIBSSH2_ED25519 0
+
+#define MD5_DIGEST_LENGTH 16
+#define SHA_DIGEST_LENGTH 20
+#define SHA256_DIGEST_LENGTH 32
+#define SHA384_DIGEST_LENGTH 48
+#define SHA512_DIGEST_LENGTH 64
+
+#define EC_MAX_POINT_LEN ((528 * 2 / 8) + 1)
+
+#define _libssh2_random(buf, len)                \
+  (gcry_randomize ((buf), (len), GCRY_STRONG_RANDOM), 1)
+
+#define libssh2_prepare_iovec(vec, len)  /* Empty. */
+
+#define libssh2_sha1_ctx gcry_md_hd_t
+
+/* returns 0 in case of failure */
+#define libssh2_sha1_init(ctx) \
+  (GPG_ERR_NO_ERROR == gcry_md_open(ctx,  GCRY_MD_SHA1, 0))
+#define libssh2_sha1_update(ctx, data, len) \
+  gcry_md_write(ctx, (unsigned char *) data, len)
+#define libssh2_sha1_final(ctx, out) \
+  memcpy(out, gcry_md_read(ctx, 0), SHA_DIGEST_LENGTH), gcry_md_close(ctx)
+#define libssh2_sha1(message, len, out) \
+  gcry_md_hash_buffer(GCRY_MD_SHA1, out, message, len)
+
+#define libssh2_sha256_ctx gcry_md_hd_t
+
+#define libssh2_sha256_init(ctx) \
+  (GPG_ERR_NO_ERROR == gcry_md_open(ctx,  GCRY_MD_SHA256, 0))
+#define libssh2_sha256_update(ctx, data, len) \
+  gcry_md_write(ctx, (unsigned char *) data, len)
+#define libssh2_sha256_final(ctx, out) \
+  memcpy(out, gcry_md_read(ctx, 0), SHA256_DIGEST_LENGTH), gcry_md_close(ctx)
+#define libssh2_sha256(message, len, out) \
+  gcry_md_hash_buffer(GCRY_MD_SHA256, out, message, len)
+
+#define libssh2_sha384_ctx gcry_md_hd_t
+
+#define libssh2_sha384_init(ctx) \
+  (GPG_ERR_NO_ERROR == gcry_md_open(ctx,  GCRY_MD_SHA384, 0))
+#define libssh2_sha384_update(ctx, data, len) \
+  gcry_md_write(ctx, (unsigned char *) data, len)
+#define libssh2_sha384_final(ctx, out) \
+  memcpy(out, gcry_md_read(ctx, 0), SHA384_DIGEST_LENGTH), gcry_md_close(ctx)
+#define libssh2_sha384(message, len, out) \
+  gcry_md_hash_buffer(GCRY_MD_SHA384, out, message, len)
+
+#define libssh2_sha512_ctx gcry_md_hd_t
+
+#define libssh2_sha512_init(ctx) \
+  (GPG_ERR_NO_ERROR == gcry_md_open(ctx,  GCRY_MD_SHA512, 0))
+#define libssh2_sha512_update(ctx, data, len) \
+  gcry_md_write(ctx, (unsigned char *) data, len)
+#define libssh2_sha512_final(ctx, out) \
+  memcpy(out, gcry_md_read(ctx, 0), SHA512_DIGEST_LENGTH), gcry_md_close(ctx)
+#define libssh2_sha512(message, len, out) \
+  gcry_md_hash_buffer(GCRY_MD_SHA512, out, message, len)
+
+#define libssh2_md5_ctx gcry_md_hd_t
+
+/* returns 0 in case of failure */
+#define libssh2_md5_init(ctx) \
+  (GPG_ERR_NO_ERROR == gcry_md_open(ctx,  GCRY_MD_MD5, 0))
+
+#define libssh2_md5_update(ctx, data, len) \
+  gcry_md_write(ctx, (unsigned char *) data, len)
+#define libssh2_md5_final(ctx, out) \
+  memcpy(out, gcry_md_read(ctx, 0), MD5_DIGEST_LENGTH), gcry_md_close(ctx)
+#define libssh2_md5(message, len, out) \
+  gcry_md_hash_buffer(GCRY_MD_MD5, out, message, len)
+
+#define libssh2_hmac_ctx gcry_md_hd_t
+#define libssh2_hmac_ctx_init(ctx)
+#define libssh2_hmac_sha1_init(ctx, key, keylen) \
+  gcry_md_open(ctx, GCRY_MD_SHA1, GCRY_MD_FLAG_HMAC), \
+    gcry_md_setkey(*ctx, key, keylen)
+#define libssh2_hmac_md5_init(ctx, key, keylen) \
+  gcry_md_open(ctx, GCRY_MD_MD5, GCRY_MD_FLAG_HMAC), \
+    gcry_md_setkey(*ctx, key, keylen)
+#define libssh2_hmac_ripemd160_init(ctx, key, keylen) \
+  gcry_md_open(ctx, GCRY_MD_RMD160, GCRY_MD_FLAG_HMAC), \
+    gcry_md_setkey(*ctx, key, keylen)
+#define libssh2_hmac_sha256_init(ctx, key, keylen) \
+  gcry_md_open(ctx, GCRY_MD_SHA256, GCRY_MD_FLAG_HMAC), \
+    gcry_md_setkey(*ctx, key, keylen)
+#define libssh2_hmac_sha512_init(ctx, key, keylen) \
+  gcry_md_open(ctx, GCRY_MD_SHA512, GCRY_MD_FLAG_HMAC), \
+    gcry_md_setkey(*ctx, key, keylen)
+#define libssh2_hmac_update(ctx, data, datalen) \
+  gcry_md_write(ctx, (unsigned char *) data, datalen)
+#define libssh2_hmac_final(ctx, data) \
+  memcpy(data, gcry_md_read(ctx, 0), \
+      gcry_md_get_algo_dlen(gcry_md_get_algo(ctx)))
+#define libssh2_hmac_cleanup(ctx) gcry_md_close (*ctx);
+
+#define libssh2_crypto_init() gcry_control (GCRYCTL_DISABLE_SECMEM)
+#define libssh2_crypto_exit()
+
+#define libssh2_rsa_ctx struct gcry_sexp
+
+#define _libssh2_rsa_free(rsactx)  gcry_sexp_release (rsactx)
+
+#define libssh2_dsa_ctx struct gcry_sexp
+
+#define _libssh2_dsa_free(dsactx)  gcry_sexp_release (dsactx)
+
+#if LIBSSH2_ECDSA
+#else
+#define _libssh2_ec_key void
+#endif
+
+#define _libssh2_cipher_type(name) int name
+#define _libssh2_cipher_ctx gcry_cipher_hd_t
+
+#define _libssh2_gcry_ciphermode(c,m) ((c << 8) | m)
+#define _libssh2_gcry_cipher(c) (c >> 8)
+#define _libssh2_gcry_mode(m) (m & 0xFF)
+
+#define _libssh2_cipher_aes256ctr \
+  _libssh2_gcry_ciphermode(GCRY_CIPHER_AES256, GCRY_CIPHER_MODE_CTR)
+#define _libssh2_cipher_aes192ctr \
+  _libssh2_gcry_ciphermode(GCRY_CIPHER_AES192, GCRY_CIPHER_MODE_CTR)
+#define _libssh2_cipher_aes128ctr \
+  _libssh2_gcry_ciphermode(GCRY_CIPHER_AES128, GCRY_CIPHER_MODE_CTR)
+#define _libssh2_cipher_aes256 \
+  _libssh2_gcry_ciphermode(GCRY_CIPHER_AES256, GCRY_CIPHER_MODE_CBC)
+#define _libssh2_cipher_aes192 \
+  _libssh2_gcry_ciphermode(GCRY_CIPHER_AES192, GCRY_CIPHER_MODE_CBC)
+#define _libssh2_cipher_aes128 \
+  _libssh2_gcry_ciphermode(GCRY_CIPHER_AES128, GCRY_CIPHER_MODE_CBC)
+#define _libssh2_cipher_blowfish \
+  _libssh2_gcry_ciphermode(GCRY_CIPHER_BLOWFISH, GCRY_CIPHER_MODE_CBC)
+#define _libssh2_cipher_arcfour \
+  _libssh2_gcry_ciphermode(GCRY_CIPHER_ARCFOUR, GCRY_CIPHER_MODE_STREAM)
+#define _libssh2_cipher_cast5 \
+  _libssh2_gcry_ciphermode(GCRY_CIPHER_CAST5, GCRY_CIPHER_MODE_CBC)
+#define _libssh2_cipher_3des \
+  _libssh2_gcry_ciphermode(GCRY_CIPHER_3DES, GCRY_CIPHER_MODE_CBC)
+
+
+#define _libssh2_cipher_dtor(ctx) gcry_cipher_close(*(ctx))
+
+#define _libssh2_bn struct gcry_mpi
+#define _libssh2_bn_ctx int
+#define _libssh2_bn_ctx_new() 0
+#define _libssh2_bn_ctx_free(bnctx) ((void)0)
+#define _libssh2_bn_init() gcry_mpi_new(0)
+#define _libssh2_bn_init_from_bin() NULL /* because gcry_mpi_scan() creates a
+                                            new bignum */
+#define _libssh2_bn_set_word(bn, val) gcry_mpi_set_ui(bn, val)
+#define _libssh2_bn_from_bin(bn, len, val)                      \
+    gcry_mpi_scan(&((bn)), GCRYMPI_FMT_USG, val, len, NULL)
+#define _libssh2_bn_to_bin(bn, val)                                     \
+    gcry_mpi_print(GCRYMPI_FMT_USG, val, _libssh2_bn_bytes(bn), NULL, bn)
+#define _libssh2_bn_bytes(bn)                                           \
+    (gcry_mpi_get_nbits (bn) / 8 +                                      \
+     ((gcry_mpi_get_nbits (bn) % 8 == 0) ? 0 : 1))
+#define _libssh2_bn_bits(bn) gcry_mpi_get_nbits (bn)
+#define _libssh2_bn_free(bn) gcry_mpi_release(bn)
+
+#define _libssh2_dh_ctx struct gcry_mpi *
+#define libssh2_dh_init(dhctx) _libssh2_dh_init(dhctx)
+#define libssh2_dh_key_pair(dhctx, public, g, p, group_order, bnctx) \
+        _libssh2_dh_key_pair(dhctx, public, g, p, group_order)
+#define libssh2_dh_secret(dhctx, secret, f, p, bnctx) \
+        _libssh2_dh_secret(dhctx, secret, f, p)
+#define libssh2_dh_dtor(dhctx) _libssh2_dh_dtor(dhctx)
+extern void _libssh2_dh_init(_libssh2_dh_ctx *dhctx);
+extern int _libssh2_dh_key_pair(_libssh2_dh_ctx *dhctx, _libssh2_bn *public,
+                                _libssh2_bn *g, _libssh2_bn *p,
+                                int group_order);
+extern int _libssh2_dh_secret(_libssh2_dh_ctx *dhctx, _libssh2_bn *secret,
+                              _libssh2_bn *f, _libssh2_bn *p);
+extern void _libssh2_dh_dtor(_libssh2_dh_ctx *dhctx);
+

+ 1143 - 0
libssh2/libssh2/src/libssh2_priv.h

@@ -0,0 +1,1143 @@
+/* Copyright (c) 2004-2008, 2010, Sara Golemon <sarag@libssh2.org>
+ * Copyright (c) 2009-2014 by Daniel Stenberg
+ * Copyright (c) 2010 Simon Josefsson
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms,
+ * with or without modification, are permitted provided
+ * that the following conditions are met:
+ *
+ *   Redistributions of source code must retain the above
+ *   copyright notice, this list of conditions and the
+ *   following disclaimer.
+ *
+ *   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.
+ *
+ *   Neither the name of the copyright holder nor the names
+ *   of any other contributors may be used to endorse or
+ *   promote products derived from this software without
+ *   specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+ * CONTRIBUTORS "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 COPYRIGHT OWNER OR
+ * CONTRIBUTORS 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 LIBSSH2_PRIV_H
+#define LIBSSH2_PRIV_H 1
+
+#define LIBSSH2_LIBRARY
+#include "libssh2_config.h"
+
+#ifdef HAVE_WINDOWS_H
+#ifndef WIN32_LEAN_AND_MEAN
+#define WIN32_LEAN_AND_MEAN
+#endif
+#include <windows.h>
+#undef WIN32_LEAN_AND_MEAN
+#endif
+
+#ifdef HAVE_WS2TCPIP_H
+#include <ws2tcpip.h>
+#endif
+
+#include <stdio.h>
+#include <time.h>
+
+/* The following CPP block should really only be in session.c and packet.c.
+   However, AIX have #define's for 'events' and 'revents' and we are using
+   those names in libssh2.h, so we need to include the AIX headers first, to
+   make sure all code is compiled with consistent names of these fields.
+   While arguable the best would to change libssh2.h to use other names, that
+   would break backwards compatibility.
+*/
+#ifdef HAVE_POLL
+# include <poll.h>
+#else
+# if defined(HAVE_SELECT) && !defined(WIN32)
+# ifdef HAVE_SYS_SELECT_H
+# include <sys/select.h>
+# else
+# include <sys/time.h>
+# include <sys/types.h>
+# endif
+# endif
+#endif
+
+/* Needed for struct iovec on some platforms */
+#ifdef HAVE_SYS_UIO_H
+#include <sys/uio.h>
+#endif
+
+#ifdef HAVE_SYS_SOCKET_H
+# include <sys/socket.h>
+#endif
+#ifdef HAVE_SYS_IOCTL_H
+# include <sys/ioctl.h>
+#endif
+#ifdef HAVE_INTTYPES_H
+#include <inttypes.h>
+#endif
+
+#include "libssh2.h"
+#include "libssh2_publickey.h"
+#include "libssh2_sftp.h"
+#include "misc.h" /* for the linked list stuff */
+
+#ifndef FALSE
+#define FALSE 0
+#endif
+#ifndef TRUE
+#define TRUE 1
+#endif
+
+#ifdef _MSC_VER
+/* "inline" keyword is valid only with C++ engine! */
+#define inline __inline
+#endif
+
+/* Provide iovec / writev on WIN32 platform. */
+#ifdef WIN32
+
+struct iovec {
+    size_t iov_len;
+    void *iov_base;
+};
+
+static inline int writev(int sock, struct iovec *iov, int nvecs)
+{
+    DWORD ret;
+    if(WSASend(sock, (LPWSABUF)iov, nvecs, &ret, 0, NULL, NULL) == 0) {
+        return ret;
+    }
+    return -1;
+}
+
+#endif /* WIN32 */
+
+#ifdef __OS400__
+/* Force parameter type. */
+#define send(s, b, l, f)    send((s), (unsigned char *) (b), (l), (f))
+#endif
+
+#include "crypto.h"
+
+#ifdef HAVE_WINSOCK2_H
+
+#include <winsock2.h>
+#include <ws2tcpip.h>
+
+#endif
+
+#ifndef SIZE_MAX
+#if _WIN64
+#define SIZE_MAX 0xFFFFFFFFFFFFFFFF
+#else
+#define SIZE_MAX 0xFFFFFFFF
+#endif
+#endif
+
+#ifndef UINT_MAX
+#define UINT_MAX 0xFFFFFFFF
+#endif
+
+/* RFC4253 section 6.1 Maximum Packet Length says:
+ *
+ * "All implementations MUST be able to process packets with
+ * uncompressed payload length of 32768 bytes or less and
+ * total packet size of 35000 bytes or less (including length,
+ * padding length, payload, padding, and MAC.)."
+ */
+#define MAX_SSH_PACKET_LEN 35000
+#define MAX_SHA_DIGEST_LEN SHA512_DIGEST_LENGTH
+
+#define LIBSSH2_ALLOC(session, count) \
+  session->alloc((count), &(session)->abstract)
+#define LIBSSH2_CALLOC(session, count) _libssh2_calloc(session, count)
+#define LIBSSH2_REALLOC(session, ptr, count) \
+ ((ptr) ? session->realloc((ptr), (count), &(session)->abstract) : \
+ session->alloc((count), &(session)->abstract))
+#define LIBSSH2_FREE(session, ptr) \
+ session->free((ptr), &(session)->abstract)
+#define LIBSSH2_IGNORE(session, data, datalen) \
+ session->ssh_msg_ignore((session), (data), (datalen), &(session)->abstract)
+#define LIBSSH2_DEBUG(session, always_display, message, message_len, \
+                      language, language_len)    \
+    session->ssh_msg_debug((session), (always_display), (message), \
+                           (message_len), (language), (language_len), \
+                           &(session)->abstract)
+#define LIBSSH2_DISCONNECT(session, reason, message, message_len, \
+                           language, language_len)                \
+    session->ssh_msg_disconnect((session), (reason), (message),   \
+                                (message_len), (language), (language_len), \
+                                &(session)->abstract)
+
+#define LIBSSH2_MACERROR(session, data, datalen)         \
+    session->macerror((session), (data), (datalen), &(session)->abstract)
+#define LIBSSH2_X11_OPEN(channel, shost, sport)          \
+    channel->session->x11(((channel)->session), (channel), \
+                          (shost), (sport), (&(channel)->session->abstract))
+
+#define LIBSSH2_CHANNEL_CLOSE(session, channel)          \
+    channel->close_cb((session), &(session)->abstract, \
+                      (channel), &(channel)->abstract)
+
+#define LIBSSH2_SEND_FD(session, fd, buffer, length, flags) \
+    (session->send)(fd, buffer, length, flags, &session->abstract)
+#define LIBSSH2_RECV_FD(session, fd, buffer, length, flags) \
+    (session->recv)(fd, buffer, length, flags, &session->abstract)
+
+#define LIBSSH2_SEND(session, buffer, length, flags)  \
+    LIBSSH2_SEND_FD(session, session->socket_fd, buffer, length, flags)
+#define LIBSSH2_RECV(session, buffer, length, flags)                    \
+    LIBSSH2_RECV_FD(session, session->socket_fd, buffer, length, flags)
+
+typedef struct _LIBSSH2_KEX_METHOD LIBSSH2_KEX_METHOD;
+typedef struct _LIBSSH2_HOSTKEY_METHOD LIBSSH2_HOSTKEY_METHOD;
+typedef struct _LIBSSH2_CRYPT_METHOD LIBSSH2_CRYPT_METHOD;
+typedef struct _LIBSSH2_COMP_METHOD LIBSSH2_COMP_METHOD;
+
+typedef struct _LIBSSH2_PACKET LIBSSH2_PACKET;
+
+typedef enum
+{
+    libssh2_NB_state_idle = 0,
+    libssh2_NB_state_allocated,
+    libssh2_NB_state_created,
+    libssh2_NB_state_sent,
+    libssh2_NB_state_sent1,
+    libssh2_NB_state_sent2,
+    libssh2_NB_state_sent3,
+    libssh2_NB_state_sent4,
+    libssh2_NB_state_sent5,
+    libssh2_NB_state_sent6,
+    libssh2_NB_state_sent7,
+    libssh2_NB_state_jump1,
+    libssh2_NB_state_jump2,
+    libssh2_NB_state_jump3,
+    libssh2_NB_state_jump4,
+    libssh2_NB_state_jump5,
+    libssh2_NB_state_end
+} libssh2_nonblocking_states;
+
+typedef struct packet_require_state_t
+{
+    libssh2_nonblocking_states state;
+    time_t start;
+} packet_require_state_t;
+
+typedef struct packet_requirev_state_t
+{
+    time_t start;
+} packet_requirev_state_t;
+
+typedef struct kmdhgGPshakex_state_t
+{
+    libssh2_nonblocking_states state;
+    unsigned char *e_packet;
+    unsigned char *s_packet;
+    unsigned char *tmp;
+    unsigned char h_sig_comp[MAX_SHA_DIGEST_LEN];
+    unsigned char c;
+    size_t e_packet_len;
+    size_t s_packet_len;
+    size_t tmp_len;
+    _libssh2_bn_ctx *ctx;
+    _libssh2_dh_ctx x;
+    _libssh2_bn *e;
+    _libssh2_bn *f;
+    _libssh2_bn *k;
+    unsigned char *f_value;
+    unsigned char *k_value;
+    unsigned char *h_sig;
+    size_t f_value_len;
+    size_t k_value_len;
+    size_t h_sig_len;
+    void *exchange_hash;
+    packet_require_state_t req_state;
+    libssh2_nonblocking_states burn_state;
+} kmdhgGPshakex_state_t;
+
+typedef struct key_exchange_state_low_t
+{
+    libssh2_nonblocking_states state;
+    packet_require_state_t req_state;
+    kmdhgGPshakex_state_t exchange_state;
+    _libssh2_bn *p;             /* SSH2 defined value (p_value) */
+    _libssh2_bn *g;             /* SSH2 defined value (2) */
+    unsigned char request[256]; /* Must fit EC_MAX_POINT_LEN + data */
+    unsigned char *data;
+    size_t request_len;
+    size_t data_len;
+    _libssh2_ec_key *private_key;   /* SSH2 ecdh private key */
+    unsigned char *public_key_oct;  /* SSH2 ecdh public key octal value */
+    size_t public_key_oct_len;      /* SSH2 ecdh public key octal value
+                                       length */
+    unsigned char *curve25519_public_key; /* curve25519 public key, 32
+                                             bytes */
+    unsigned char *curve25519_private_key; /* curve25519 private key, 32
+                                              bytes */
+} key_exchange_state_low_t;
+
+typedef struct key_exchange_state_t
+{
+    libssh2_nonblocking_states state;
+    packet_require_state_t req_state;
+    key_exchange_state_low_t key_state_low;
+    unsigned char *data;
+    size_t data_len;
+    unsigned char *oldlocal;
+    size_t oldlocal_len;
+} key_exchange_state_t;
+
+#define FwdNotReq "Forward not requested"
+
+typedef struct packet_queue_listener_state_t
+{
+    libssh2_nonblocking_states state;
+    unsigned char packet[17 + (sizeof(FwdNotReq) - 1)];
+    unsigned char *host;
+    unsigned char *shost;
+    uint32_t sender_channel;
+    uint32_t initial_window_size;
+    uint32_t packet_size;
+    uint32_t port;
+    uint32_t sport;
+    uint32_t host_len;
+    uint32_t shost_len;
+    LIBSSH2_CHANNEL *channel;
+} packet_queue_listener_state_t;
+
+#define X11FwdUnAvil "X11 Forward Unavailable"
+
+typedef struct packet_x11_open_state_t
+{
+    libssh2_nonblocking_states state;
+    unsigned char packet[17 + (sizeof(X11FwdUnAvil) - 1)];
+    unsigned char *shost;
+    uint32_t sender_channel;
+    uint32_t initial_window_size;
+    uint32_t packet_size;
+    uint32_t sport;
+    uint32_t shost_len;
+    LIBSSH2_CHANNEL *channel;
+} packet_x11_open_state_t;
+
+struct _LIBSSH2_PACKET
+{
+    struct list_node node; /* linked list header */
+
+    /* the raw unencrypted payload */
+    unsigned char *data;
+    size_t data_len;
+
+    /* Where to start reading data from,
+     * used for channel data that's been partially consumed */
+    size_t data_head;
+};
+
+typedef struct _libssh2_channel_data
+{
+    /* Identifier */
+    uint32_t id;
+
+    /* Limits and restrictions */
+    uint32_t window_size_initial, window_size, packet_size;
+
+    /* Set to 1 when CHANNEL_CLOSE / CHANNEL_EOF sent/received */
+    char close, eof, extended_data_ignore_mode;
+} libssh2_channel_data;
+
+struct _LIBSSH2_CHANNEL
+{
+    struct list_node node;
+
+    unsigned char *channel_type;
+    unsigned channel_type_len;
+
+    /* channel's program exit status */
+    int exit_status;
+
+    /* channel's program exit signal (without the SIG prefix) */
+    char *exit_signal;
+
+    libssh2_channel_data local, remote;
+    /* Amount of bytes to be refunded to receive window (but not yet sent) */
+    uint32_t adjust_queue;
+    /* Data immediately available for reading */
+    uint32_t read_avail;
+
+    LIBSSH2_SESSION *session;
+
+    void *abstract;
+      LIBSSH2_CHANNEL_CLOSE_FUNC((*close_cb));
+
+    /* State variables used in libssh2_channel_setenv_ex() */
+    libssh2_nonblocking_states setenv_state;
+    unsigned char *setenv_packet;
+    size_t setenv_packet_len;
+    unsigned char setenv_local_channel[4];
+    packet_requirev_state_t setenv_packet_requirev_state;
+
+    /* State variables used in libssh2_channel_request_pty_ex()
+       libssh2_channel_request_pty_size_ex() */
+    libssh2_nonblocking_states reqPTY_state;
+    unsigned char reqPTY_packet[41 + 256];
+    size_t reqPTY_packet_len;
+    unsigned char reqPTY_local_channel[4];
+    packet_requirev_state_t reqPTY_packet_requirev_state;
+
+    /* State variables used in libssh2_channel_x11_req_ex() */
+    libssh2_nonblocking_states reqX11_state;
+    unsigned char *reqX11_packet;
+    size_t reqX11_packet_len;
+    unsigned char reqX11_local_channel[4];
+    packet_requirev_state_t reqX11_packet_requirev_state;
+
+    /* State variables used in libssh2_channel_process_startup() */
+    libssh2_nonblocking_states process_state;
+    unsigned char *process_packet;
+    size_t process_packet_len;
+    unsigned char process_local_channel[4];
+    packet_requirev_state_t process_packet_requirev_state;
+
+    /* State variables used in libssh2_channel_flush_ex() */
+    libssh2_nonblocking_states flush_state;
+    size_t flush_refund_bytes;
+    size_t flush_flush_bytes;
+
+    /* State variables used in libssh2_channel_receive_window_adjust() */
+    libssh2_nonblocking_states adjust_state;
+    unsigned char adjust_adjust[9];     /* packet_type(1) + channel(4) +
+                                           adjustment(4) */
+
+    /* State variables used in libssh2_channel_read_ex() */
+    libssh2_nonblocking_states read_state;
+
+    uint32_t read_local_id;
+
+    /* State variables used in libssh2_channel_write_ex() */
+    libssh2_nonblocking_states write_state;
+    unsigned char write_packet[13];
+    size_t write_packet_len;
+    size_t write_bufwrite;
+
+    /* State variables used in libssh2_channel_close() */
+    libssh2_nonblocking_states close_state;
+    unsigned char close_packet[5];
+
+    /* State variables used in libssh2_channel_wait_closedeof() */
+    libssh2_nonblocking_states wait_eof_state;
+
+    /* State variables used in libssh2_channel_wait_closed() */
+    libssh2_nonblocking_states wait_closed_state;
+
+    /* State variables used in libssh2_channel_free() */
+    libssh2_nonblocking_states free_state;
+
+    /* State variables used in libssh2_channel_handle_extended_data2() */
+    libssh2_nonblocking_states extData2_state;
+
+};
+
+struct _LIBSSH2_LISTENER
+{
+    struct list_node node; /* linked list header */
+
+    LIBSSH2_SESSION *session;
+
+    char *host;
+    int port;
+
+    /* a list of CHANNELs for this listener */
+    struct list_head queue;
+
+    int queue_size;
+    int queue_maxsize;
+
+    /* State variables used in libssh2_channel_forward_cancel() */
+    libssh2_nonblocking_states chanFwdCncl_state;
+    unsigned char *chanFwdCncl_data;
+    size_t chanFwdCncl_data_len;
+};
+
+typedef struct _libssh2_endpoint_data
+{
+    unsigned char *banner;
+
+    unsigned char *kexinit;
+    size_t kexinit_len;
+
+    const LIBSSH2_CRYPT_METHOD *crypt;
+    void *crypt_abstract;
+
+    const struct _LIBSSH2_MAC_METHOD *mac;
+    uint32_t seqno;
+    void *mac_abstract;
+
+    const LIBSSH2_COMP_METHOD *comp;
+    void *comp_abstract;
+
+    /* Method Preferences -- NULL yields "load order" */
+    char *crypt_prefs;
+    char *mac_prefs;
+    char *comp_prefs;
+    char *lang_prefs;
+} libssh2_endpoint_data;
+
+#define PACKETBUFSIZE (1024*16)
+
+struct transportpacket
+{
+    /* ------------- for incoming data --------------- */
+    unsigned char buf[PACKETBUFSIZE];
+    unsigned char init[5];  /* first 5 bytes of the incoming data stream,
+                               still encrypted */
+    size_t writeidx;        /* at what array index we do the next write into
+                               the buffer */
+    size_t readidx;         /* at what array index we do the next read from
+                               the buffer */
+    uint32_t packet_length; /* the most recent packet_length as read from the
+                               network data */
+    uint8_t padding_length; /* the most recent padding_length as read from the
+                               network data */
+    size_t data_num;        /* How much of the total package that has been read
+                               so far. */
+    size_t total_num;       /* How much a total package is supposed to be, in
+                               number of bytes. A full package is
+                               packet_length + padding_length + 4 +
+                               mac_length. */
+    unsigned char *payload; /* this is a pointer to a LIBSSH2_ALLOC()
+                               area to which we write decrypted data */
+    unsigned char *wptr;    /* write pointer into the payload to where we
+                               are currently writing decrypted data */
+
+    /* ------------- for outgoing data --------------- */
+    unsigned char outbuf[MAX_SSH_PACKET_LEN]; /* area for the outgoing data */
+
+    int ototal_num;         /* size of outbuf in number of bytes */
+    const unsigned char *odata; /* original pointer to the data */
+    size_t olen;            /* original size of the data we stored in
+                               outbuf */
+    size_t osent;           /* number of bytes already sent */
+};
+
+struct _LIBSSH2_PUBLICKEY
+{
+    LIBSSH2_CHANNEL *channel;
+    uint32_t version;
+
+    /* State variables used in libssh2_publickey_packet_receive() */
+    libssh2_nonblocking_states receive_state;
+    unsigned char *receive_packet;
+    size_t receive_packet_len;
+
+    /* State variables used in libssh2_publickey_add_ex() */
+    libssh2_nonblocking_states add_state;
+    unsigned char *add_packet;
+    unsigned char *add_s;
+
+    /* State variables used in libssh2_publickey_remove_ex() */
+    libssh2_nonblocking_states remove_state;
+    unsigned char *remove_packet;
+    unsigned char *remove_s;
+
+    /* State variables used in libssh2_publickey_list_fetch() */
+    libssh2_nonblocking_states listFetch_state;
+    unsigned char *listFetch_s;
+    unsigned char listFetch_buffer[12];
+    unsigned char *listFetch_data;
+    size_t listFetch_data_len;
+};
+
+#define LIBSSH2_SCP_RESPONSE_BUFLEN     256
+
+struct flags {
+    int sigpipe;  /* LIBSSH2_FLAG_SIGPIPE */
+    int compress; /* LIBSSH2_FLAG_COMPRESS */
+};
+
+struct _LIBSSH2_SESSION
+{
+    /* Memory management callbacks */
+    void *abstract;
+      LIBSSH2_ALLOC_FUNC((*alloc));
+      LIBSSH2_REALLOC_FUNC((*realloc));
+      LIBSSH2_FREE_FUNC((*free));
+
+    /* Other callbacks */
+      LIBSSH2_IGNORE_FUNC((*ssh_msg_ignore));
+      LIBSSH2_DEBUG_FUNC((*ssh_msg_debug));
+      LIBSSH2_DISCONNECT_FUNC((*ssh_msg_disconnect));
+      LIBSSH2_MACERROR_FUNC((*macerror));
+      LIBSSH2_X11_OPEN_FUNC((*x11));
+      LIBSSH2_SEND_FUNC((*send));
+      LIBSSH2_RECV_FUNC((*recv));
+
+    /* Method preferences -- NULL yields "load order" */
+    char *kex_prefs;
+    char *hostkey_prefs;
+
+    int state;
+
+    /* Flag options */
+    struct flags flag;
+
+    /* Agreed Key Exchange Method */
+    const LIBSSH2_KEX_METHOD *kex;
+    unsigned int burn_optimistic_kexinit:1;
+
+    unsigned char *session_id;
+    uint32_t session_id_len;
+
+    /* this is set to TRUE if a blocking API behavior is requested */
+    int api_block_mode;
+
+    /* Timeout used when blocking API behavior is active */
+    long api_timeout;
+
+    /* Server's public key */
+    const LIBSSH2_HOSTKEY_METHOD *hostkey;
+    void *server_hostkey_abstract;
+
+    /* Either set with libssh2_session_hostkey() (for server mode)
+     * Or read from server in (eg) KEXDH_INIT (for client mode)
+     */
+    unsigned char *server_hostkey;
+    uint32_t server_hostkey_len;
+#if LIBSSH2_MD5
+    unsigned char server_hostkey_md5[MD5_DIGEST_LENGTH];
+    int server_hostkey_md5_valid;
+#endif                          /* ! LIBSSH2_MD5 */
+    unsigned char server_hostkey_sha1[SHA_DIGEST_LENGTH];
+    int server_hostkey_sha1_valid;
+
+    unsigned char server_hostkey_sha256[SHA256_DIGEST_LENGTH];
+    int server_hostkey_sha256_valid;
+
+    /* (remote as source of data -- packet_read ) */
+    libssh2_endpoint_data remote;
+
+    /* (local as source of data -- packet_write ) */
+    libssh2_endpoint_data local;
+
+    /* Inbound Data linked list -- Sometimes the packet that comes in isn't the
+       packet we're ready for */
+    struct list_head packets;
+
+    /* Active connection channels */
+    struct list_head channels;
+
+    uint32_t next_channel;
+
+    struct list_head listeners; /* list of LIBSSH2_LISTENER structs */
+
+    /* Actual I/O socket */
+    libssh2_socket_t socket_fd;
+    int socket_state;
+    int socket_block_directions;
+    int socket_prev_blockstate; /* stores the state of the socket blockiness
+                                   when libssh2_session_startup() is called */
+
+    /* Error tracking */
+    const char *err_msg;
+    int err_code;
+    int err_flags;
+
+    /* struct members for packet-level reading */
+    struct transportpacket packet;
+#ifdef LIBSSH2DEBUG
+    int showmask;               /* what debug/trace messages to display */
+    libssh2_trace_handler_func tracehandler; /* callback to display trace
+                                                messages */
+    void *tracehandler_context; /* context for the trace handler */
+#endif
+
+    /* State variables used in libssh2_banner_send() */
+    libssh2_nonblocking_states banner_TxRx_state;
+    char banner_TxRx_banner[256];
+    ssize_t banner_TxRx_total_send;
+
+    /* State variables used in libssh2_kexinit() */
+    libssh2_nonblocking_states kexinit_state;
+    unsigned char *kexinit_data;
+    size_t kexinit_data_len;
+
+    /* State variables used in libssh2_session_startup() */
+    libssh2_nonblocking_states startup_state;
+    unsigned char *startup_data;
+    size_t startup_data_len;
+    unsigned char startup_service[sizeof("ssh-userauth") + 5 - 1];
+    size_t startup_service_length;
+    packet_require_state_t startup_req_state;
+    key_exchange_state_t startup_key_state;
+
+    /* State variables used in libssh2_session_free() */
+    libssh2_nonblocking_states free_state;
+
+    /* State variables used in libssh2_session_disconnect_ex() */
+    libssh2_nonblocking_states disconnect_state;
+    unsigned char disconnect_data[256 + 13];
+    size_t disconnect_data_len;
+
+    /* State variables used in libssh2_packet_read() */
+    libssh2_nonblocking_states readPack_state;
+    int readPack_encrypted;
+
+    /* State variables used in libssh2_userauth_list() */
+    libssh2_nonblocking_states userauth_list_state;
+    unsigned char *userauth_list_data;
+    size_t userauth_list_data_len;
+    packet_requirev_state_t userauth_list_packet_requirev_state;
+
+    /* State variables used in libssh2_userauth_password_ex() */
+    libssh2_nonblocking_states userauth_pswd_state;
+    unsigned char *userauth_pswd_data;
+    unsigned char userauth_pswd_data0;
+    size_t userauth_pswd_data_len;
+    char *userauth_pswd_newpw;
+    int userauth_pswd_newpw_len;
+    packet_requirev_state_t userauth_pswd_packet_requirev_state;
+
+    /* State variables used in libssh2_userauth_hostbased_fromfile_ex() */
+    libssh2_nonblocking_states userauth_host_state;
+    unsigned char *userauth_host_data;
+    size_t userauth_host_data_len;
+    unsigned char *userauth_host_packet;
+    size_t userauth_host_packet_len;
+    unsigned char *userauth_host_method;
+    size_t userauth_host_method_len;
+    unsigned char *userauth_host_s;
+    packet_requirev_state_t userauth_host_packet_requirev_state;
+
+    /* State variables used in libssh2_userauth_publickey_fromfile_ex() */
+    libssh2_nonblocking_states userauth_pblc_state;
+    unsigned char *userauth_pblc_data;
+    size_t userauth_pblc_data_len;
+    unsigned char *userauth_pblc_packet;
+    size_t userauth_pblc_packet_len;
+    unsigned char *userauth_pblc_method;
+    size_t userauth_pblc_method_len;
+    unsigned char *userauth_pblc_s;
+    unsigned char *userauth_pblc_b;
+    packet_requirev_state_t userauth_pblc_packet_requirev_state;
+
+    /* State variables used in libssh2_userauth_keyboard_interactive_ex() */
+    libssh2_nonblocking_states userauth_kybd_state;
+    unsigned char *userauth_kybd_data;
+    size_t userauth_kybd_data_len;
+    unsigned char *userauth_kybd_packet;
+    size_t userauth_kybd_packet_len;
+    unsigned int userauth_kybd_auth_name_len;
+    char *userauth_kybd_auth_name;
+    unsigned userauth_kybd_auth_instruction_len;
+    char *userauth_kybd_auth_instruction;
+    unsigned int userauth_kybd_num_prompts;
+    int userauth_kybd_auth_failure;
+    LIBSSH2_USERAUTH_KBDINT_PROMPT *userauth_kybd_prompts;
+    LIBSSH2_USERAUTH_KBDINT_RESPONSE *userauth_kybd_responses;
+    packet_requirev_state_t userauth_kybd_packet_requirev_state;
+
+    /* State variables used in libssh2_channel_open_ex() */
+    libssh2_nonblocking_states open_state;
+    packet_requirev_state_t open_packet_requirev_state;
+    LIBSSH2_CHANNEL *open_channel;
+    unsigned char *open_packet;
+    size_t open_packet_len;
+    unsigned char *open_data;
+    size_t open_data_len;
+    uint32_t open_local_channel;
+
+    /* State variables used in libssh2_channel_direct_tcpip_ex() */
+    libssh2_nonblocking_states direct_state;
+    unsigned char *direct_message;
+    size_t direct_host_len;
+    size_t direct_shost_len;
+    size_t direct_message_len;
+
+    /* State variables used in libssh2_channel_forward_listen_ex() */
+    libssh2_nonblocking_states fwdLstn_state;
+    unsigned char *fwdLstn_packet;
+    uint32_t fwdLstn_host_len;
+    uint32_t fwdLstn_packet_len;
+    packet_requirev_state_t fwdLstn_packet_requirev_state;
+
+    /* State variables used in libssh2_publickey_init() */
+    libssh2_nonblocking_states pkeyInit_state;
+    LIBSSH2_PUBLICKEY *pkeyInit_pkey;
+    LIBSSH2_CHANNEL *pkeyInit_channel;
+    unsigned char *pkeyInit_data;
+    size_t pkeyInit_data_len;
+    /* 19 = packet_len(4) + version_len(4) + "version"(7) + version_num(4) */
+    unsigned char pkeyInit_buffer[19];
+    size_t pkeyInit_buffer_sent; /* how much of buffer that has been sent */
+
+    /* State variables used in libssh2_packet_add() */
+    libssh2_nonblocking_states packAdd_state;
+    LIBSSH2_CHANNEL *packAdd_channelp; /* keeper of the channel during EAGAIN
+                                          states */
+    packet_queue_listener_state_t packAdd_Qlstn_state;
+    packet_x11_open_state_t packAdd_x11open_state;
+
+    /* State variables used in fullpacket() */
+    libssh2_nonblocking_states fullpacket_state;
+    int fullpacket_macstate;
+    size_t fullpacket_payload_len;
+    int fullpacket_packet_type;
+
+    /* State variables used in libssh2_sftp_init() */
+    libssh2_nonblocking_states sftpInit_state;
+    LIBSSH2_SFTP *sftpInit_sftp;
+    LIBSSH2_CHANNEL *sftpInit_channel;
+    unsigned char sftpInit_buffer[9];   /* sftp_header(5){excludes request_id}
+                                           + version_id(4) */
+    int sftpInit_sent; /* number of bytes from the buffer that have been
+                          sent */
+
+    /* State variables used in libssh2_scp_recv() / libssh_scp_recv2() */
+    libssh2_nonblocking_states scpRecv_state;
+    unsigned char *scpRecv_command;
+    size_t scpRecv_command_len;
+    unsigned char scpRecv_response[LIBSSH2_SCP_RESPONSE_BUFLEN];
+    size_t scpRecv_response_len;
+    long scpRecv_mode;
+#if defined(HAVE_LONGLONG) && defined(HAVE_STRTOLL)
+    /* we have the type and we can parse such numbers */
+    long long scpRecv_size;
+#define scpsize_strtol strtoll
+#elif defined(HAVE_STRTOI64)
+    __int64 scpRecv_size;
+#define scpsize_strtol _strtoi64
+#else
+    long scpRecv_size;
+#define scpsize_strtol strtol
+#endif
+    long scpRecv_mtime;
+    long scpRecv_atime;
+    LIBSSH2_CHANNEL *scpRecv_channel;
+
+    /* State variables used in libssh2_scp_send_ex() */
+    libssh2_nonblocking_states scpSend_state;
+    unsigned char *scpSend_command;
+    size_t scpSend_command_len;
+    unsigned char scpSend_response[LIBSSH2_SCP_RESPONSE_BUFLEN];
+    size_t scpSend_response_len;
+    LIBSSH2_CHANNEL *scpSend_channel;
+
+    /* Keepalive variables used by keepalive.c. */
+    int keepalive_interval;
+    int keepalive_want_reply;
+    time_t keepalive_last_sent;
+};
+
+/* session.state bits */
+#define LIBSSH2_STATE_EXCHANGING_KEYS   0x00000001
+#define LIBSSH2_STATE_NEWKEYS           0x00000002
+#define LIBSSH2_STATE_AUTHENTICATED     0x00000004
+#define LIBSSH2_STATE_KEX_ACTIVE        0x00000008
+
+/* session.flag helpers */
+#ifdef MSG_NOSIGNAL
+#define LIBSSH2_SOCKET_SEND_FLAGS(session)              \
+    (((session)->flag.sigpipe) ? 0 : MSG_NOSIGNAL)
+#define LIBSSH2_SOCKET_RECV_FLAGS(session)              \
+    (((session)->flag.sigpipe) ? 0 : MSG_NOSIGNAL)
+#else
+/* If MSG_NOSIGNAL isn't defined we're SOL on blocking SIGPIPE */
+#define LIBSSH2_SOCKET_SEND_FLAGS(session)      0
+#define LIBSSH2_SOCKET_RECV_FLAGS(session)      0
+#endif
+
+/* --------- */
+
+/* libssh2 extensible ssh api, ultimately I'd like to allow loading additional
+   methods via .so/.dll */
+
+struct _LIBSSH2_KEX_METHOD
+{
+    const char *name;
+
+    /* Key exchange, populates session->* and returns 0 on success, non-0 on
+       error */
+    int (*exchange_keys) (LIBSSH2_SESSION * session,
+                          key_exchange_state_low_t * key_state);
+
+    long flags;
+};
+
+struct _LIBSSH2_HOSTKEY_METHOD
+{
+    const char *name;
+    unsigned long hash_len;
+
+    int (*init) (LIBSSH2_SESSION * session, const unsigned char *hostkey_data,
+                 size_t hostkey_data_len, void **abstract);
+    int (*initPEM) (LIBSSH2_SESSION * session, const char *privkeyfile,
+                    unsigned const char *passphrase, void **abstract);
+    int (*initPEMFromMemory) (LIBSSH2_SESSION * session,
+                              const char *privkeyfiledata,
+                              size_t privkeyfiledata_len,
+                              unsigned const char *passphrase,
+                              void **abstract);
+    int (*sig_verify) (LIBSSH2_SESSION * session, const unsigned char *sig,
+                       size_t sig_len, const unsigned char *m,
+                       size_t m_len, void **abstract);
+    int (*signv) (LIBSSH2_SESSION * session, unsigned char **signature,
+                  size_t *signature_len, int veccount,
+                  const struct iovec datavec[], void **abstract);
+    int (*encrypt) (LIBSSH2_SESSION * session, unsigned char **dst,
+                    size_t *dst_len, const unsigned char *src,
+                    size_t src_len, void **abstract);
+    int (*dtor) (LIBSSH2_SESSION * session, void **abstract);
+};
+
+struct _LIBSSH2_CRYPT_METHOD
+{
+    const char *name;
+    const char *pem_annotation;
+
+    int blocksize;
+
+    /* iv and key sizes (-1 for variable length) */
+    int iv_len;
+    int secret_len;
+
+    long flags;
+
+    int (*init) (LIBSSH2_SESSION * session,
+                 const LIBSSH2_CRYPT_METHOD * method, unsigned char *iv,
+                 int *free_iv, unsigned char *secret, int *free_secret,
+                 int encrypt, void **abstract);
+    int (*crypt) (LIBSSH2_SESSION * session, unsigned char *block,
+                  size_t blocksize, void **abstract);
+    int (*dtor) (LIBSSH2_SESSION * session, void **abstract);
+
+      _libssh2_cipher_type(algo);
+};
+
+struct _LIBSSH2_COMP_METHOD
+{
+    const char *name;
+    int compress; /* 1 if it does compress, 0 if it doesn't */
+    int use_in_auth; /* 1 if compression should be used in userauth */
+    int (*init) (LIBSSH2_SESSION *session, int compress, void **abstract);
+    int (*comp) (LIBSSH2_SESSION *session,
+                 unsigned char *dest,
+                 size_t *dest_len,
+                 const unsigned char *src,
+                 size_t src_len,
+                 void **abstract);
+    int (*decomp) (LIBSSH2_SESSION *session,
+                   unsigned char **dest,
+                   size_t *dest_len,
+                   size_t payload_limit,
+                   const unsigned char *src,
+                   size_t src_len,
+                   void **abstract);
+    int (*dtor) (LIBSSH2_SESSION * session, int compress, void **abstract);
+};
+
+#ifdef LIBSSH2DEBUG
+void _libssh2_debug(LIBSSH2_SESSION * session, int context, const char *format,
+                    ...);
+#else
+#if (defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)) ||     \
+    defined(__GNUC__)
+/* C99 supported and also by older GCC */
+#define _libssh2_debug(x,y,z,...) do {} while (0)
+#else
+/* no gcc and not C99, do static and hopefully inline */
+static inline void
+_libssh2_debug(LIBSSH2_SESSION * session, int context, const char *format, ...)
+{
+    (void)session;
+    (void)context;
+    (void)format;
+}
+#endif
+#endif
+
+#define LIBSSH2_SOCKET_UNKNOWN                   1
+#define LIBSSH2_SOCKET_CONNECTED                 0
+#define LIBSSH2_SOCKET_DISCONNECTED             -1
+
+/* Initial packet state, prior to MAC check */
+#define LIBSSH2_MAC_UNCONFIRMED                  1
+/* When MAC type is "none" (proto initiation phase) all packets are deemed
+   "confirmed" */
+#define LIBSSH2_MAC_CONFIRMED                    0
+/* Something very bad is going on */
+#define LIBSSH2_MAC_INVALID                     -1
+
+/* Flags for _libssh2_error_flags */
+/* Error message is allocated on the heap */
+#define LIBSSH2_ERR_FLAG_DUP                     1
+
+/* SSH Packet Types -- Defined by internet draft */
+/* Transport Layer */
+#define SSH_MSG_DISCONNECT                          1
+#define SSH_MSG_IGNORE                              2
+#define SSH_MSG_UNIMPLEMENTED                       3
+#define SSH_MSG_DEBUG                               4
+#define SSH_MSG_SERVICE_REQUEST                     5
+#define SSH_MSG_SERVICE_ACCEPT                      6
+
+#define SSH_MSG_KEXINIT                             20
+#define SSH_MSG_NEWKEYS                             21
+
+/* diffie-hellman-group1-sha1 */
+#define SSH_MSG_KEXDH_INIT                          30
+#define SSH_MSG_KEXDH_REPLY                         31
+
+/* diffie-hellman-group-exchange-sha1 and
+   diffie-hellman-group-exchange-sha256 */
+#define SSH_MSG_KEX_DH_GEX_REQUEST_OLD              30
+#define SSH_MSG_KEX_DH_GEX_REQUEST                  34
+#define SSH_MSG_KEX_DH_GEX_GROUP                    31
+#define SSH_MSG_KEX_DH_GEX_INIT                     32
+#define SSH_MSG_KEX_DH_GEX_REPLY                    33
+
+/* ecdh */
+#define SSH2_MSG_KEX_ECDH_INIT                      30
+#define SSH2_MSG_KEX_ECDH_REPLY                     31
+
+/* User Authentication */
+#define SSH_MSG_USERAUTH_REQUEST                    50
+#define SSH_MSG_USERAUTH_FAILURE                    51
+#define SSH_MSG_USERAUTH_SUCCESS                    52
+#define SSH_MSG_USERAUTH_BANNER                     53
+
+/* "public key" method */
+#define SSH_MSG_USERAUTH_PK_OK                      60
+/* "password" method */
+#define SSH_MSG_USERAUTH_PASSWD_CHANGEREQ           60
+/* "keyboard-interactive" method */
+#define SSH_MSG_USERAUTH_INFO_REQUEST               60
+#define SSH_MSG_USERAUTH_INFO_RESPONSE              61
+
+/* Channels */
+#define SSH_MSG_GLOBAL_REQUEST                      80
+#define SSH_MSG_REQUEST_SUCCESS                     81
+#define SSH_MSG_REQUEST_FAILURE                     82
+
+#define SSH_MSG_CHANNEL_OPEN                        90
+#define SSH_MSG_CHANNEL_OPEN_CONFIRMATION           91
+#define SSH_MSG_CHANNEL_OPEN_FAILURE                92
+#define SSH_MSG_CHANNEL_WINDOW_ADJUST               93
+#define SSH_MSG_CHANNEL_DATA                        94
+#define SSH_MSG_CHANNEL_EXTENDED_DATA               95
+#define SSH_MSG_CHANNEL_EOF                         96
+#define SSH_MSG_CHANNEL_CLOSE                       97
+#define SSH_MSG_CHANNEL_REQUEST                     98
+#define SSH_MSG_CHANNEL_SUCCESS                     99
+#define SSH_MSG_CHANNEL_FAILURE                     100
+
+/* Error codes returned in SSH_MSG_CHANNEL_OPEN_FAILURE message
+   (see RFC4254) */
+#define SSH_OPEN_ADMINISTRATIVELY_PROHIBITED 1
+#define SSH_OPEN_CONNECT_FAILED              2
+#define SSH_OPEN_UNKNOWN_CHANNELTYPE         3
+#define SSH_OPEN_RESOURCE_SHORTAGE           4
+
+ssize_t _libssh2_recv(libssh2_socket_t socket, void *buffer,
+                      size_t length, int flags, void **abstract);
+ssize_t _libssh2_send(libssh2_socket_t socket, const void *buffer,
+                      size_t length, int flags, void **abstract);
+
+#define LIBSSH2_READ_TIMEOUT 60 /* generic timeout in seconds used when
+                                   waiting for more data to arrive */
+
+
+int _libssh2_kex_exchange(LIBSSH2_SESSION * session, int reexchange,
+                          key_exchange_state_t * state);
+
+/* Let crypt.c/hostkey.c expose their method structs */
+const LIBSSH2_CRYPT_METHOD **libssh2_crypt_methods(void);
+const LIBSSH2_HOSTKEY_METHOD **libssh2_hostkey_methods(void);
+
+/* misc.c */
+int _libssh2_bcrypt_pbkdf(const char *pass,
+                          size_t passlen,
+                          const uint8_t *salt,
+                          size_t saltlen,
+                          uint8_t *key,
+                          size_t keylen,
+                          unsigned int rounds);
+
+/* pem.c */
+int _libssh2_pem_parse(LIBSSH2_SESSION * session,
+                       const char *headerbegin,
+                       const char *headerend,
+                       const unsigned char *passphrase,
+                       FILE * fp, unsigned char **data, unsigned int *datalen);
+int _libssh2_pem_parse_memory(LIBSSH2_SESSION * session,
+                              const char *headerbegin,
+                              const char *headerend,
+                              const char *filedata, size_t filedata_len,
+                              unsigned char **data, unsigned int *datalen);
+ /* OpenSSL keys */
+int
+_libssh2_openssh_pem_parse(LIBSSH2_SESSION * session,
+                           const unsigned char *passphrase,
+                           FILE * fp, struct string_buf **decrypted_buf);
+int
+_libssh2_openssh_pem_parse_memory(LIBSSH2_SESSION * session,
+                                  const unsigned char *passphrase,
+                                  const char *filedata, size_t filedata_len,
+                                  struct string_buf **decrypted_buf);
+
+int _libssh2_pem_decode_sequence(unsigned char **data, unsigned int *datalen);
+int _libssh2_pem_decode_integer(unsigned char **data, unsigned int *datalen,
+                                unsigned char **i, unsigned int *ilen);
+
+/* global.c */
+void _libssh2_init_if_needed(void);
+
+
+#define ARRAY_SIZE(a) (sizeof ((a)) / sizeof ((a)[0]))
+
+/* define to output the libssh2_int64_t type in a *printf() */
+#if defined(__BORLANDC__) || defined(_MSC_VER) || defined(__MINGW32__)
+#define LIBSSH2_INT64_T_FORMAT "I64d"
+#else
+#define LIBSSH2_INT64_T_FORMAT "lld"
+#endif
+
+/* In Windows the default file mode is text but an application can override it.
+Therefore we specify it explicitly. https://github.com/curl/curl/pull/258
+*/
+#if defined(WIN32) || defined(MSDOS)
+#define FOPEN_READTEXT "rt"
+#define FOPEN_WRITETEXT "wt"
+#define FOPEN_APPENDTEXT "at"
+#elif defined(__CYGWIN__)
+/* Cygwin has specific behavior we need to address when WIN32 is not defined.
+https://cygwin.com/cygwin-ug-net/using-textbinary.html
+For write we want our output to have line endings of LF and be compatible with
+other Cygwin utilities. For read we want to handle input that may have line
+endings either CRLF or LF so 't' is appropriate.
+*/
+#define FOPEN_READTEXT "rt"
+#define FOPEN_WRITETEXT "w"
+#define FOPEN_APPENDTEXT "a"
+#else
+#define FOPEN_READTEXT "r"
+#define FOPEN_WRITETEXT "w"
+#define FOPEN_APPENDTEXT "a"
+#endif
+
+#endif /* LIBSSH2_H */

+ 414 - 0
libssh2/libssh2/src/mac.c

@@ -0,0 +1,414 @@
+/* Copyright (c) 2004-2007, Sara Golemon <sarag@libssh2.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms,
+ * with or without modification, are permitted provided
+ * that the following conditions are met:
+ *
+ *   Redistributions of source code must retain the above
+ *   copyright notice, this list of conditions and the
+ *   following disclaimer.
+ *
+ *   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.
+ *
+ *   Neither the name of the copyright holder nor the names
+ *   of any other contributors may be used to endorse or
+ *   promote products derived from this software without
+ *   specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+ * CONTRIBUTORS "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 COPYRIGHT OWNER OR
+ * CONTRIBUTORS 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 "libssh2_priv.h"
+#include "mac.h"
+
+#ifdef LIBSSH2_MAC_NONE
+/* mac_none_MAC
+ * Minimalist MAC: No MAC
+ */
+static int
+mac_none_MAC(LIBSSH2_SESSION * session, unsigned char *buf,
+             uint32_t seqno, const unsigned char *packet,
+             uint32_t packet_len, const unsigned char *addtl,
+             uint32_t addtl_len, void **abstract)
+{
+    return 0;
+}
+
+
+
+
+static LIBSSH2_MAC_METHOD mac_method_none = {
+    "none",
+    0,
+    0,
+    NULL,
+    mac_none_MAC,
+    NULL
+};
+#endif /* LIBSSH2_MAC_NONE */
+
+/* mac_method_common_init
+ * Initialize simple mac methods
+ */
+static int
+mac_method_common_init(LIBSSH2_SESSION * session, unsigned char *key,
+                       int *free_key, void **abstract)
+{
+    *abstract = key;
+    *free_key = 0;
+    (void) session;
+
+    return 0;
+}
+
+
+
+/* mac_method_common_dtor
+ * Cleanup simple mac methods
+ */
+static int
+mac_method_common_dtor(LIBSSH2_SESSION * session, void **abstract)
+{
+    if(*abstract) {
+        LIBSSH2_FREE(session, *abstract);
+    }
+    *abstract = NULL;
+
+    return 0;
+}
+
+
+
+#if LIBSSH2_HMAC_SHA512
+/* mac_method_hmac_sha512_hash
+ * Calculate hash using full sha512 value
+ */
+static int
+mac_method_hmac_sha2_512_hash(LIBSSH2_SESSION * session,
+                          unsigned char *buf, uint32_t seqno,
+                          const unsigned char *packet,
+                          uint32_t packet_len,
+                          const unsigned char *addtl,
+                          uint32_t addtl_len, void **abstract)
+{
+    libssh2_hmac_ctx ctx;
+    unsigned char seqno_buf[4];
+    (void) session;
+
+    _libssh2_htonu32(seqno_buf, seqno);
+
+    libssh2_hmac_ctx_init(ctx);
+    libssh2_hmac_sha512_init(&ctx, *abstract, 64);
+    libssh2_hmac_update(ctx, seqno_buf, 4);
+    libssh2_hmac_update(ctx, packet, packet_len);
+    if(addtl && addtl_len) {
+        libssh2_hmac_update(ctx, addtl, addtl_len);
+    }
+    libssh2_hmac_final(ctx, buf);
+    libssh2_hmac_cleanup(&ctx);
+
+    return 0;
+}
+
+
+
+static const LIBSSH2_MAC_METHOD mac_method_hmac_sha2_512 = {
+    "hmac-sha2-512",
+    64,
+    64,
+    mac_method_common_init,
+    mac_method_hmac_sha2_512_hash,
+    mac_method_common_dtor,
+};
+#endif
+
+
+
+#if LIBSSH2_HMAC_SHA256
+/* mac_method_hmac_sha256_hash
+ * Calculate hash using full sha256 value
+ */
+static int
+mac_method_hmac_sha2_256_hash(LIBSSH2_SESSION * session,
+                          unsigned char *buf, uint32_t seqno,
+                          const unsigned char *packet,
+                          uint32_t packet_len,
+                          const unsigned char *addtl,
+                          uint32_t addtl_len, void **abstract)
+{
+    libssh2_hmac_ctx ctx;
+    unsigned char seqno_buf[4];
+    (void) session;
+
+    _libssh2_htonu32(seqno_buf, seqno);
+
+    libssh2_hmac_ctx_init(ctx);
+    libssh2_hmac_sha256_init(&ctx, *abstract, 32);
+    libssh2_hmac_update(ctx, seqno_buf, 4);
+    libssh2_hmac_update(ctx, packet, packet_len);
+    if(addtl && addtl_len) {
+        libssh2_hmac_update(ctx, addtl, addtl_len);
+    }
+    libssh2_hmac_final(ctx, buf);
+    libssh2_hmac_cleanup(&ctx);
+
+    return 0;
+}
+
+
+
+static const LIBSSH2_MAC_METHOD mac_method_hmac_sha2_256 = {
+    "hmac-sha2-256",
+    32,
+    32,
+    mac_method_common_init,
+    mac_method_hmac_sha2_256_hash,
+    mac_method_common_dtor,
+};
+#endif
+
+
+
+
+/* mac_method_hmac_sha1_hash
+ * Calculate hash using full sha1 value
+ */
+static int
+mac_method_hmac_sha1_hash(LIBSSH2_SESSION * session,
+                          unsigned char *buf, uint32_t seqno,
+                          const unsigned char *packet,
+                          uint32_t packet_len,
+                          const unsigned char *addtl,
+                          uint32_t addtl_len, void **abstract)
+{
+    libssh2_hmac_ctx ctx;
+    unsigned char seqno_buf[4];
+    (void) session;
+
+    _libssh2_htonu32(seqno_buf, seqno);
+
+    libssh2_hmac_ctx_init(ctx);
+    libssh2_hmac_sha1_init(&ctx, *abstract, 20);
+    libssh2_hmac_update(ctx, seqno_buf, 4);
+    libssh2_hmac_update(ctx, packet, packet_len);
+    if(addtl && addtl_len) {
+        libssh2_hmac_update(ctx, addtl, addtl_len);
+    }
+    libssh2_hmac_final(ctx, buf);
+    libssh2_hmac_cleanup(&ctx);
+
+    return 0;
+}
+
+
+
+static const LIBSSH2_MAC_METHOD mac_method_hmac_sha1 = {
+    "hmac-sha1",
+    20,
+    20,
+    mac_method_common_init,
+    mac_method_hmac_sha1_hash,
+    mac_method_common_dtor,
+};
+
+/* mac_method_hmac_sha1_96_hash
+ * Calculate hash using first 96 bits of sha1 value
+ */
+static int
+mac_method_hmac_sha1_96_hash(LIBSSH2_SESSION * session,
+                             unsigned char *buf, uint32_t seqno,
+                             const unsigned char *packet,
+                             uint32_t packet_len,
+                             const unsigned char *addtl,
+                             uint32_t addtl_len, void **abstract)
+{
+    unsigned char temp[SHA_DIGEST_LENGTH];
+
+    mac_method_hmac_sha1_hash(session, temp, seqno, packet, packet_len,
+                              addtl, addtl_len, abstract);
+    memcpy(buf, (char *) temp, 96 / 8);
+
+    return 0;
+}
+
+
+
+static const LIBSSH2_MAC_METHOD mac_method_hmac_sha1_96 = {
+    "hmac-sha1-96",
+    12,
+    20,
+    mac_method_common_init,
+    mac_method_hmac_sha1_96_hash,
+    mac_method_common_dtor,
+};
+
+#if LIBSSH2_MD5
+/* mac_method_hmac_md5_hash
+ * Calculate hash using full md5 value
+ */
+static int
+mac_method_hmac_md5_hash(LIBSSH2_SESSION * session, unsigned char *buf,
+                         uint32_t seqno,
+                         const unsigned char *packet,
+                         uint32_t packet_len,
+                         const unsigned char *addtl,
+                         uint32_t addtl_len, void **abstract)
+{
+    libssh2_hmac_ctx ctx;
+    unsigned char seqno_buf[4];
+    (void) session;
+
+    _libssh2_htonu32(seqno_buf, seqno);
+
+    libssh2_hmac_ctx_init(ctx);
+    libssh2_hmac_md5_init(&ctx, *abstract, 16);
+    libssh2_hmac_update(ctx, seqno_buf, 4);
+    libssh2_hmac_update(ctx, packet, packet_len);
+    if(addtl && addtl_len) {
+        libssh2_hmac_update(ctx, addtl, addtl_len);
+    }
+    libssh2_hmac_final(ctx, buf);
+    libssh2_hmac_cleanup(&ctx);
+
+    return 0;
+}
+
+
+
+static const LIBSSH2_MAC_METHOD mac_method_hmac_md5 = {
+    "hmac-md5",
+    16,
+    16,
+    mac_method_common_init,
+    mac_method_hmac_md5_hash,
+    mac_method_common_dtor,
+};
+
+/* mac_method_hmac_md5_96_hash
+ * Calculate hash using first 96 bits of md5 value
+ */
+static int
+mac_method_hmac_md5_96_hash(LIBSSH2_SESSION * session,
+                            unsigned char *buf, uint32_t seqno,
+                            const unsigned char *packet,
+                            uint32_t packet_len,
+                            const unsigned char *addtl,
+                            uint32_t addtl_len, void **abstract)
+{
+    unsigned char temp[MD5_DIGEST_LENGTH];
+    mac_method_hmac_md5_hash(session, temp, seqno, packet, packet_len,
+                             addtl, addtl_len, abstract);
+    memcpy(buf, (char *) temp, 96 / 8);
+    return 0;
+}
+
+
+
+static const LIBSSH2_MAC_METHOD mac_method_hmac_md5_96 = {
+    "hmac-md5-96",
+    12,
+    16,
+    mac_method_common_init,
+    mac_method_hmac_md5_96_hash,
+    mac_method_common_dtor,
+};
+#endif /* LIBSSH2_MD5 */
+
+#if LIBSSH2_HMAC_RIPEMD
+/* mac_method_hmac_ripemd160_hash
+ * Calculate hash using ripemd160 value
+ */
+static int
+mac_method_hmac_ripemd160_hash(LIBSSH2_SESSION * session,
+                               unsigned char *buf, uint32_t seqno,
+                               const unsigned char *packet,
+                               uint32_t packet_len,
+                               const unsigned char *addtl,
+                               uint32_t addtl_len,
+                               void **abstract)
+{
+    libssh2_hmac_ctx ctx;
+    unsigned char seqno_buf[4];
+    (void) session;
+
+    _libssh2_htonu32(seqno_buf, seqno);
+
+    libssh2_hmac_ctx_init(ctx);
+    libssh2_hmac_ripemd160_init(&ctx, *abstract, 20);
+    libssh2_hmac_update(ctx, seqno_buf, 4);
+    libssh2_hmac_update(ctx, packet, packet_len);
+    if(addtl && addtl_len) {
+        libssh2_hmac_update(ctx, addtl, addtl_len);
+    }
+    libssh2_hmac_final(ctx, buf);
+    libssh2_hmac_cleanup(&ctx);
+
+    return 0;
+}
+
+
+
+static const LIBSSH2_MAC_METHOD mac_method_hmac_ripemd160 = {
+    "hmac-ripemd160",
+    20,
+    20,
+    mac_method_common_init,
+    mac_method_hmac_ripemd160_hash,
+    mac_method_common_dtor,
+};
+
+static const LIBSSH2_MAC_METHOD mac_method_hmac_ripemd160_openssh_com = {
+    "hmac-ripemd160@openssh.com",
+    20,
+    20,
+    mac_method_common_init,
+    mac_method_hmac_ripemd160_hash,
+    mac_method_common_dtor,
+};
+#endif /* LIBSSH2_HMAC_RIPEMD */
+
+static const LIBSSH2_MAC_METHOD *mac_methods[] = {
+#if LIBSSH2_HMAC_SHA256
+    &mac_method_hmac_sha2_256,
+#endif
+#if LIBSSH2_HMAC_SHA512
+    &mac_method_hmac_sha2_512,
+#endif
+    &mac_method_hmac_sha1,
+    &mac_method_hmac_sha1_96,
+#if LIBSSH2_MD5
+    &mac_method_hmac_md5,
+    &mac_method_hmac_md5_96,
+#endif
+#if LIBSSH2_HMAC_RIPEMD
+    &mac_method_hmac_ripemd160,
+    &mac_method_hmac_ripemd160_openssh_com,
+#endif /* LIBSSH2_HMAC_RIPEMD */
+#ifdef LIBSSH2_MAC_NONE
+    &mac_method_none,
+#endif /* LIBSSH2_MAC_NONE */
+    NULL
+};
+
+const LIBSSH2_MAC_METHOD **
+_libssh2_mac_methods(void)
+{
+    return mac_methods;
+}

+ 67 - 0
libssh2/libssh2/src/mac.h

@@ -0,0 +1,67 @@
+#ifndef __LIBSSH2_MAC_H
+#define __LIBSSH2_MAC_H
+
+/* Copyright (C) 2009-2010 by Daniel Stenberg
+ *
+ * Redistribution and use in source and binary forms,
+ * with or without modification, are permitted provided
+ * that the following conditions are met:
+ *
+ *   Redistributions of source code must retain the above
+ *   copyright notice, this list of conditions and the
+ *   following disclaimer.
+ *
+ *   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.
+ *
+ *   Neither the name of the copyright holder nor the names
+ *   of any other contributors may be used to endorse or
+ *   promote products derived from this software without
+ *   specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+ * CONTRIBUTORS "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 COPYRIGHT OWNER OR
+ * CONTRIBUTORS 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 "libssh2_priv.h"
+
+struct _LIBSSH2_MAC_METHOD
+{
+    const char *name;
+
+    /* The length of a given MAC packet */
+    int mac_len;
+
+    /* integrity key length */
+    int key_len;
+
+    /* Message Authentication Code Hashing algo */
+    int (*init) (LIBSSH2_SESSION * session, unsigned char *key, int *free_key,
+                 void **abstract);
+    int (*hash) (LIBSSH2_SESSION * session, unsigned char *buf,
+                 uint32_t seqno, const unsigned char *packet,
+                 uint32_t packet_len, const unsigned char *addtl,
+                 uint32_t addtl_len, void **abstract);
+    int (*dtor) (LIBSSH2_SESSION * session, void **abstract);
+};
+
+typedef struct _LIBSSH2_MAC_METHOD LIBSSH2_MAC_METHOD;
+
+const LIBSSH2_MAC_METHOD **_libssh2_mac_methods(void);
+
+#endif /* __LIBSSH2_MAC_H */

+ 733 - 0
libssh2/libssh2/src/mbedtls.c

@@ -0,0 +1,733 @@
+/* Copyright (c) 2016, Art <https://github.com/wildart>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms,
+ * with or without modification, are permitted provided
+ * that the following conditions are met:
+ *
+ *   Redistributions of source code must retain the above
+ *   copyright notice, this list of conditions and the
+ *   following disclaimer.
+ *
+ *   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.
+ *
+ *   Neither the name of the copyright holder nor the names
+ *   of any other contributors may be used to endorse or
+ *   promote products derived from this software without
+ *   specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+ * CONTRIBUTORS "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 COPYRIGHT OWNER OR
+ * CONTRIBUTORS 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 "libssh2_priv.h"
+
+#ifdef LIBSSH2_MBEDTLS /* compile only if we build with mbedtls */
+
+/*******************************************************************/
+/*
+ * mbedTLS backend: Global context handles
+ */
+
+static mbedtls_entropy_context  _libssh2_mbedtls_entropy;
+static mbedtls_ctr_drbg_context _libssh2_mbedtls_ctr_drbg;
+
+/*******************************************************************/
+/*
+ * mbedTLS backend: Generic functions
+ */
+
+void
+_libssh2_mbedtls_init(void)
+{
+    int ret;
+
+    mbedtls_entropy_init(&_libssh2_mbedtls_entropy);
+    mbedtls_ctr_drbg_init(&_libssh2_mbedtls_ctr_drbg);
+
+    ret = mbedtls_ctr_drbg_seed(&_libssh2_mbedtls_ctr_drbg,
+                                mbedtls_entropy_func,
+                                &_libssh2_mbedtls_entropy, NULL, 0);
+    if(ret != 0)
+        mbedtls_ctr_drbg_free(&_libssh2_mbedtls_ctr_drbg);
+}
+
+void
+_libssh2_mbedtls_free(void)
+{
+    mbedtls_ctr_drbg_free(&_libssh2_mbedtls_ctr_drbg);
+    mbedtls_entropy_free(&_libssh2_mbedtls_entropy);
+}
+
+int
+_libssh2_mbedtls_random(unsigned char *buf, int len)
+{
+    int ret;
+    ret = mbedtls_ctr_drbg_random(&_libssh2_mbedtls_ctr_drbg, buf, len);
+    return ret == 0 ? 0 : -1;
+}
+
+static void
+_libssh2_mbedtls_safe_free(void *buf, int len)
+{
+#ifndef LIBSSH2_CLEAR_MEMORY
+    (void)len;
+#endif
+
+    if(!buf)
+        return;
+
+#ifdef LIBSSH2_CLEAR_MEMORY
+    if(len > 0)
+        memset(buf, 0, len);
+#endif
+
+    mbedtls_free(buf);
+}
+
+int
+_libssh2_mbedtls_cipher_init(_libssh2_cipher_ctx *ctx,
+                             _libssh2_cipher_type(algo),
+                             unsigned char *iv,
+                             unsigned char *secret,
+                             int encrypt)
+{
+    const mbedtls_cipher_info_t *cipher_info;
+    int ret, op;
+
+    if(!ctx)
+        return -1;
+
+    op = encrypt == 0 ? MBEDTLS_ENCRYPT : MBEDTLS_DECRYPT;
+
+    cipher_info = mbedtls_cipher_info_from_type(algo);
+    if(!cipher_info)
+        return -1;
+
+    mbedtls_cipher_init(ctx);
+    ret = mbedtls_cipher_setup(ctx, cipher_info);
+    if(!ret)
+        ret = mbedtls_cipher_setkey(ctx, secret, cipher_info->key_bitlen, op);
+
+    if(!ret)
+        ret = mbedtls_cipher_set_iv(ctx, iv, cipher_info->iv_size);
+
+    return ret == 0 ? 0 : -1;
+}
+
+int
+_libssh2_mbedtls_cipher_crypt(_libssh2_cipher_ctx *ctx,
+                              _libssh2_cipher_type(algo),
+                              int encrypt,
+                              unsigned char *block,
+                              size_t blocklen)
+{
+    int ret;
+    unsigned char *output;
+    size_t osize, olen, finish_olen;
+
+    (void) encrypt;
+    (void) algo;
+
+    osize = blocklen + mbedtls_cipher_get_block_size(ctx);
+
+    output = (unsigned char *)mbedtls_calloc(osize, sizeof(char));
+    if(output) {
+        ret = mbedtls_cipher_reset(ctx);
+
+        if(!ret)
+            ret = mbedtls_cipher_update(ctx, block, blocklen, output, &olen);
+
+        if(!ret)
+            ret = mbedtls_cipher_finish(ctx, output + olen, &finish_olen);
+
+        if(!ret) {
+            olen += finish_olen;
+            memcpy(block, output, olen);
+        }
+
+        _libssh2_mbedtls_safe_free(output, osize);
+    }
+    else
+        ret = -1;
+
+    return ret == 0 ? 0 : -1;
+}
+
+void
+_libssh2_mbedtls_cipher_dtor(_libssh2_cipher_ctx *ctx)
+{
+    mbedtls_cipher_free(ctx);
+}
+
+
+int
+_libssh2_mbedtls_hash_init(mbedtls_md_context_t *ctx,
+                          mbedtls_md_type_t mdtype,
+                          const unsigned char *key, unsigned long keylen)
+{
+    const mbedtls_md_info_t *md_info;
+    int ret, hmac;
+
+    md_info = mbedtls_md_info_from_type(mdtype);
+    if(!md_info)
+        return 0;
+
+    hmac = key == NULL ? 0 : 1;
+
+    mbedtls_md_init(ctx);
+    ret = mbedtls_md_setup(ctx, md_info, hmac);
+    if(!ret) {
+        if(hmac)
+            ret = mbedtls_md_hmac_starts(ctx, key, keylen);
+        else
+            ret = mbedtls_md_starts(ctx);
+    }
+
+    return ret == 0 ? 1 : 0;
+}
+
+int
+_libssh2_mbedtls_hash_final(mbedtls_md_context_t *ctx, unsigned char *hash)
+{
+    int ret;
+
+    ret = mbedtls_md_finish(ctx, hash);
+    mbedtls_md_free(ctx);
+
+    return ret == 0 ? 0 : -1;
+}
+
+int
+_libssh2_mbedtls_hash(const unsigned char *data, unsigned long datalen,
+                      mbedtls_md_type_t mdtype, unsigned char *hash)
+{
+    const mbedtls_md_info_t *md_info;
+    int ret;
+
+    md_info = mbedtls_md_info_from_type(mdtype);
+    if(!md_info)
+        return 0;
+
+    ret = mbedtls_md(md_info, data, datalen, hash);
+
+    return ret == 0 ? 0 : -1;
+}
+
+/*******************************************************************/
+/*
+ * mbedTLS backend: BigNumber functions
+ */
+
+_libssh2_bn *
+_libssh2_mbedtls_bignum_init(void)
+{
+    _libssh2_bn *bignum;
+
+    bignum = (_libssh2_bn *)mbedtls_calloc(1, sizeof(_libssh2_bn));
+    if(bignum) {
+        mbedtls_mpi_init(bignum);
+    }
+
+    return bignum;
+}
+
+void
+_libssh2_mbedtls_bignum_free(_libssh2_bn *bn)
+{
+    if(bn) {
+        mbedtls_mpi_free(bn);
+        mbedtls_free(bn);
+    }
+}
+
+static int
+_libssh2_mbedtls_bignum_random(_libssh2_bn *bn, int bits, int top, int bottom)
+{
+    size_t len;
+    int err;
+    int i;
+
+    if(!bn || bits <= 0)
+        return -1;
+
+    len = (bits + 7) >> 3;
+    err = mbedtls_mpi_fill_random(bn, len, mbedtls_ctr_drbg_random,
+                                  &_libssh2_mbedtls_ctr_drbg);
+    if(err)
+        return -1;
+
+    /* Zero unsued bits above the most significant bit*/
+    for(i = len*8 - 1; bits <= i; --i) {
+        err = mbedtls_mpi_set_bit(bn, i, 0);
+        if(err)
+            return -1;
+    }
+
+    /* If `top` is -1, the most significant bit of the random number can be
+       zero.  If top is 0, the most significant bit of the random number is
+       set to 1, and if top is 1, the two most significant bits of the number
+       will be set to 1, so that the product of two such random numbers will
+       always have 2*bits length.
+    */
+    for(i = 0; i <= top; ++i) {
+        err = mbedtls_mpi_set_bit(bn, bits-i-1, 1);
+        if(err)
+            return -1;
+    }
+
+    /* make odd by setting first bit in least significant byte */
+    if(bottom) {
+        err = mbedtls_mpi_set_bit(bn, 0, 1);
+        if(err)
+            return -1;
+    }
+
+    return 0;
+}
+
+
+/*******************************************************************/
+/*
+ * mbedTLS backend: RSA functions
+ */
+
+int
+_libssh2_mbedtls_rsa_new(libssh2_rsa_ctx **rsa,
+                        const unsigned char *edata,
+                        unsigned long elen,
+                        const unsigned char *ndata,
+                        unsigned long nlen,
+                        const unsigned char *ddata,
+                        unsigned long dlen,
+                        const unsigned char *pdata,
+                        unsigned long plen,
+                        const unsigned char *qdata,
+                        unsigned long qlen,
+                        const unsigned char *e1data,
+                        unsigned long e1len,
+                        const unsigned char *e2data,
+                        unsigned long e2len,
+                        const unsigned char *coeffdata,
+                        unsigned long coefflen)
+{
+    int ret;
+    libssh2_rsa_ctx *ctx;
+
+    ctx = (libssh2_rsa_ctx *) mbedtls_calloc(1, sizeof(libssh2_rsa_ctx));
+    if(ctx != NULL) {
+        mbedtls_rsa_init(ctx, MBEDTLS_RSA_PKCS_V15, 0);
+    }
+    else
+        return -1;
+
+    /* !checksrc! disable ASSIGNWITHINCONDITION 1 */
+    if((ret = mbedtls_mpi_read_binary(&(ctx->E), edata, elen) ) != 0 ||
+       (ret = mbedtls_mpi_read_binary(&(ctx->N), ndata, nlen) ) != 0) {
+        ret = -1;
+    }
+
+    if(!ret) {
+        ctx->len = mbedtls_mpi_size(&(ctx->N));
+    }
+
+    if(!ret && ddata) {
+        /* !checksrc! disable ASSIGNWITHINCONDITION 1 */
+        if((ret = mbedtls_mpi_read_binary(&(ctx->D), ddata, dlen) ) != 0 ||
+           (ret = mbedtls_mpi_read_binary(&(ctx->P), pdata, plen) ) != 0 ||
+           (ret = mbedtls_mpi_read_binary(&(ctx->Q), qdata, qlen) ) != 0 ||
+           (ret = mbedtls_mpi_read_binary(&(ctx->DP), e1data, e1len) ) != 0 ||
+           (ret = mbedtls_mpi_read_binary(&(ctx->DQ), e2data, e2len) ) != 0 ||
+           (ret = mbedtls_mpi_read_binary(&(ctx->QP), coeffdata, coefflen) )
+           != 0) {
+            ret = -1;
+        }
+        ret = mbedtls_rsa_check_privkey(ctx);
+    }
+    else if(!ret) {
+        ret = mbedtls_rsa_check_pubkey(ctx);
+    }
+
+    if(ret && ctx) {
+        _libssh2_mbedtls_rsa_free(ctx);
+        ctx = NULL;
+    }
+    *rsa = ctx;
+    return ret;
+}
+
+int
+_libssh2_mbedtls_rsa_new_private(libssh2_rsa_ctx **rsa,
+                                LIBSSH2_SESSION *session,
+                                const char *filename,
+                                const unsigned char *passphrase)
+{
+    int ret;
+    mbedtls_pk_context pkey;
+    mbedtls_rsa_context *pk_rsa;
+
+    *rsa = (libssh2_rsa_ctx *) LIBSSH2_ALLOC(session, sizeof(libssh2_rsa_ctx));
+    if(*rsa == NULL)
+        return -1;
+
+    mbedtls_rsa_init(*rsa, MBEDTLS_RSA_PKCS_V15, 0);
+    mbedtls_pk_init(&pkey);
+
+    ret = mbedtls_pk_parse_keyfile(&pkey, filename, (char *)passphrase);
+    if(ret != 0 || mbedtls_pk_get_type(&pkey) != MBEDTLS_PK_RSA) {
+        mbedtls_pk_free(&pkey);
+        mbedtls_rsa_free(*rsa);
+        LIBSSH2_FREE(session, *rsa);
+        *rsa = NULL;
+        return -1;
+    }
+
+    pk_rsa = mbedtls_pk_rsa(pkey);
+    mbedtls_rsa_copy(*rsa, pk_rsa);
+    mbedtls_pk_free(&pkey);
+
+    return 0;
+}
+
+int
+_libssh2_mbedtls_rsa_new_private_frommemory(libssh2_rsa_ctx **rsa,
+                                           LIBSSH2_SESSION *session,
+                                           const char *filedata,
+                                           size_t filedata_len,
+                                           unsigned const char *passphrase)
+{
+    int ret;
+    mbedtls_pk_context pkey;
+    mbedtls_rsa_context *pk_rsa;
+    void *filedata_nullterm;
+    size_t pwd_len;
+
+    *rsa = (libssh2_rsa_ctx *) mbedtls_calloc(1, sizeof(libssh2_rsa_ctx));
+    if(*rsa == NULL)
+        return -1;
+
+    /*
+    mbedtls checks in "mbedtls/pkparse.c:1184" if "key[keylen - 1] != '\0'"
+    private-key from memory will fail if the last byte is not a null byte
+    */
+    filedata_nullterm = mbedtls_calloc(filedata_len + 1, 1);
+    if(filedata_nullterm == NULL) {
+        return -1;
+    }
+    memcpy(filedata_nullterm, filedata, filedata_len);
+
+    mbedtls_pk_init(&pkey);
+
+    pwd_len = passphrase != NULL ? strlen((const char *)passphrase) : 0;
+    ret = mbedtls_pk_parse_key(&pkey, (unsigned char *)filedata_nullterm,
+                               filedata_len + 1,
+                               passphrase, pwd_len);
+    _libssh2_mbedtls_safe_free(filedata_nullterm, filedata_len);
+
+    if(ret != 0 || mbedtls_pk_get_type(&pkey) != MBEDTLS_PK_RSA) {
+        mbedtls_pk_free(&pkey);
+        mbedtls_rsa_free(*rsa);
+        LIBSSH2_FREE(session, *rsa);
+        *rsa = NULL;
+        return -1;
+    }
+
+    pk_rsa = mbedtls_pk_rsa(pkey);
+    mbedtls_rsa_copy(*rsa, pk_rsa);
+    mbedtls_pk_free(&pkey);
+
+    return 0;
+}
+
+int
+_libssh2_mbedtls_rsa_sha1_verify(libssh2_rsa_ctx *rsa,
+                                const unsigned char *sig,
+                                unsigned long sig_len,
+                                const unsigned char *m,
+                                unsigned long m_len)
+{
+    unsigned char hash[SHA_DIGEST_LENGTH];
+    int ret;
+
+    ret = _libssh2_mbedtls_hash(m, m_len, MBEDTLS_MD_SHA1, hash);
+    if(ret)
+        return -1; /* failure */
+
+    ret = mbedtls_rsa_pkcs1_verify(rsa, NULL, NULL, MBEDTLS_RSA_PUBLIC,
+                                   MBEDTLS_MD_SHA1, SHA_DIGEST_LENGTH,
+                                   hash, sig);
+
+    return (ret == 0) ? 0 : -1;
+}
+
+int
+_libssh2_mbedtls_rsa_sha1_sign(LIBSSH2_SESSION *session,
+                              libssh2_rsa_ctx *rsa,
+                              const unsigned char *hash,
+                              size_t hash_len,
+                              unsigned char **signature,
+                              size_t *signature_len)
+{
+    int ret;
+    unsigned char *sig;
+    unsigned int sig_len;
+
+    (void)hash_len;
+
+    sig_len = rsa->len;
+    sig = LIBSSH2_ALLOC(session, sig_len);
+    if(!sig) {
+        return -1;
+    }
+
+    ret = mbedtls_rsa_pkcs1_sign(rsa, NULL, NULL, MBEDTLS_RSA_PRIVATE,
+                                 MBEDTLS_MD_SHA1, SHA_DIGEST_LENGTH,
+                                 hash, sig);
+    if(ret) {
+        LIBSSH2_FREE(session, sig);
+        return -1;
+    }
+
+    *signature = sig;
+    *signature_len = sig_len;
+
+    return (ret == 0) ? 0 : -1;
+}
+
+void
+_libssh2_mbedtls_rsa_free(libssh2_rsa_ctx *ctx)
+{
+    mbedtls_rsa_free(ctx);
+    mbedtls_free(ctx);
+}
+
+static unsigned char *
+gen_publickey_from_rsa(LIBSSH2_SESSION *session,
+                      mbedtls_rsa_context *rsa,
+                      size_t *keylen)
+{
+    int            e_bytes, n_bytes;
+    unsigned long  len;
+    unsigned char *key;
+    unsigned char *p;
+
+    e_bytes = mbedtls_mpi_size(&rsa->E);
+    n_bytes = mbedtls_mpi_size(&rsa->N);
+
+    /* Key form is "ssh-rsa" + e + n. */
+    len = 4 + 7 + 4 + e_bytes + 4 + n_bytes;
+
+    key = LIBSSH2_ALLOC(session, len);
+    if(!key) {
+        return NULL;
+    }
+
+    /* Process key encoding. */
+    p = key;
+
+    _libssh2_htonu32(p, 7);  /* Key type. */
+    p += 4;
+    memcpy(p, "ssh-rsa", 7);
+    p += 7;
+
+    _libssh2_htonu32(p, e_bytes);
+    p += 4;
+    mbedtls_mpi_write_binary(&rsa->E, p, e_bytes);
+
+    _libssh2_htonu32(p, n_bytes);
+    p += 4;
+    mbedtls_mpi_write_binary(&rsa->N, p, n_bytes);
+
+    *keylen = (size_t)(p - key);
+    return key;
+}
+
+static int
+_libssh2_mbedtls_pub_priv_key(LIBSSH2_SESSION *session,
+                               unsigned char **method,
+                               size_t *method_len,
+                               unsigned char **pubkeydata,
+                               size_t *pubkeydata_len,
+                               mbedtls_pk_context *pkey)
+{
+    unsigned char *key = NULL, *mth = NULL;
+    size_t keylen = 0, mthlen = 0;
+    int ret;
+    mbedtls_rsa_context *rsa;
+
+    if(mbedtls_pk_get_type(pkey) != MBEDTLS_PK_RSA) {
+        mbedtls_pk_free(pkey);
+        return _libssh2_error(session, LIBSSH2_ERROR_FILE,
+                              "Key type not supported");
+    }
+
+    /* write method */
+    mthlen = 7;
+    mth = LIBSSH2_ALLOC(session, mthlen);
+    if(mth) {
+        memcpy(mth, "ssh-rsa", mthlen);
+    }
+    else {
+        ret = -1;
+    }
+
+    rsa = mbedtls_pk_rsa(*pkey);
+    key = gen_publickey_from_rsa(session, rsa, &keylen);
+    if(key == NULL) {
+        ret = -1;
+    }
+
+    /* write output */
+    if(ret) {
+        if(mth)
+            LIBSSH2_FREE(session, mth);
+        if(key)
+            LIBSSH2_FREE(session, key);
+    }
+    else {
+        *method = mth;
+        *method_len = mthlen;
+        *pubkeydata = key;
+        *pubkeydata_len = keylen;
+    }
+
+    return ret;
+}
+
+int
+_libssh2_mbedtls_pub_priv_keyfile(LIBSSH2_SESSION *session,
+                                 unsigned char **method,
+                                 size_t *method_len,
+                                 unsigned char **pubkeydata,
+                                 size_t *pubkeydata_len,
+                                 const char *privatekey,
+                                 const char *passphrase)
+{
+    mbedtls_pk_context pkey;
+    char buf[1024];
+    int ret;
+
+    mbedtls_pk_init(&pkey);
+    ret = mbedtls_pk_parse_keyfile(&pkey, privatekey, passphrase);
+    if(ret != 0) {
+        mbedtls_strerror(ret, (char *)buf, sizeof(buf));
+        mbedtls_pk_free(&pkey);
+        return _libssh2_error(session, LIBSSH2_ERROR_FILE, buf);
+    }
+
+    ret = _libssh2_mbedtls_pub_priv_key(session, method, method_len,
+                                       pubkeydata, pubkeydata_len, &pkey);
+
+    mbedtls_pk_free(&pkey);
+
+    return ret;
+}
+
+int
+_libssh2_mbedtls_pub_priv_keyfilememory(LIBSSH2_SESSION *session,
+                                       unsigned char **method,
+                                       size_t *method_len,
+                                       unsigned char **pubkeydata,
+                                       size_t *pubkeydata_len,
+                                       const char *privatekeydata,
+                                       size_t privatekeydata_len,
+                                       const char *passphrase)
+{
+    mbedtls_pk_context pkey;
+    char buf[1024];
+    int ret;
+    void *privatekeydata_nullterm;
+    size_t pwd_len;
+
+    /*
+    mbedtls checks in "mbedtls/pkparse.c:1184" if "key[keylen - 1] != '\0'"
+    private-key from memory will fail if the last byte is not a null byte
+    */
+    privatekeydata_nullterm = mbedtls_calloc(privatekeydata_len + 1, 1);
+    if(privatekeydata_nullterm == NULL) {
+        return -1;
+    }
+    memcpy(privatekeydata_nullterm, privatekeydata, privatekeydata_len);
+
+    mbedtls_pk_init(&pkey);
+
+    pwd_len = passphrase != NULL ? strlen((const char *)passphrase) : 0;
+    ret = mbedtls_pk_parse_key(&pkey,
+                               (unsigned char *)privatekeydata_nullterm,
+                               privatekeydata_len + 1,
+                               (const unsigned char *)passphrase, pwd_len);
+    _libssh2_mbedtls_safe_free(privatekeydata_nullterm, privatekeydata_len);
+
+    if(ret != 0) {
+        mbedtls_strerror(ret, (char *)buf, sizeof(buf));
+        mbedtls_pk_free(&pkey);
+        return _libssh2_error(session, LIBSSH2_ERROR_FILE, buf);
+    }
+
+    ret = _libssh2_mbedtls_pub_priv_key(session, method, method_len,
+                                       pubkeydata, pubkeydata_len, &pkey);
+
+    mbedtls_pk_free(&pkey);
+
+    return ret;
+}
+
+void _libssh2_init_aes_ctr(void)
+{
+    /* no implementation */
+}
+
+
+/*******************************************************************/
+/*
+ * mbedTLS backend: Diffie-Hellman functions
+ */
+
+void
+_libssh2_dh_init(_libssh2_dh_ctx *dhctx)
+{
+    *dhctx = _libssh2_mbedtls_bignum_init();    /* Random from client */
+}
+
+int
+_libssh2_dh_key_pair(_libssh2_dh_ctx *dhctx, _libssh2_bn *public,
+                     _libssh2_bn *g, _libssh2_bn *p, int group_order)
+{
+    /* Generate x and e */
+    _libssh2_mbedtls_bignum_random(*dhctx, group_order * 8 - 1, 0, -1);
+    mbedtls_mpi_exp_mod(public, g, *dhctx, p, NULL);
+    return 0;
+}
+
+int
+_libssh2_dh_secret(_libssh2_dh_ctx *dhctx, _libssh2_bn *secret,
+                   _libssh2_bn *f, _libssh2_bn *p)
+{
+    /* Compute the shared secret */
+    mbedtls_mpi_exp_mod(secret, f, *dhctx, p, NULL);
+    return 0;
+}
+
+void
+_libssh2_dh_dtor(_libssh2_dh_ctx *dhctx)
+{
+    _libssh2_mbedtls_bignum_free(*dhctx);
+    *dhctx = NULL;
+}
+
+#endif /* LIBSSH2_MBEDTLS */

+ 447 - 0
libssh2/libssh2/src/mbedtls.h

@@ -0,0 +1,447 @@
+/* Copyright (c) 2016, Art <https://github.com/wildart>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms,
+ * with or without modification, are permitted provided
+ * that the following conditions are met:
+ *
+ *   Redistributions of source code must retain the above
+ *   copyright notice, this list of conditions and the
+ *   following disclaimer.
+ *
+ *   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.
+ *
+ *   Neither the name of the copyright holder nor the names
+ *   of any other contributors may be used to endorse or
+ *   promote products derived from this software without
+ *   specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+ * CONTRIBUTORS "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 COPYRIGHT OWNER OR
+ * CONTRIBUTORS 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 <stdlib.h>
+#include <string.h>
+
+#include <mbedtls/platform.h>
+#include <mbedtls/md.h>
+#include <mbedtls/rsa.h>
+#include <mbedtls/bignum.h>
+#include <mbedtls/cipher.h>
+#include <mbedtls/entropy.h>
+#include <mbedtls/ctr_drbg.h>
+#include <mbedtls/pk.h>
+#include <mbedtls/error.h>
+
+/* Define which features are supported. */
+#define LIBSSH2_MD5             1
+
+#define LIBSSH2_HMAC_RIPEMD     1
+#define LIBSSH2_HMAC_SHA256     1
+#define LIBSSH2_HMAC_SHA512     1
+
+#define LIBSSH2_AES             1
+#define LIBSSH2_AES_CTR         1
+#define LIBSSH2_BLOWFISH        1
+#define LIBSSH2_RC4             1
+#define LIBSSH2_CAST            0
+#define LIBSSH2_3DES            1
+
+#define LIBSSH2_RSA             1
+#define LIBSSH2_DSA             0
+#define LIBSSH2_ECDSA           0
+#define LIBSSH2_ED25519         0
+
+#define MD5_DIGEST_LENGTH      16
+#define SHA_DIGEST_LENGTH      20
+#define SHA256_DIGEST_LENGTH   32
+#define SHA384_DIGEST_LENGTH   48
+#define SHA512_DIGEST_LENGTH   64
+
+#define EC_MAX_POINT_LEN ((528 * 2 / 8) + 1)
+
+#if LIBSSH2_ECDSA
+#else
+#define _libssh2_ec_key void
+#endif
+
+/*******************************************************************/
+/*
+ * mbedTLS backend: Generic functions
+ */
+
+#define libssh2_crypto_init() \
+  _libssh2_mbedtls_init()
+#define libssh2_crypto_exit() \
+  _libssh2_mbedtls_free()
+
+#define _libssh2_random(buf, len) \
+  _libssh2_mbedtls_random(buf, len)
+
+#define libssh2_prepare_iovec(vec, len)  /* Empty. */
+
+
+/*******************************************************************/
+/*
+ * mbedTLS backend: HMAC functions
+ */
+
+#define libssh2_hmac_ctx    mbedtls_md_context_t
+
+#define libssh2_hmac_ctx_init(ctx)
+#define libssh2_hmac_cleanup(pctx) \
+  mbedtls_md_free(pctx)
+#define libssh2_hmac_update(ctx, data, datalen) \
+  mbedtls_md_hmac_update(&ctx, (unsigned char *) data, datalen)
+#define libssh2_hmac_final(ctx, hash) \
+  mbedtls_md_hmac_finish(&ctx, hash)
+
+#define libssh2_hmac_sha1_init(pctx, key, keylen) \
+  _libssh2_mbedtls_hash_init(pctx, MBEDTLS_MD_SHA1, key, keylen)
+#define libssh2_hmac_md5_init(pctx, key, keylen) \
+  _libssh2_mbedtls_hash_init(pctx, MBEDTLS_MD_MD5, key, keylen)
+#define libssh2_hmac_ripemd160_init(pctx, key, keylen) \
+  _libssh2_mbedtls_hash_init(pctx, MBEDTLS_MD_RIPEMD160, key, keylen)
+#define libssh2_hmac_sha256_init(pctx, key, keylen) \
+  _libssh2_mbedtls_hash_init(pctx, MBEDTLS_MD_SHA256, key, keylen)
+#define libssh2_hmac_sha384_init(pctx, key, keylen) \
+  _libssh2_mbedtls_hash_init(pctx, MBEDTLS_MD_SHA384, key, keylen)
+#define libssh2_hmac_sha512_init(pctx, key, keylen) \
+  _libssh2_mbedtls_hash_init(pctx, MBEDTLS_MD_SHA512, key, keylen)
+
+
+/*******************************************************************/
+/*
+ * mbedTLS backend: SHA1 functions
+ */
+
+#define libssh2_sha1_ctx      mbedtls_md_context_t
+
+#define libssh2_sha1_init(pctx) \
+  _libssh2_mbedtls_hash_init(pctx, MBEDTLS_MD_SHA1, NULL, 0)
+#define libssh2_sha1_update(ctx, data, datalen) \
+  mbedtls_md_update(&ctx, (unsigned char *) data, datalen)
+#define libssh2_sha1_final(ctx, hash) \
+  _libssh2_mbedtls_hash_final(&ctx, hash)
+#define libssh2_sha1(data, datalen, hash) \
+  _libssh2_mbedtls_hash(data, datalen, MBEDTLS_MD_SHA1, hash)
+
+/*******************************************************************/
+/*
+ * mbedTLS backend: SHA256 functions
+ */
+
+#define libssh2_sha256_ctx      mbedtls_md_context_t
+
+#define libssh2_sha256_init(pctx) \
+  _libssh2_mbedtls_hash_init(pctx, MBEDTLS_MD_SHA256, NULL, 0)
+#define libssh2_sha256_update(ctx, data, datalen) \
+  mbedtls_md_update(&ctx, (unsigned char *) data, datalen)
+#define libssh2_sha256_final(ctx, hash) \
+  _libssh2_mbedtls_hash_final(&ctx, hash)
+#define libssh2_sha256(data, datalen, hash) \
+  _libssh2_mbedtls_hash(data, datalen, MBEDTLS_MD_SHA256, hash)
+
+
+/*******************************************************************/
+/*
+ * mbedTLS backend: SHA384 functions
+ */
+
+#define libssh2_sha384_ctx      mbedtls_md_context_t
+
+#define libssh2_sha384_init(pctx) \
+  _libssh2_mbedtls_hash_init(pctx, MBEDTLS_MD_SHA384, NULL, 0)
+#define libssh2_sha384_update(ctx, data, datalen) \
+  mbedtls_md_update(&ctx, (unsigned char *) data, datalen)
+#define libssh2_sha384_final(ctx, hash) \
+  _libssh2_mbedtls_hash_final(&ctx, hash)
+#define libssh2_sha384(data, datalen, hash) \
+  _libssh2_mbedtls_hash(data, datalen, MBEDTLS_MD_SHA384, hash)
+
+
+/*******************************************************************/
+/*
+ * mbedTLS backend: SHA512 functions
+ */
+
+#define libssh2_sha512_ctx      mbedtls_md_context_t
+
+#define libssh2_sha512_init(pctx) \
+  _libssh2_mbedtls_hash_init(pctx, MBEDTLS_MD_SHA512, NULL, 0)
+#define libssh2_sha512_update(ctx, data, datalen) \
+  mbedtls_md_update(&ctx, (unsigned char *) data, datalen)
+#define libssh2_sha512_final(ctx, hash) \
+  _libssh2_mbedtls_hash_final(&ctx, hash)
+#define libssh2_sha512(data, datalen, hash) \
+  _libssh2_mbedtls_hash(data, datalen, MBEDTLS_MD_SHA512, hash)
+
+
+/*******************************************************************/
+/*
+ * mbedTLS backend: MD5 functions
+ */
+
+#define libssh2_md5_ctx      mbedtls_md_context_t
+
+#define libssh2_md5_init(pctx) \
+  _libssh2_mbedtls_hash_init(pctx, MBEDTLS_MD_MD5, NULL, 0)
+#define libssh2_md5_update(ctx, data, datalen) \
+  mbedtls_md_update(&ctx, (unsigned char *) data, datalen)
+#define libssh2_md5_final(ctx, hash) \
+  _libssh2_mbedtls_hash_final(&ctx, hash)
+#define libssh2_md5(data, datalen, hash) \
+  _libssh2_mbedtls_hash(data, datalen, MBEDTLS_MD_MD5, hash)
+
+/*******************************************************************/
+/*
+ * mbedTLS backend: RSA structure
+ */
+
+#define libssh2_rsa_ctx  mbedtls_rsa_context
+
+#define _libssh2_rsa_new(rsactx, e, e_len, n, n_len, \
+                         d, d_len, p, p_len, q, q_len, \
+                         e1, e1_len, e2, e2_len, c, c_len) \
+  _libssh2_mbedtls_rsa_new(rsactx, e, e_len, n, n_len, \
+                          d, d_len, p, p_len, q, q_len, \
+                          e1, e1_len, e2, e2_len, c, c_len)
+
+#define _libssh2_rsa_new_private(rsactx, s, filename, passphrase) \
+  _libssh2_mbedtls_rsa_new_private(rsactx, s, filename, passphrase)
+
+#define _libssh2_rsa_new_private_frommemory(rsactx, s, filedata, \
+                                            filedata_len, passphrase) \
+  _libssh2_mbedtls_rsa_new_private_frommemory(rsactx, s, filedata, \
+                                             filedata_len, passphrase)
+
+#define _libssh2_rsa_sha1_sign(s, rsactx, hash, hash_len, sig, sig_len) \
+  _libssh2_mbedtls_rsa_sha1_sign(s, rsactx, hash, hash_len, sig, sig_len)
+
+#define _libssh2_rsa_sha1_verify(rsactx, sig, sig_len, m, m_len) \
+  _libssh2_mbedtls_rsa_sha1_verify(rsactx, sig, sig_len, m, m_len)
+
+#define _libssh2_rsa_free(rsactx) \
+  _libssh2_mbedtls_rsa_free(rsactx)
+
+/*
+ * mbedTLS backend: Key functions
+ */
+
+#define _libssh2_pub_priv_keyfile(s, m, m_len, p, p_len, pk, pw) \
+  _libssh2_mbedtls_pub_priv_keyfile(s, m, m_len, p, p_len, pk, pw)
+#define _libssh2_pub_priv_keyfilememory(s, m, m_len, p, p_len, \
+                                                     pk, pk_len, pw) \
+  _libssh2_mbedtls_pub_priv_keyfilememory(s, m, m_len, p, p_len, \
+                                                      pk, pk_len, pw)
+
+
+ /*******************************************************************/
+/*
+ * mbedTLS backend: Cipher Context structure
+ */
+#define _libssh2_cipher_ctx         mbedtls_cipher_context_t
+
+#define _libssh2_cipher_type(algo)  mbedtls_cipher_type_t algo
+
+#define _libssh2_cipher_aes256ctr MBEDTLS_CIPHER_AES_256_CTR
+#define _libssh2_cipher_aes192ctr MBEDTLS_CIPHER_AES_192_CTR
+#define _libssh2_cipher_aes128ctr MBEDTLS_CIPHER_AES_128_CTR
+#define _libssh2_cipher_aes256    MBEDTLS_CIPHER_AES_256_CBC
+#define _libssh2_cipher_aes192    MBEDTLS_CIPHER_AES_192_CBC
+#define _libssh2_cipher_aes128    MBEDTLS_CIPHER_AES_128_CBC
+#define _libssh2_cipher_blowfish  MBEDTLS_CIPHER_BLOWFISH_CBC
+#define _libssh2_cipher_arcfour   MBEDTLS_CIPHER_ARC4_128
+#define _libssh2_cipher_cast5     MBEDTLS_CIPHER_NULL
+#define _libssh2_cipher_3des      MBEDTLS_CIPHER_DES_EDE3_CBC
+
+/*
+ * mbedTLS backend: Cipher functions
+ */
+
+#define _libssh2_cipher_init(ctx, type, iv, secret, encrypt) \
+  _libssh2_mbedtls_cipher_init(ctx, type, iv, secret, encrypt)
+#define _libssh2_cipher_crypt(ctx, type, encrypt, block, blocklen) \
+  _libssh2_mbedtls_cipher_crypt(ctx, type, encrypt, block, blocklen)
+#define _libssh2_cipher_dtor(ctx) \
+  _libssh2_mbedtls_cipher_dtor(ctx)
+
+
+/*******************************************************************/
+/*
+ * mbedTLS backend: BigNumber Support
+ */
+
+#define _libssh2_bn_ctx int /* not used */
+#define _libssh2_bn_ctx_new() 0 /* not used */
+#define _libssh2_bn_ctx_free(bnctx) ((void)0) /* not used */
+
+#define _libssh2_bn mbedtls_mpi
+
+#define _libssh2_bn_init() \
+  _libssh2_mbedtls_bignum_init()
+#define _libssh2_bn_init_from_bin() \
+  _libssh2_mbedtls_bignum_init()
+#define _libssh2_bn_set_word(bn, word) \
+  mbedtls_mpi_lset(bn, word)
+#define _libssh2_bn_from_bin(bn, len, bin) \
+  mbedtls_mpi_read_binary(bn, bin, len)
+#define _libssh2_bn_to_bin(bn, bin) \
+  mbedtls_mpi_write_binary(bn, bin, mbedtls_mpi_size(bn))
+#define _libssh2_bn_bytes(bn) \
+  mbedtls_mpi_size(bn)
+#define _libssh2_bn_bits(bn) \
+  mbedtls_mpi_bitlen(bn)
+#define _libssh2_bn_free(bn) \
+  _libssh2_mbedtls_bignum_free(bn)
+
+
+/*******************************************************************/
+/*
+ * mbedTLS backend: Diffie-Hellman support.
+ */
+
+#define _libssh2_dh_ctx mbedtls_mpi *
+#define libssh2_dh_init(dhctx) _libssh2_dh_init(dhctx)
+#define libssh2_dh_key_pair(dhctx, public, g, p, group_order, bnctx) \
+        _libssh2_dh_key_pair(dhctx, public, g, p, group_order)
+#define libssh2_dh_secret(dhctx, secret, f, p, bnctx) \
+        _libssh2_dh_secret(dhctx, secret, f, p)
+#define libssh2_dh_dtor(dhctx) _libssh2_dh_dtor(dhctx)
+
+
+/*******************************************************************/
+/*
+ * mbedTLS backend: forward declarations
+ */
+void
+_libssh2_mbedtls_init(void);
+
+void
+_libssh2_mbedtls_free(void);
+
+int
+_libssh2_mbedtls_random(unsigned char *buf, int len);
+
+int
+_libssh2_mbedtls_cipher_init(_libssh2_cipher_ctx *ctx,
+                            _libssh2_cipher_type(type),
+                            unsigned char *iv,
+                            unsigned char *secret,
+                            int encrypt);
+int
+_libssh2_mbedtls_cipher_crypt(_libssh2_cipher_ctx *ctx,
+                             _libssh2_cipher_type(type),
+                             int encrypt,
+                             unsigned char *block,
+                             size_t blocklen);
+void
+_libssh2_mbedtls_cipher_dtor(_libssh2_cipher_ctx *ctx);
+
+int
+_libssh2_mbedtls_hash_init(mbedtls_md_context_t *ctx,
+                          mbedtls_md_type_t mdtype,
+                          const unsigned char *key, unsigned long keylen);
+
+int
+_libssh2_mbedtls_hash_final(mbedtls_md_context_t *ctx, unsigned char *hash);
+int
+_libssh2_mbedtls_hash(const unsigned char *data, unsigned long datalen,
+                      mbedtls_md_type_t mdtype, unsigned char *hash);
+
+_libssh2_bn *
+_libssh2_mbedtls_bignum_init(void);
+
+void
+_libssh2_mbedtls_bignum_free(_libssh2_bn *bn);
+
+int
+_libssh2_mbedtls_rsa_new(libssh2_rsa_ctx **rsa,
+                        const unsigned char *edata,
+                        unsigned long elen,
+                        const unsigned char *ndata,
+                        unsigned long nlen,
+                        const unsigned char *ddata,
+                        unsigned long dlen,
+                        const unsigned char *pdata,
+                        unsigned long plen,
+                        const unsigned char *qdata,
+                        unsigned long qlen,
+                        const unsigned char *e1data,
+                        unsigned long e1len,
+                        const unsigned char *e2data,
+                        unsigned long e2len,
+                        const unsigned char *coeffdata,
+                        unsigned long coefflen);
+
+int
+_libssh2_mbedtls_rsa_new_private(libssh2_rsa_ctx **rsa,
+                                LIBSSH2_SESSION *session,
+                                const char *filename,
+                                const unsigned char *passphrase);
+
+int
+_libssh2_mbedtls_rsa_new_private_frommemory(libssh2_rsa_ctx **rsa,
+                                           LIBSSH2_SESSION *session,
+                                           const char *filedata,
+                                           size_t filedata_len,
+                                           unsigned const char *passphrase);
+int
+_libssh2_mbedtls_rsa_sha1_verify(libssh2_rsa_ctx *rsa,
+                                const unsigned char *sig,
+                                unsigned long sig_len,
+                                const unsigned char *m,
+                                unsigned long m_len);
+int
+_libssh2_mbedtls_rsa_sha1_sign(LIBSSH2_SESSION *session,
+                              libssh2_rsa_ctx *rsa,
+                              const unsigned char *hash,
+                              size_t hash_len,
+                              unsigned char **signature,
+                              size_t *signature_len);
+void
+_libssh2_mbedtls_rsa_free(libssh2_rsa_ctx *rsa);
+
+int
+_libssh2_mbedtls_pub_priv_keyfile(LIBSSH2_SESSION *session,
+                                 unsigned char **method,
+                                 size_t *method_len,
+                                 unsigned char **pubkeydata,
+                                 size_t *pubkeydata_len,
+                                 const char *privatekey,
+                                 const char *passphrase);
+int
+_libssh2_mbedtls_pub_priv_keyfilememory(LIBSSH2_SESSION *session,
+                                       unsigned char **method,
+                                       size_t *method_len,
+                                       unsigned char **pubkeydata,
+                                       size_t *pubkeydata_len,
+                                       const char *privatekeydata,
+                                       size_t privatekeydata_len,
+                                       const char *passphrase);
+
+extern void
+_libssh2_dh_init(_libssh2_dh_ctx *dhctx);
+extern int
+_libssh2_dh_key_pair(_libssh2_dh_ctx *dhctx, _libssh2_bn *public,
+                    _libssh2_bn *g, _libssh2_bn *p, int group_order);
+extern int
+_libssh2_dh_secret(_libssh2_dh_ctx *dhctx, _libssh2_bn *secret,
+                  _libssh2_bn *f, _libssh2_bn *p);
+extern void
+_libssh2_dh_dtor(_libssh2_dh_ctx *dhctx);

+ 874 - 0
libssh2/libssh2/src/misc.c

@@ -0,0 +1,874 @@
+/* Copyright (c) 2004-2007 Sara Golemon <sarag@libssh2.org>
+ * Copyright (c) 2009-2019 by Daniel Stenberg
+ * Copyright (c) 2010  Simon Josefsson
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms,
+ * with or without modification, are permitted provided
+ * that the following conditions are met:
+ *
+ *   Redistributions of source code must retain the above
+ *   copyright notice, this list of conditions and the
+ *   following disclaimer.
+ *
+ *   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.
+ *
+ *   Neither the name of the copyright holder nor the names
+ *   of any other contributors may be used to endorse or
+ *   promote products derived from this software without
+ *   specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+ * CONTRIBUTORS "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 COPYRIGHT OWNER OR
+ * CONTRIBUTORS 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 "libssh2_priv.h"
+#include "misc.h"
+#include "blf.h"
+
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
+#ifdef HAVE_SYS_TIME_H
+#include <sys/time.h>
+#endif
+
+#if defined(HAVE_DECL_SECUREZEROMEMORY) && HAVE_DECL_SECUREZEROMEMORY
+#ifdef HAVE_WINDOWS_H
+#include <windows.h>
+#endif
+#endif
+
+#include <stdio.h>
+#include <errno.h>
+
+int _libssh2_error_flags(LIBSSH2_SESSION* session, int errcode,
+                         const char *errmsg, int errflags)
+{
+    if(session->err_flags & LIBSSH2_ERR_FLAG_DUP)
+        LIBSSH2_FREE(session, (char *)session->err_msg);
+
+    session->err_code = errcode;
+    session->err_flags = 0;
+
+    if((errmsg != NULL) && ((errflags & LIBSSH2_ERR_FLAG_DUP) != 0)) {
+        size_t len = strlen(errmsg);
+        char *copy = LIBSSH2_ALLOC(session, len + 1);
+        if(copy) {
+            memcpy(copy, errmsg, len + 1);
+            session->err_flags = LIBSSH2_ERR_FLAG_DUP;
+            session->err_msg = copy;
+        }
+        else
+            /* Out of memory: this code path is very unlikely */
+            session->err_msg = "former error forgotten (OOM)";
+    }
+    else
+        session->err_msg = errmsg;
+
+#ifdef LIBSSH2DEBUG
+    if((errcode == LIBSSH2_ERROR_EAGAIN) && !session->api_block_mode)
+        /* if this is EAGAIN and we're in non-blocking mode, don't generate
+           a debug output for this */
+        return errcode;
+    _libssh2_debug(session, LIBSSH2_TRACE_ERROR, "%d - %s", session->err_code,
+                   session->err_msg);
+#endif
+
+    return errcode;
+}
+
+int _libssh2_error(LIBSSH2_SESSION* session, int errcode, const char *errmsg)
+{
+    return _libssh2_error_flags(session, errcode, errmsg, 0);
+}
+
+#ifdef WIN32
+static int wsa2errno(void)
+{
+    switch(WSAGetLastError()) {
+    case WSAEWOULDBLOCK:
+        return EAGAIN;
+
+    case WSAENOTSOCK:
+        return EBADF;
+
+    case WSAEINTR:
+        return EINTR;
+
+    default:
+        /* It is most important to ensure errno does not stay at EAGAIN
+         * when a different error occurs so just set errno to a generic
+         * error */
+        return EIO;
+    }
+}
+#endif
+
+/* _libssh2_recv
+ *
+ * Replacement for the standard recv, return -errno on failure.
+ */
+ssize_t
+_libssh2_recv(libssh2_socket_t sock, void *buffer, size_t length,
+              int flags, void **abstract)
+{
+    ssize_t rc;
+
+    (void) abstract;
+
+    rc = recv(sock, buffer, length, flags);
+#ifdef WIN32
+    if(rc < 0)
+        return -wsa2errno();
+#elif defined(__VMS)
+    if(rc < 0) {
+        if(errno == EWOULDBLOCK)
+            return -EAGAIN;
+        else
+            return -errno;
+    }
+#else
+    if(rc < 0) {
+        /* Sometimes the first recv() function call sets errno to ENOENT on
+           Solaris and HP-UX */
+        if(errno == ENOENT)
+            return -EAGAIN;
+        else
+            return -errno;
+    }
+#endif
+    return rc;
+}
+
+/* _libssh2_send
+ *
+ * Replacement for the standard send, return -errno on failure.
+ */
+ssize_t
+_libssh2_send(libssh2_socket_t sock, const void *buffer, size_t length,
+              int flags, void **abstract)
+{
+    ssize_t rc;
+
+    (void) abstract;
+
+    rc = send(sock, buffer, length, flags);
+#ifdef WIN32
+    if(rc < 0)
+        return -wsa2errno();
+#elif defined(__VMS)
+    if(rc < 0) {
+        if(errno == EWOULDBLOCK)
+            return -EAGAIN;
+        else
+            return -errno;
+    }
+#else
+    if(rc < 0)
+        return -errno;
+#endif
+    return rc;
+}
+
+/* libssh2_ntohu32
+ */
+unsigned int
+_libssh2_ntohu32(const unsigned char *buf)
+{
+    return (buf[0] << 24) | (buf[1] << 16) | (buf[2] << 8) | buf[3];
+}
+
+
+/* _libssh2_ntohu64
+ */
+libssh2_uint64_t
+_libssh2_ntohu64(const unsigned char *buf)
+{
+    unsigned long msl, lsl;
+
+    msl = ((libssh2_uint64_t)buf[0] << 24) | ((libssh2_uint64_t)buf[1] << 16)
+        | ((libssh2_uint64_t)buf[2] << 8) | (libssh2_uint64_t)buf[3];
+    lsl = ((libssh2_uint64_t)buf[4] << 24) | ((libssh2_uint64_t)buf[5] << 16)
+        | ((libssh2_uint64_t)buf[6] << 8) | (libssh2_uint64_t)buf[7];
+
+    return ((libssh2_uint64_t)msl <<32) | lsl;
+}
+
+/* _libssh2_htonu32
+ */
+void
+_libssh2_htonu32(unsigned char *buf, uint32_t value)
+{
+    buf[0] = (value >> 24) & 0xFF;
+    buf[1] = (value >> 16) & 0xFF;
+    buf[2] = (value >> 8) & 0xFF;
+    buf[3] = value & 0xFF;
+}
+
+/* _libssh2_store_u32
+ */
+void _libssh2_store_u32(unsigned char **buf, uint32_t value)
+{
+    _libssh2_htonu32(*buf, value);
+    *buf += sizeof(uint32_t);
+}
+
+/* _libssh2_store_str
+ */
+void _libssh2_store_str(unsigned char **buf, const char *str, size_t len)
+{
+    _libssh2_store_u32(buf, (uint32_t)len);
+    if(len) {
+        memcpy(*buf, str, len);
+        *buf += len;
+    }
+}
+
+/* Base64 Conversion */
+
+static const short base64_reverse_table[256] = {
+    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 62, -1, -1, -1, 63,
+    52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, -1, -1, -1,
+    -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
+    15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1,
+    -1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
+    41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, -1, -1, -1, -1, -1,
+    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
+};
+
+/* libssh2_base64_decode
+ *
+ * Decode a base64 chunk and store it into a newly alloc'd buffer
+ */
+LIBSSH2_API int
+libssh2_base64_decode(LIBSSH2_SESSION *session, char **data,
+                      unsigned int *datalen, const char *src,
+                      unsigned int src_len)
+{
+    unsigned char *s, *d;
+    short v;
+    int i = 0, len = 0;
+
+    *data = LIBSSH2_ALLOC(session, (3 * src_len / 4) + 1);
+    d = (unsigned char *) *data;
+    if(!d) {
+        return _libssh2_error(session, LIBSSH2_ERROR_ALLOC,
+                              "Unable to allocate memory for base64 decoding");
+    }
+
+    for(s = (unsigned char *) src; ((char *) s) < (src + src_len); s++) {
+        v = base64_reverse_table[*s];
+        if(v < 0)
+            continue;
+        switch(i % 4) {
+        case 0:
+            d[len] = (unsigned char)(v << 2);
+            break;
+        case 1:
+            d[len++] |= v >> 4;
+            d[len] = (unsigned char)(v << 4);
+            break;
+        case 2:
+            d[len++] |= v >> 2;
+            d[len] = (unsigned char)(v << 6);
+            break;
+        case 3:
+            d[len++] |= v;
+            break;
+        }
+        i++;
+    }
+    if((i % 4) == 1) {
+        /* Invalid -- We have a byte which belongs exclusively to a partial
+           octet */
+        LIBSSH2_FREE(session, *data);
+        *data = NULL;
+        return _libssh2_error(session, LIBSSH2_ERROR_INVAL, "Invalid base64");
+    }
+
+    *datalen = len;
+    return 0;
+}
+
+/* ---- Base64 Encoding/Decoding Table --- */
+static const char table64[]=
+  "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
+
+/*
+ * _libssh2_base64_encode()
+ *
+ * Returns the length of the newly created base64 string. The third argument
+ * is a pointer to an allocated area holding the base64 data. If something
+ * went wrong, 0 is returned.
+ *
+ */
+size_t _libssh2_base64_encode(LIBSSH2_SESSION *session,
+                              const char *inp, size_t insize, char **outptr)
+{
+    unsigned char ibuf[3];
+    unsigned char obuf[4];
+    int i;
+    int inputparts;
+    char *output;
+    char *base64data;
+    const char *indata = inp;
+
+    *outptr = NULL; /* set to NULL in case of failure before we reach the
+                       end */
+
+    if(0 == insize)
+        insize = strlen(indata);
+
+    base64data = output = LIBSSH2_ALLOC(session, insize * 4 / 3 + 4);
+    if(NULL == output)
+        return 0;
+
+    while(insize > 0) {
+        for(i = inputparts = 0; i < 3; i++) {
+            if(insize > 0) {
+                inputparts++;
+                ibuf[i] = *indata;
+                indata++;
+                insize--;
+            }
+            else
+                ibuf[i] = 0;
+        }
+
+        obuf[0] = (unsigned char)  ((ibuf[0] & 0xFC) >> 2);
+        obuf[1] = (unsigned char) (((ibuf[0] & 0x03) << 4) | \
+                                   ((ibuf[1] & 0xF0) >> 4));
+        obuf[2] = (unsigned char) (((ibuf[1] & 0x0F) << 2) | \
+                                   ((ibuf[2] & 0xC0) >> 6));
+        obuf[3] = (unsigned char)   (ibuf[2] & 0x3F);
+
+        switch(inputparts) {
+        case 1: /* only one byte read */
+            snprintf(output, 5, "%c%c==",
+                     table64[obuf[0]],
+                     table64[obuf[1]]);
+            break;
+        case 2: /* two bytes read */
+            snprintf(output, 5, "%c%c%c=",
+                     table64[obuf[0]],
+                     table64[obuf[1]],
+                     table64[obuf[2]]);
+            break;
+        default:
+            snprintf(output, 5, "%c%c%c%c",
+                     table64[obuf[0]],
+                     table64[obuf[1]],
+                     table64[obuf[2]],
+                     table64[obuf[3]]);
+            break;
+        }
+        output += 4;
+    }
+    *output = 0;
+    *outptr = base64data; /* make it return the actual data memory */
+
+    return strlen(base64data); /* return the length of the new data */
+}
+/* ---- End of Base64 Encoding ---- */
+
+LIBSSH2_API void
+libssh2_free(LIBSSH2_SESSION *session, void *ptr)
+{
+    LIBSSH2_FREE(session, ptr);
+}
+
+#ifdef LIBSSH2DEBUG
+#include <stdarg.h>
+
+LIBSSH2_API int
+libssh2_trace(LIBSSH2_SESSION * session, int bitmask)
+{
+    session->showmask = bitmask;
+    return 0;
+}
+
+LIBSSH2_API int
+libssh2_trace_sethandler(LIBSSH2_SESSION *session, void *handler_context,
+                         libssh2_trace_handler_func callback)
+{
+    session->tracehandler = callback;
+    session->tracehandler_context = handler_context;
+    return 0;
+}
+
+void
+_libssh2_debug(LIBSSH2_SESSION * session, int context, const char *format, ...)
+{
+    char buffer[1536];
+    int len, msglen, buflen = sizeof(buffer);
+    va_list vargs;
+    struct timeval now;
+    static int firstsec;
+    static const char *const contexts[] = {
+        "Unknown",
+        "Transport",
+        "Key Ex",
+        "Userauth",
+        "Conn",
+        "SCP",
+        "SFTP",
+        "Failure Event",
+        "Publickey",
+        "Socket",
+    };
+    const char *contexttext = contexts[0];
+    unsigned int contextindex;
+
+    if(!(session->showmask & context)) {
+        /* no such output asked for */
+        return;
+    }
+
+    /* Find the first matching context string for this message */
+    for(contextindex = 0; contextindex < ARRAY_SIZE(contexts);
+         contextindex++) {
+        if((context & (1 << contextindex)) != 0) {
+            contexttext = contexts[contextindex];
+            break;
+        }
+    }
+
+    _libssh2_gettimeofday(&now, NULL);
+    if(!firstsec) {
+        firstsec = now.tv_sec;
+    }
+    now.tv_sec -= firstsec;
+
+    len = snprintf(buffer, buflen, "[libssh2] %d.%06d %s: ",
+                   (int)now.tv_sec, (int)now.tv_usec, contexttext);
+
+    if(len >= buflen)
+        msglen = buflen - 1;
+    else {
+        buflen -= len;
+        msglen = len;
+        va_start(vargs, format);
+        len = vsnprintf(buffer + msglen, buflen, format, vargs);
+        va_end(vargs);
+        msglen += len < buflen ? len : buflen - 1;
+    }
+
+    if(session->tracehandler)
+        (session->tracehandler)(session, session->tracehandler_context, buffer,
+                                msglen);
+    else
+        fprintf(stderr, "%s\n", buffer);
+}
+
+#else
+LIBSSH2_API int
+libssh2_trace(LIBSSH2_SESSION * session, int bitmask)
+{
+    (void) session;
+    (void) bitmask;
+    return 0;
+}
+
+LIBSSH2_API int
+libssh2_trace_sethandler(LIBSSH2_SESSION *session, void *handler_context,
+                         libssh2_trace_handler_func callback)
+{
+    (void) session;
+    (void) handler_context;
+    (void) callback;
+    return 0;
+}
+#endif
+
+/* init the list head */
+void _libssh2_list_init(struct list_head *head)
+{
+    head->first = head->last = NULL;
+}
+
+/* add a node to the list */
+void _libssh2_list_add(struct list_head *head,
+                       struct list_node *entry)
+{
+    /* store a pointer to the head */
+    entry->head = head;
+
+    /* we add this entry at the "top" so it has no next */
+    entry->next = NULL;
+
+    /* make our prev point to what the head thinks is last */
+    entry->prev = head->last;
+
+    /* and make head's last be us now */
+    head->last = entry;
+
+    /* make sure our 'prev' node points to us next */
+    if(entry->prev)
+        entry->prev->next = entry;
+    else
+        head->first = entry;
+}
+
+/* return the "first" node in the list this head points to */
+void *_libssh2_list_first(struct list_head *head)
+{
+    return head->first;
+}
+
+/* return the next node in the list */
+void *_libssh2_list_next(struct list_node *node)
+{
+    return node->next;
+}
+
+/* return the prev node in the list */
+void *_libssh2_list_prev(struct list_node *node)
+{
+    return node->prev;
+}
+
+/* remove this node from the list */
+void _libssh2_list_remove(struct list_node *entry)
+{
+    if(entry->prev)
+        entry->prev->next = entry->next;
+    else
+        entry->head->first = entry->next;
+
+    if(entry->next)
+        entry->next->prev = entry->prev;
+    else
+        entry->head->last = entry->prev;
+}
+
+#if 0
+/* insert a node before the given 'after' entry */
+void _libssh2_list_insert(struct list_node *after, /* insert before this */
+                          struct list_node *entry)
+{
+    /* 'after' is next to 'entry' */
+    bentry->next = after;
+
+    /* entry's prev is then made to be the prev after current has */
+    entry->prev = after->prev;
+
+    /* the node that is now before 'entry' was previously before 'after'
+       and must be made to point to 'entry' correctly */
+    if(entry->prev)
+        entry->prev->next = entry;
+    else
+      /* there was no node before this, so we make sure we point the head
+         pointer to this node */
+      after->head->first = entry;
+
+    /* after's prev entry points back to entry */
+    after->prev = entry;
+
+    /* after's next entry is still the same as before */
+
+    /* entry's head is the same as after's */
+    entry->head = after->head;
+}
+
+#endif
+
+/* this define is defined in misc.h for the correct platforms */
+#ifdef LIBSSH2_GETTIMEOFDAY_WIN32
+/*
+ * gettimeofday
+ * Implementation according to:
+ * The Open Group Base Specifications Issue 6
+ * IEEE Std 1003.1, 2004 Edition
+ */
+
+/*
+ *  THIS SOFTWARE IS NOT COPYRIGHTED
+ *
+ *  This source code is offered for use in the public domain. You may
+ *  use, modify or distribute it freely.
+ *
+ *  This code is distributed in the hope that it will be useful but
+ *  WITHOUT ANY WARRANTY. ALL WARRANTIES, EXPRESS OR IMPLIED ARE HEREBY
+ *  DISCLAIMED. This includes but is not limited to warranties of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ *  Contributed by:
+ *  Danny Smith <dannysmith@users.sourceforge.net>
+ */
+
+/* Offset between 1/1/1601 and 1/1/1970 in 100 nanosec units */
+#define _W32_FT_OFFSET (116444736000000000)
+
+int __cdecl _libssh2_gettimeofday(struct timeval *tp, void *tzp)
+{
+    union {
+        unsigned __int64 ns100; /*time since 1 Jan 1601 in 100ns units */
+        FILETIME ft;
+    } _now;
+    (void)tzp;
+    if(tp) {
+        GetSystemTimeAsFileTime(&_now.ft);
+        tp->tv_usec = (long)((_now.ns100 / 10) % 1000000);
+        tp->tv_sec = (long)((_now.ns100 - _W32_FT_OFFSET) / 10000000);
+    }
+    /* Always return 0 as per Open Group Base Specifications Issue 6.
+       Do not set errno on error.  */
+    return 0;
+}
+
+
+#endif
+
+void *_libssh2_calloc(LIBSSH2_SESSION* session, size_t size)
+{
+    void *p = LIBSSH2_ALLOC(session, size);
+    if(p) {
+        memset(p, 0, size);
+    }
+    return p;
+}
+
+/* XOR operation on buffers input1 and input2, result in output.
+   It is safe to use an input buffer as the output buffer. */
+void _libssh2_xor_data(unsigned char *output,
+                       const unsigned char *input1,
+                       const unsigned char *input2,
+                       size_t length)
+{
+    size_t i;
+
+    for(i = 0; i < length; i++)
+        *output++ = *input1++ ^ *input2++;
+}
+
+/* Increments an AES CTR buffer to prepare it for use with the
+   next AES block. */
+void _libssh2_aes_ctr_increment(unsigned char *ctr,
+                                size_t length)
+{
+    unsigned char *pc;
+    unsigned int val, carry;
+
+    pc = ctr + length - 1;
+    carry = 1;
+
+    while(pc >= ctr) {
+        val = (unsigned int)*pc + carry;
+        *pc-- = val & 0xFF;
+        carry = val >> 8;
+    }
+}
+
+#ifdef WIN32
+static void * (__cdecl * const volatile memset_libssh)(void *, int, size_t) =
+    memset;
+#else
+static void * (* const volatile memset_libssh)(void *, int, size_t) = memset;
+#endif
+
+void _libssh2_explicit_zero(void *buf, size_t size)
+{
+#if defined(HAVE_DECL_SECUREZEROMEMORY) && HAVE_DECL_SECUREZEROMEMORY
+    SecureZeroMemory(buf, size);
+    (void)memset_libssh; /* Silence unused variable warning */
+#elif defined(HAVE_MEMSET_S)
+    (void)memset_s(buf, size, 0, size);
+    (void)memset_libssh; /* Silence unused variable warning */
+#else
+    memset_libssh(buf, 0, size);
+#endif
+}
+
+/* String buffer */
+
+struct string_buf* _libssh2_string_buf_new(LIBSSH2_SESSION *session)
+{
+    struct string_buf *ret;
+
+    ret = _libssh2_calloc(session, sizeof(*ret));
+    if(ret == NULL)
+        return NULL;
+
+    return ret;
+}
+
+void _libssh2_string_buf_free(LIBSSH2_SESSION *session, struct string_buf *buf)
+{
+    if(buf == NULL)
+        return;
+
+    if(buf->data != NULL)
+        LIBSSH2_FREE(session, buf->data);
+
+    LIBSSH2_FREE(session, buf);
+    buf = NULL;
+}
+
+int _libssh2_get_u32(struct string_buf *buf, uint32_t *out)
+{
+    if(!_libssh2_check_length(buf, 4)) {
+        return -1;
+    }
+
+    *out = _libssh2_ntohu32(buf->dataptr);
+    buf->dataptr += 4;
+    return 0;
+}
+
+int _libssh2_get_u64(struct string_buf *buf, libssh2_uint64_t *out)
+{
+    if(!_libssh2_check_length(buf, 8)) {
+        return -1;
+    }
+
+    *out = _libssh2_ntohu64(buf->dataptr);
+    buf->dataptr += 8;
+    return 0;
+}
+
+int _libssh2_match_string(struct string_buf *buf, const char *match)
+{
+    unsigned char *out;
+    size_t len = 0;
+    if(_libssh2_get_string(buf, &out, &len) || len != strlen(match) ||
+        strncmp((char *)out, match, strlen(match)) != 0) {
+        return -1;
+    }
+    return 0;
+}
+
+int _libssh2_get_string(struct string_buf *buf, unsigned char **outbuf,
+                        size_t *outlen)
+{
+    uint32_t data_len;
+    if(_libssh2_get_u32(buf, &data_len) != 0) {
+        return -1;
+    }
+    if(!_libssh2_check_length(buf, data_len)) {
+        return -1;
+    }
+    *outbuf = buf->dataptr;
+    buf->dataptr += data_len;
+
+    if(outlen)
+        *outlen = (size_t)data_len;
+
+    return 0;
+}
+
+int _libssh2_copy_string(LIBSSH2_SESSION *session, struct string_buf *buf,
+                         unsigned char **outbuf, size_t *outlen)
+{
+    size_t str_len;
+    unsigned char *str;
+
+    if(_libssh2_get_string(buf, &str, &str_len)) {
+        return -1;
+    }
+
+    *outbuf = LIBSSH2_ALLOC(session, str_len);
+    if(*outbuf) {
+        memcpy(*outbuf, str, str_len);
+    }
+    else {
+        return -1;
+    }
+
+    if(outlen)
+        *outlen = str_len;
+
+    return 0;
+}
+
+int _libssh2_get_bignum_bytes(struct string_buf *buf, unsigned char **outbuf,
+                              size_t *outlen)
+{
+    uint32_t data_len;
+    uint32_t bn_len;
+    unsigned char *bnptr;
+
+    if(_libssh2_get_u32(buf, &data_len)) {
+        return -1;
+    }
+    if(!_libssh2_check_length(buf, data_len)) {
+        return -1;
+    }
+
+    bn_len = data_len;
+    bnptr = buf->dataptr;
+
+    /* trim leading zeros */
+    while(bn_len > 0 && *bnptr == 0x00) {
+        bn_len--;
+        bnptr++;
+    }
+
+    *outbuf = bnptr;
+    buf->dataptr += data_len;
+
+    if(outlen)
+        *outlen = (size_t)bn_len;
+
+    return 0;
+}
+
+/* Given the current location in buf, _libssh2_check_length ensures
+   callers can read the next len number of bytes out of the buffer
+   before reading the buffer content */
+
+int _libssh2_check_length(struct string_buf *buf, size_t len)
+{
+    unsigned char *endp = &buf->data[buf->len];
+    size_t left = endp - buf->dataptr;
+    return ((len <= left) && (left <= buf->len));
+}
+
+/* Wrappers */
+
+int _libssh2_bcrypt_pbkdf(const char *pass,
+                          size_t passlen,
+                          const uint8_t *salt,
+                          size_t saltlen,
+                          uint8_t *key,
+                          size_t keylen,
+                          unsigned int rounds)
+{
+    /* defined in bcrypt_pbkdf.c */
+    return bcrypt_pbkdf(pass,
+                        passlen,
+                        salt,
+                        saltlen,
+                        key,
+                        keylen,
+                        rounds);
+}

+ 125 - 0
libssh2/libssh2/src/misc.h

@@ -0,0 +1,125 @@
+#ifndef __LIBSSH2_MISC_H
+#define __LIBSSH2_MISC_H
+/* Copyright (c) 2009-2019 by Daniel Stenberg
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms,
+ * with or without modification, are permitted provided
+ * that the following conditions are met:
+ *
+ *   Redistributions of source code must retain the above
+ *   copyright notice, this list of conditions and the
+ *   following disclaimer.
+ *
+ *   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.
+ *
+ *   Neither the name of the copyright holder nor the names
+ *   of any other contributors may be used to endorse or
+ *   promote products derived from this software without
+ *   specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+ * CONTRIBUTORS "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 COPYRIGHT OWNER OR
+ * CONTRIBUTORS 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.
+ */
+
+struct list_head {
+    struct list_node *last;
+    struct list_node *first;
+};
+
+struct list_node {
+    struct list_node *next;
+    struct list_node *prev;
+    struct list_head *head;
+};
+
+struct string_buf {
+    unsigned char *data;
+    unsigned char *dataptr;
+    size_t len;
+};
+
+int _libssh2_error_flags(LIBSSH2_SESSION* session, int errcode,
+                         const char *errmsg, int errflags);
+int _libssh2_error(LIBSSH2_SESSION* session, int errcode, const char *errmsg);
+
+void _libssh2_list_init(struct list_head *head);
+
+/* add a node last in the list */
+void _libssh2_list_add(struct list_head *head,
+                       struct list_node *entry);
+
+/* return the "first" node in the list this head points to */
+void *_libssh2_list_first(struct list_head *head);
+
+/* return the next node in the list */
+void *_libssh2_list_next(struct list_node *node);
+
+/* return the prev node in the list */
+void *_libssh2_list_prev(struct list_node *node);
+
+/* remove this node from the list */
+void _libssh2_list_remove(struct list_node *entry);
+
+size_t _libssh2_base64_encode(LIBSSH2_SESSION *session,
+                              const char *inp, size_t insize, char **outptr);
+
+unsigned int _libssh2_ntohu32(const unsigned char *buf);
+libssh2_uint64_t _libssh2_ntohu64(const unsigned char *buf);
+void _libssh2_htonu32(unsigned char *buf, uint32_t val);
+void _libssh2_store_u32(unsigned char **buf, uint32_t value);
+void _libssh2_store_str(unsigned char **buf, const char *str, size_t len);
+void *_libssh2_calloc(LIBSSH2_SESSION *session, size_t size);
+void _libssh2_explicit_zero(void *buf, size_t size);
+
+struct string_buf* _libssh2_string_buf_new(LIBSSH2_SESSION *session);
+void _libssh2_string_buf_free(LIBSSH2_SESSION *session,
+                              struct string_buf *buf);
+int _libssh2_get_u32(struct string_buf *buf, uint32_t *out);
+int _libssh2_get_u64(struct string_buf *buf, libssh2_uint64_t *out);
+int _libssh2_match_string(struct string_buf *buf, const char *match);
+int _libssh2_get_string(struct string_buf *buf, unsigned char **outbuf,
+                        size_t *outlen);
+int _libssh2_copy_string(LIBSSH2_SESSION* session, struct string_buf *buf,
+                         unsigned char **outbuf, size_t *outlen);
+int _libssh2_get_bignum_bytes(struct string_buf *buf, unsigned char **outbuf,
+                              size_t *outlen);
+int _libssh2_check_length(struct string_buf *buf, size_t requested_len);
+
+#if defined(LIBSSH2_WIN32) && !defined(__MINGW32__) && !defined(__CYGWIN__)
+/* provide a private one */
+#undef HAVE_GETTIMEOFDAY
+int __cdecl _libssh2_gettimeofday(struct timeval *tp, void *tzp);
+#define HAVE_LIBSSH2_GETTIMEOFDAY
+#define LIBSSH2_GETTIMEOFDAY_WIN32 /* enable the win32 implementation */
+#else
+#ifdef HAVE_GETTIMEOFDAY
+#define _libssh2_gettimeofday(x,y) gettimeofday(x,y)
+#define HAVE_LIBSSH2_GETTIMEOFDAY
+#endif
+#endif
+
+void _libssh2_xor_data(unsigned char *output,
+                       const unsigned char *input1,
+                       const unsigned char *input2,
+                       size_t length);
+
+void _libssh2_aes_ctr_increment(unsigned char *ctr, size_t length);
+
+#endif /* _LIBSSH2_MISC_H */

+ 3240 - 0
libssh2/libssh2/src/openssl.c

@@ -0,0 +1,3240 @@
+/* Copyright (C) 2009, 2010 Simon Josefsson
+ * Copyright (C) 2006, 2007 The Written Word, Inc.  All rights reserved.
+ * Copyright (c) 2004-2006, Sara Golemon <sarag@libssh2.org>
+ *
+ * Author: Simon Josefsson
+ *
+ * Redistribution and use in source and binary forms,
+ * with or without modification, are permitted provided
+ * that the following conditions are met:
+ *
+ *   Redistributions of source code must retain the above
+ *   copyright notice, this list of conditions and the
+ *   following disclaimer.
+ *
+ *   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.
+ *
+ *   Neither the name of the copyright holder nor the names
+ *   of any other contributors may be used to endorse or
+ *   promote products derived from this software without
+ *   specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+ * CONTRIBUTORS "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 COPYRIGHT OWNER OR
+ * CONTRIBUTORS 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 "libssh2_priv.h"
+
+#ifdef LIBSSH2_OPENSSL /* compile only if we build with openssl */
+
+#include <string.h>
+#include "misc.h"
+
+#ifndef EVP_MAX_BLOCK_LENGTH
+#define EVP_MAX_BLOCK_LENGTH 32
+#endif
+
+int
+read_openssh_private_key_from_memory(void **key_ctx, LIBSSH2_SESSION *session,
+                                     const char *key_type,
+                                     const char *filedata,
+                                     size_t filedata_len,
+                                     unsigned const char *passphrase);
+
+static unsigned char *
+write_bn(unsigned char *buf, const BIGNUM *bn, int bn_bytes)
+{
+    unsigned char *p = buf;
+
+    /* Left space for bn size which will be written below. */
+    p += 4;
+
+    *p = 0;
+    BN_bn2bin(bn, p + 1);
+    if(!(*(p + 1) & 0x80)) {
+        memmove(p, p + 1, --bn_bytes);
+    }
+    _libssh2_htonu32(p - 4, bn_bytes);  /* Post write bn size. */
+
+    return p + bn_bytes;
+}
+
+int
+_libssh2_rsa_new(libssh2_rsa_ctx ** rsa,
+                 const unsigned char *edata,
+                 unsigned long elen,
+                 const unsigned char *ndata,
+                 unsigned long nlen,
+                 const unsigned char *ddata,
+                 unsigned long dlen,
+                 const unsigned char *pdata,
+                 unsigned long plen,
+                 const unsigned char *qdata,
+                 unsigned long qlen,
+                 const unsigned char *e1data,
+                 unsigned long e1len,
+                 const unsigned char *e2data,
+                 unsigned long e2len,
+                 const unsigned char *coeffdata, unsigned long coefflen)
+{
+    BIGNUM * e;
+    BIGNUM * n;
+    BIGNUM * d = 0;
+    BIGNUM * p = 0;
+    BIGNUM * q = 0;
+    BIGNUM * dmp1 = 0;
+    BIGNUM * dmq1 = 0;
+    BIGNUM * iqmp = 0;
+
+    e = BN_new();
+    BN_bin2bn(edata, elen, e);
+
+    n = BN_new();
+    BN_bin2bn(ndata, nlen, n);
+
+    if(ddata) {
+        d = BN_new();
+        BN_bin2bn(ddata, dlen, d);
+
+        p = BN_new();
+        BN_bin2bn(pdata, plen, p);
+
+        q = BN_new();
+        BN_bin2bn(qdata, qlen, q);
+
+        dmp1 = BN_new();
+        BN_bin2bn(e1data, e1len, dmp1);
+
+        dmq1 = BN_new();
+        BN_bin2bn(e2data, e2len, dmq1);
+
+        iqmp = BN_new();
+        BN_bin2bn(coeffdata, coefflen, iqmp);
+    }
+
+    *rsa = RSA_new();
+#ifdef HAVE_OPAQUE_STRUCTS
+    RSA_set0_key(*rsa, n, e, d);
+#else
+    (*rsa)->e = e;
+    (*rsa)->n = n;
+    (*rsa)->d = d;
+#endif
+
+#ifdef HAVE_OPAQUE_STRUCTS
+    RSA_set0_factors(*rsa, p, q);
+#else
+    (*rsa)->p = p;
+    (*rsa)->q = q;
+#endif
+
+#ifdef HAVE_OPAQUE_STRUCTS
+    RSA_set0_crt_params(*rsa, dmp1, dmq1, iqmp);
+#else
+    (*rsa)->dmp1 = dmp1;
+    (*rsa)->dmq1 = dmq1;
+    (*rsa)->iqmp = iqmp;
+#endif
+    return 0;
+}
+
+int
+_libssh2_rsa_sha1_verify(libssh2_rsa_ctx * rsactx,
+                         const unsigned char *sig,
+                         unsigned long sig_len,
+                         const unsigned char *m, unsigned long m_len)
+{
+    unsigned char hash[SHA_DIGEST_LENGTH];
+    int ret;
+
+    if(_libssh2_sha1(m, m_len, hash))
+        return -1; /* failure */
+    ret = RSA_verify(NID_sha1, hash, SHA_DIGEST_LENGTH,
+                     (unsigned char *) sig, sig_len, rsactx);
+    return (ret == 1) ? 0 : -1;
+}
+
+#if LIBSSH2_DSA
+int
+_libssh2_dsa_new(libssh2_dsa_ctx ** dsactx,
+                 const unsigned char *p,
+                 unsigned long p_len,
+                 const unsigned char *q,
+                 unsigned long q_len,
+                 const unsigned char *g,
+                 unsigned long g_len,
+                 const unsigned char *y,
+                 unsigned long y_len,
+                 const unsigned char *x, unsigned long x_len)
+{
+    BIGNUM * p_bn;
+    BIGNUM * q_bn;
+    BIGNUM * g_bn;
+    BIGNUM * pub_key;
+    BIGNUM * priv_key = NULL;
+
+    p_bn = BN_new();
+    BN_bin2bn(p, p_len, p_bn);
+
+    q_bn = BN_new();
+    BN_bin2bn(q, q_len, q_bn);
+
+    g_bn = BN_new();
+    BN_bin2bn(g, g_len, g_bn);
+
+    pub_key = BN_new();
+    BN_bin2bn(y, y_len, pub_key);
+
+    if(x_len) {
+        priv_key = BN_new();
+        BN_bin2bn(x, x_len, priv_key);
+    }
+
+    *dsactx = DSA_new();
+
+#ifdef HAVE_OPAQUE_STRUCTS
+    DSA_set0_pqg(*dsactx, p_bn, q_bn, g_bn);
+#else
+    (*dsactx)->p = p_bn;
+    (*dsactx)->g = g_bn;
+    (*dsactx)->q = q_bn;
+#endif
+
+#ifdef HAVE_OPAQUE_STRUCTS
+    DSA_set0_key(*dsactx, pub_key, priv_key);
+#else
+    (*dsactx)->pub_key = pub_key;
+    (*dsactx)->priv_key = priv_key;
+#endif
+    return 0;
+}
+
+int
+_libssh2_dsa_sha1_verify(libssh2_dsa_ctx * dsactx,
+                         const unsigned char *sig,
+                         const unsigned char *m, unsigned long m_len)
+{
+    unsigned char hash[SHA_DIGEST_LENGTH];
+    DSA_SIG * dsasig;
+    BIGNUM * r;
+    BIGNUM * s;
+    int ret = -1;
+
+    r = BN_new();
+    BN_bin2bn(sig, 20, r);
+    s = BN_new();
+    BN_bin2bn(sig + 20, 20, s);
+
+    dsasig = DSA_SIG_new();
+#ifdef HAVE_OPAQUE_STRUCTS
+    DSA_SIG_set0(dsasig, r, s);
+#else
+    dsasig->r = r;
+    dsasig->s = s;
+#endif
+    if(!_libssh2_sha1(m, m_len, hash))
+        /* _libssh2_sha1() succeeded */
+        ret = DSA_do_verify(hash, SHA_DIGEST_LENGTH, dsasig, dsactx);
+
+    DSA_SIG_free(dsasig);
+
+    return (ret == 1) ? 0 : -1;
+}
+#endif /* LIBSSH_DSA */
+
+#if LIBSSH2_ECDSA
+
+/* _libssh2_ecdsa_key_get_curve_type
+ *
+ * returns key curve type that maps to libssh2_curve_type
+ *
+ */
+
+libssh2_curve_type
+_libssh2_ecdsa_key_get_curve_type(_libssh2_ec_key *key)
+{
+    const EC_GROUP *group = EC_KEY_get0_group(key);
+    return EC_GROUP_get_curve_name(group);
+}
+
+/* _libssh2_ecdsa_curve_type_from_name
+ *
+ * returns 0 for success, key curve type that maps to libssh2_curve_type
+ *
+ */
+
+int
+_libssh2_ecdsa_curve_type_from_name(const char *name,
+                                    libssh2_curve_type *out_type)
+{
+    int ret = 0;
+    libssh2_curve_type type;
+
+    if(name == NULL || strlen(name) != 19)
+        return -1;
+
+    if(strcmp(name, "ecdsa-sha2-nistp256") == 0)
+        type = LIBSSH2_EC_CURVE_NISTP256;
+    else if(strcmp(name, "ecdsa-sha2-nistp384") == 0)
+        type = LIBSSH2_EC_CURVE_NISTP384;
+    else if(strcmp(name, "ecdsa-sha2-nistp521") == 0)
+        type = LIBSSH2_EC_CURVE_NISTP521;
+    else {
+        ret = -1;
+    }
+
+    if(ret == 0 && out_type) {
+        *out_type = type;
+    }
+
+    return ret;
+}
+
+/* _libssh2_ecdsa_curve_name_with_octal_new
+ *
+ * Creates a new public key given an octal string, length and type
+ *
+ */
+
+int
+_libssh2_ecdsa_curve_name_with_octal_new(libssh2_ecdsa_ctx ** ec_ctx,
+     const unsigned char *k,
+     size_t k_len, libssh2_curve_type curve)
+{
+
+    int ret = 0;
+    const EC_GROUP *ec_group = NULL;
+    EC_KEY *ec_key = EC_KEY_new_by_curve_name(curve);
+    EC_POINT *point = NULL;
+
+    if(ec_key) {
+        ec_group = EC_KEY_get0_group(ec_key);
+        point = EC_POINT_new(ec_group);
+        ret = EC_POINT_oct2point(ec_group, point, k, k_len, NULL);
+        ret = EC_KEY_set_public_key(ec_key, point);
+
+        if(point != NULL)
+            EC_POINT_free(point);
+
+        if(ec_ctx != NULL)
+            *ec_ctx = ec_key;
+    }
+
+    return (ret == 1) ? 0 : -1;
+}
+
+#define LIBSSH2_ECDSA_VERIFY(digest_type)                           \
+{                                                                   \
+    unsigned char hash[SHA##digest_type##_DIGEST_LENGTH];           \
+    libssh2_sha##digest_type(m, m_len, hash);                       \
+    ret = ECDSA_do_verify(hash, SHA##digest_type##_DIGEST_LENGTH,   \
+      ecdsa_sig, ec_key);                                           \
+                                                                    \
+}
+
+int
+_libssh2_ecdsa_verify(libssh2_ecdsa_ctx * ctx,
+      const unsigned char *r, size_t r_len,
+      const unsigned char *s, size_t s_len,
+      const unsigned char *m, size_t m_len)
+{
+    int ret = 0;
+    EC_KEY *ec_key = (EC_KEY*)ctx;
+    libssh2_curve_type type = _libssh2_ecdsa_key_get_curve_type(ec_key);
+
+#ifdef HAVE_OPAQUE_STRUCTS
+    ECDSA_SIG *ecdsa_sig = ECDSA_SIG_new();
+    BIGNUM *pr = BN_new();
+    BIGNUM *ps = BN_new();
+
+    BN_bin2bn(r, r_len, pr);
+    BN_bin2bn(s, s_len, ps);
+    ECDSA_SIG_set0(ecdsa_sig, pr, ps);
+
+#else
+    ECDSA_SIG ecdsa_sig_;
+    ECDSA_SIG *ecdsa_sig = &ecdsa_sig_;
+    ecdsa_sig_.r = BN_new();
+    BN_bin2bn(r, r_len, ecdsa_sig_.r);
+    ecdsa_sig_.s = BN_new();
+    BN_bin2bn(s, s_len, ecdsa_sig_.s);
+#endif
+
+    if(type == LIBSSH2_EC_CURVE_NISTP256) {
+        LIBSSH2_ECDSA_VERIFY(256);
+    }
+    else if(type == LIBSSH2_EC_CURVE_NISTP384) {
+        LIBSSH2_ECDSA_VERIFY(384);
+    }
+    else if(type == LIBSSH2_EC_CURVE_NISTP521) {
+        LIBSSH2_ECDSA_VERIFY(512);
+    }
+
+#ifdef HAVE_OPAQUE_STRUCTS
+    if(ecdsa_sig)
+        ECDSA_SIG_free(ecdsa_sig);
+#else
+    BN_clear_free(ecdsa_sig_.s);
+    BN_clear_free(ecdsa_sig_.r);
+#endif
+
+    return (ret == 1) ? 0 : -1;
+}
+
+#endif /* LIBSSH2_ECDSA */
+
+int
+_libssh2_cipher_init(_libssh2_cipher_ctx * h,
+                     _libssh2_cipher_type(algo),
+                     unsigned char *iv, unsigned char *secret, int encrypt)
+{
+#ifdef HAVE_OPAQUE_STRUCTS
+    *h = EVP_CIPHER_CTX_new();
+    return !EVP_CipherInit(*h, algo(), secret, iv, encrypt);
+#else
+    EVP_CIPHER_CTX_init(h);
+    return !EVP_CipherInit(h, algo(), secret, iv, encrypt);
+#endif
+}
+
+int
+_libssh2_cipher_crypt(_libssh2_cipher_ctx * ctx,
+                      _libssh2_cipher_type(algo),
+                      int encrypt, unsigned char *block, size_t blocksize)
+{
+    unsigned char buf[EVP_MAX_BLOCK_LENGTH];
+    int ret;
+    (void) algo;
+    (void) encrypt;
+
+#ifdef HAVE_OPAQUE_STRUCTS
+    ret = EVP_Cipher(*ctx, buf, block, blocksize);
+#else
+    ret = EVP_Cipher(ctx, buf, block, blocksize);
+#endif
+    if(ret == 1) {
+        memcpy(block, buf, blocksize);
+    }
+    return ret == 1 ? 0 : 1;
+}
+
+#if LIBSSH2_AES_CTR && !defined(HAVE_EVP_AES_128_CTR)
+
+#include <openssl/aes.h>
+#include <openssl/evp.h>
+
+typedef struct
+{
+    AES_KEY       key;
+    EVP_CIPHER_CTX *aes_ctx;
+    unsigned char ctr[AES_BLOCK_SIZE];
+} aes_ctr_ctx;
+
+static int
+aes_ctr_init(EVP_CIPHER_CTX *ctx, const unsigned char *key,
+             const unsigned char *iv, int enc) /* init key */
+{
+    /*
+     * variable "c" is leaked from this scope, but is later freed
+     * in aes_ctr_cleanup
+     */
+    aes_ctr_ctx *c;
+    const EVP_CIPHER *aes_cipher;
+    (void) enc;
+
+    switch(EVP_CIPHER_CTX_key_length(ctx)) {
+    case 16:
+        aes_cipher = EVP_aes_128_ecb();
+        break;
+    case 24:
+        aes_cipher = EVP_aes_192_ecb();
+        break;
+    case 32:
+        aes_cipher = EVP_aes_256_ecb();
+        break;
+    default:
+        return 0;
+    }
+
+    c = malloc(sizeof(*c));
+    if(c == NULL)
+        return 0;
+
+#ifdef HAVE_OPAQUE_STRUCTS
+    c->aes_ctx = EVP_CIPHER_CTX_new();
+#else
+    c->aes_ctx = malloc(sizeof(EVP_CIPHER_CTX));
+#endif
+    if(c->aes_ctx == NULL) {
+        free(c);
+        return 0;
+    }
+
+    if(EVP_EncryptInit(c->aes_ctx, aes_cipher, key, NULL) != 1) {
+#ifdef HAVE_OPAQUE_STRUCTS
+        EVP_CIPHER_CTX_free(c->aes_ctx);
+#else
+        free(c->aes_ctx);
+#endif
+        free(c);
+        return 0;
+    }
+
+    EVP_CIPHER_CTX_set_padding(c->aes_ctx, 0);
+
+    memcpy(c->ctr, iv, AES_BLOCK_SIZE);
+
+    EVP_CIPHER_CTX_set_app_data(ctx, c);
+
+    return 1;
+}
+
+static int
+aes_ctr_do_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
+                  const unsigned char *in,
+                  size_t inl) /* encrypt/decrypt data */
+{
+    aes_ctr_ctx *c = EVP_CIPHER_CTX_get_app_data(ctx);
+    unsigned char b1[AES_BLOCK_SIZE];
+    int outlen = 0;
+
+    if(inl != 16) /* libssh2 only ever encrypt one block */
+        return 0;
+
+    if(c == NULL) {
+        return 0;
+    }
+
+/*
+  To encrypt a packet P=P1||P2||...||Pn (where P1, P2, ..., Pn are each
+  blocks of length L), the encryptor first encrypts <X> with <cipher>
+  to obtain a block B1.  The block B1 is then XORed with P1 to generate
+  the ciphertext block C1.  The counter X is then incremented
+*/
+
+    if(EVP_EncryptUpdate(c->aes_ctx, b1, &outlen,
+                         c->ctr, AES_BLOCK_SIZE) != 1) {
+        return 0;
+    }
+
+    _libssh2_xor_data(out, in, b1, AES_BLOCK_SIZE);
+    _libssh2_aes_ctr_increment(c->ctr, AES_BLOCK_SIZE);
+
+    return 1;
+}
+
+static int
+aes_ctr_cleanup(EVP_CIPHER_CTX *ctx) /* cleanup ctx */
+{
+    aes_ctr_ctx *c = EVP_CIPHER_CTX_get_app_data(ctx);
+
+    if(c == NULL) {
+        return 1;
+    }
+
+    if(c->aes_ctx != NULL) {
+#ifdef HAVE_OPAQUE_STRUCTS
+        EVP_CIPHER_CTX_free(c->aes_ctx);
+#else
+        _libssh2_cipher_dtor(c->aes_ctx);
+        free(c->aes_ctx);
+#endif
+    }
+
+    free(c);
+
+    return 1;
+}
+
+static const EVP_CIPHER *
+make_ctr_evp (size_t keylen, EVP_CIPHER **aes_ctr_cipher, int type)
+{
+#ifdef HAVE_OPAQUE_STRUCTS
+    *aes_ctr_cipher = EVP_CIPHER_meth_new(type, 16, keylen);
+    if(*aes_ctr_cipher) {
+        EVP_CIPHER_meth_set_iv_length(*aes_ctr_cipher, 16);
+        EVP_CIPHER_meth_set_init(*aes_ctr_cipher, aes_ctr_init);
+        EVP_CIPHER_meth_set_do_cipher(*aes_ctr_cipher, aes_ctr_do_cipher);
+        EVP_CIPHER_meth_set_cleanup(*aes_ctr_cipher, aes_ctr_cleanup);
+    }
+#else
+    (*aes_ctr_cipher)->nid = type;
+    (*aes_ctr_cipher)->block_size = 16;
+    (*aes_ctr_cipher)->key_len = keylen;
+    (*aes_ctr_cipher)->iv_len = 16;
+    (*aes_ctr_cipher)->init = aes_ctr_init;
+    (*aes_ctr_cipher)->do_cipher = aes_ctr_do_cipher;
+    (*aes_ctr_cipher)->cleanup = aes_ctr_cleanup;
+#endif
+
+    return *aes_ctr_cipher;
+}
+
+const EVP_CIPHER *
+_libssh2_EVP_aes_128_ctr(void)
+{
+#ifdef HAVE_OPAQUE_STRUCTS
+    static EVP_CIPHER * aes_ctr_cipher;
+    return !aes_ctr_cipher ?
+        make_ctr_evp(16, &aes_ctr_cipher, NID_aes_128_ctr) : aes_ctr_cipher;
+#else
+    static EVP_CIPHER aes_ctr_cipher;
+    static EVP_CIPHER * aes_ctr_cipher_ptr = &aes_ctr_cipher;
+    return !aes_ctr_cipher.key_len ?
+        make_ctr_evp(16, &aes_ctr_cipher_ptr, 0) : &aes_ctr_cipher;
+#endif
+}
+
+const EVP_CIPHER *
+_libssh2_EVP_aes_192_ctr(void)
+{
+#ifdef HAVE_OPAQUE_STRUCTS
+    static EVP_CIPHER * aes_ctr_cipher;
+    return !aes_ctr_cipher ?
+        make_ctr_evp(24, &aes_ctr_cipher, NID_aes_192_ctr) : aes_ctr_cipher;
+#else
+    static EVP_CIPHER aes_ctr_cipher;
+    static EVP_CIPHER * aes_ctr_cipher_ptr = &aes_ctr_cipher;
+    return !aes_ctr_cipher.key_len ?
+        make_ctr_evp(24, &aes_ctr_cipher_ptr, 0) : &aes_ctr_cipher;
+#endif
+}
+
+const EVP_CIPHER *
+_libssh2_EVP_aes_256_ctr(void)
+{
+#ifdef HAVE_OPAQUE_STRUCTS
+    static EVP_CIPHER * aes_ctr_cipher;
+    return !aes_ctr_cipher ?
+        make_ctr_evp(32, &aes_ctr_cipher, NID_aes_256_ctr) : aes_ctr_cipher;
+#else
+    static EVP_CIPHER aes_ctr_cipher;
+    static EVP_CIPHER * aes_ctr_cipher_ptr = &aes_ctr_cipher;
+    return !aes_ctr_cipher.key_len ?
+        make_ctr_evp(32, &aes_ctr_cipher_ptr, 0) : &aes_ctr_cipher;
+#endif
+}
+
+#endif /* LIBSSH2_AES_CTR */
+
+#ifndef HAVE_EVP_AES_128_CTR
+static EVP_CIPHER * aes_128_ctr_cipher = NULL;
+static EVP_CIPHER * aes_192_ctr_cipher = NULL;
+static EVP_CIPHER * aes_256_ctr_cipher = NULL;
+#endif
+
+void _libssh2_openssl_crypto_init(void)
+{
+#if OPENSSL_VERSION_NUMBER >= 0x10100000L && \
+    !defined(LIBRESSL_VERSION_NUMBER)
+#ifndef OPENSSL_NO_ENGINE
+    ENGINE_load_builtin_engines();
+    ENGINE_register_all_complete();
+#endif
+#else
+    OpenSSL_add_all_algorithms();
+    OpenSSL_add_all_ciphers();
+    OpenSSL_add_all_digests();
+#ifndef OPENSSL_NO_ENGINE
+    ENGINE_load_builtin_engines();
+    ENGINE_register_all_complete();
+#endif
+#endif
+#ifndef HAVE_EVP_AES_128_CTR
+    aes_128_ctr_cipher = (EVP_CIPHER *)_libssh2_EVP_aes_128_ctr();
+    aes_192_ctr_cipher = (EVP_CIPHER *)_libssh2_EVP_aes_192_ctr();
+    aes_256_ctr_cipher = (EVP_CIPHER *)_libssh2_EVP_aes_256_ctr();
+#endif
+}
+
+void _libssh2_openssl_crypto_exit(void)
+{
+#ifndef HAVE_EVP_AES_128_CTR
+#ifdef HAVE_OPAQUE_STRUCTS
+    if(aes_128_ctr_cipher) {
+        EVP_CIPHER_meth_free(aes_128_ctr_cipher);
+    }
+
+    if(aes_192_ctr_cipher) {
+        EVP_CIPHER_meth_free(aes_192_ctr_cipher);
+    }
+
+    if(aes_256_ctr_cipher) {
+        EVP_CIPHER_meth_free(aes_256_ctr_cipher);
+    }
+#endif
+
+    aes_128_ctr_cipher = NULL;
+    aes_192_ctr_cipher = NULL;
+    aes_256_ctr_cipher = NULL;
+#endif
+}
+
+/* TODO: Optionally call a passphrase callback specified by the
+ * calling program
+ */
+static int
+passphrase_cb(char *buf, int size, int rwflag, char *passphrase)
+{
+    int passphrase_len = strlen(passphrase);
+    (void) rwflag;
+
+    if(passphrase_len > (size - 1)) {
+        passphrase_len = size - 1;
+    }
+    memcpy(buf, passphrase, passphrase_len);
+    buf[passphrase_len] = '\0';
+
+    return passphrase_len;
+}
+
+typedef void * (*pem_read_bio_func)(BIO *, void **, pem_password_cb *,
+                                    void *u);
+
+static int
+read_private_key_from_memory(void **key_ctx,
+                             pem_read_bio_func read_private_key,
+                             const char *filedata,
+                             size_t filedata_len,
+                             unsigned const char *passphrase)
+{
+    BIO * bp;
+
+    *key_ctx = NULL;
+
+    bp = BIO_new_mem_buf((char *)filedata, filedata_len);
+    if(!bp) {
+        return -1;
+    }
+    *key_ctx = read_private_key(bp, NULL, (pem_password_cb *) passphrase_cb,
+                                (void *) passphrase);
+
+    BIO_free(bp);
+    return (*key_ctx) ? 0 : -1;
+}
+
+
+
+static int
+read_private_key_from_file(void **key_ctx,
+                           pem_read_bio_func read_private_key,
+                           const char *filename,
+                           unsigned const char *passphrase)
+{
+    BIO * bp;
+
+    *key_ctx = NULL;
+
+    bp = BIO_new_file(filename, "r");
+    if(!bp) {
+        return -1;
+    }
+
+    *key_ctx = read_private_key(bp, NULL, (pem_password_cb *) passphrase_cb,
+                                (void *) passphrase);
+
+    BIO_free(bp);
+    return (*key_ctx) ? 0 : -1;
+}
+
+int
+_libssh2_rsa_new_private_frommemory(libssh2_rsa_ctx ** rsa,
+                                    LIBSSH2_SESSION * session,
+                                    const char *filedata, size_t filedata_len,
+                                    unsigned const char *passphrase)
+{
+    int rc;
+
+    pem_read_bio_func read_rsa =
+        (pem_read_bio_func) &PEM_read_bio_RSAPrivateKey;
+    (void) session;
+
+    _libssh2_init_if_needed();
+
+    rc = read_private_key_from_memory((void **) rsa, read_rsa,
+                                      filedata, filedata_len, passphrase);
+
+    if(rc) {
+        rc = read_openssh_private_key_from_memory((void **)rsa, session,
+                        "ssh-rsa", filedata, filedata_len, passphrase);
+    }
+
+return rc;
+}
+
+static unsigned char *
+gen_publickey_from_rsa(LIBSSH2_SESSION *session, RSA *rsa,
+                       size_t *key_len)
+{
+    int            e_bytes, n_bytes;
+    unsigned long  len;
+    unsigned char *key;
+    unsigned char *p;
+    const BIGNUM * e;
+    const BIGNUM * n;
+#ifdef HAVE_OPAQUE_STRUCTS
+    RSA_get0_key(rsa, &n, &e, NULL);
+#else
+    e = rsa->e;
+    n = rsa->n;
+#endif
+    e_bytes = BN_num_bytes(e) + 1;
+    n_bytes = BN_num_bytes(n) + 1;
+
+    /* Key form is "ssh-rsa" + e + n. */
+    len = 4 + 7 + 4 + e_bytes + 4 + n_bytes;
+
+    key = LIBSSH2_ALLOC(session, len);
+    if(key == NULL) {
+        return NULL;
+    }
+
+    /* Process key encoding. */
+    p = key;
+
+    _libssh2_htonu32(p, 7);  /* Key type. */
+    p += 4;
+    memcpy(p, "ssh-rsa", 7);
+    p += 7;
+
+    p = write_bn(p, e, e_bytes);
+    p = write_bn(p, n, n_bytes);
+
+    *key_len = (size_t)(p - key);
+    return key;
+}
+
+static int
+gen_publickey_from_rsa_evp(LIBSSH2_SESSION *session,
+                           unsigned char **method,
+                           size_t *method_len,
+                           unsigned char **pubkeydata,
+                           size_t *pubkeydata_len,
+                           EVP_PKEY *pk)
+{
+    RSA*           rsa = NULL;
+    unsigned char *key;
+    unsigned char *method_buf = NULL;
+    size_t  key_len;
+
+    _libssh2_debug(session,
+                   LIBSSH2_TRACE_AUTH,
+                   "Computing public key from RSA private key envelop");
+
+    rsa = EVP_PKEY_get1_RSA(pk);
+    if(rsa == NULL) {
+        /* Assume memory allocation error... what else could it be ? */
+        goto __alloc_error;
+    }
+
+    method_buf = LIBSSH2_ALLOC(session, 7);  /* ssh-rsa. */
+    if(method_buf == NULL) {
+        goto __alloc_error;
+    }
+
+    key = gen_publickey_from_rsa(session, rsa, &key_len);
+    if(key == NULL) {
+        goto __alloc_error;
+    }
+    RSA_free(rsa);
+
+    memcpy(method_buf, "ssh-rsa", 7);
+    *method         = method_buf;
+    *method_len     = 7;
+    *pubkeydata     = key;
+    *pubkeydata_len = key_len;
+    return 0;
+
+  __alloc_error:
+    if(rsa != NULL) {
+        RSA_free(rsa);
+    }
+    if(method_buf != NULL) {
+        LIBSSH2_FREE(session, method_buf);
+    }
+
+    return _libssh2_error(session,
+                          LIBSSH2_ERROR_ALLOC,
+                          "Unable to allocate memory for private key data");
+}
+
+static int _libssh2_rsa_new_additional_parameters(RSA *rsa)
+{
+    BN_CTX *ctx = NULL;
+    BIGNUM *aux = NULL;
+    BIGNUM *dmp1 = NULL;
+    BIGNUM *dmq1 = NULL;
+    const BIGNUM *p = NULL;
+    const BIGNUM *q = NULL;
+    const BIGNUM *d = NULL;
+    int rc = 0;
+
+#ifdef HAVE_OPAQUE_STRUCTS
+    RSA_get0_key(rsa, NULL, NULL, &d);
+    RSA_get0_factors(rsa, &p, &q);
+#else
+    d = (*rsa).d;
+    p = (*rsa).p;
+    q = (*rsa).q;
+#endif
+
+    ctx = BN_CTX_new();
+    if(ctx == NULL)
+        return -1;
+
+    aux = BN_new();
+    if(aux == NULL) {
+        rc = -1;
+        goto out;
+    }
+
+    dmp1 = BN_new();
+    if(dmp1 == NULL) {
+        rc = -1;
+        goto out;
+    }
+
+    dmq1 = BN_new();
+    if(dmq1 == NULL) {
+        rc = -1;
+        goto out;
+    }
+
+    if((BN_sub(aux, q, BN_value_one()) == 0) ||
+        (BN_mod(dmq1, d, aux, ctx) == 0) ||
+        (BN_sub(aux, p, BN_value_one()) == 0) ||
+        (BN_mod(dmp1, d, aux, ctx) == 0)) {
+        rc = -1;
+        goto out;
+    }
+
+#ifdef HAVE_OPAQUE_STRUCTS
+    RSA_set0_crt_params(rsa, dmp1, dmq1, NULL);
+#else
+    (*rsa).dmp1 = dmp1;
+    (*rsa).dmq1 = dmq1;
+#endif
+
+out:
+    if(aux)
+        BN_clear_free(aux);
+    BN_CTX_free(ctx);
+
+    if(rc != 0) {
+        if(dmp1)
+            BN_clear_free(dmp1);
+        if(dmq1)
+            BN_clear_free(dmq1);
+    }
+
+    return rc;
+}
+
+static int
+gen_publickey_from_rsa_openssh_priv_data(LIBSSH2_SESSION *session,
+                                         struct string_buf *decrypted,
+                                         unsigned char **method,
+                                         size_t *method_len,
+                                         unsigned char **pubkeydata,
+                                         size_t *pubkeydata_len,
+                                         libssh2_rsa_ctx **rsa_ctx)
+{
+    int rc = 0;
+    size_t nlen, elen, dlen, plen, qlen, coefflen, commentlen;
+    unsigned char *n, *e, *d, *p, *q, *coeff, *comment;
+    RSA *rsa = NULL;
+
+    _libssh2_debug(session,
+                   LIBSSH2_TRACE_AUTH,
+                   "Computing RSA keys from private key data");
+
+    /* public key data */
+    if(_libssh2_get_bignum_bytes(decrypted, &n, &nlen)) {
+        _libssh2_error(session, LIBSSH2_ERROR_PROTO,
+                       "RSA no n");
+        return -1;
+    }
+
+    if(_libssh2_get_bignum_bytes(decrypted, &e, &elen)) {
+        _libssh2_error(session, LIBSSH2_ERROR_PROTO,
+                       "RSA no e");
+        return -1;
+    }
+
+    /* private key data */
+    if(_libssh2_get_bignum_bytes(decrypted, &d, &dlen)) {
+        _libssh2_error(session, LIBSSH2_ERROR_PROTO,
+                       "RSA no d");
+        return -1;
+    }
+
+    if(_libssh2_get_bignum_bytes(decrypted, &coeff, &coefflen)) {
+        _libssh2_error(session, LIBSSH2_ERROR_PROTO,
+                       "RSA no coeff");
+        return -1;
+    }
+
+    if(_libssh2_get_bignum_bytes(decrypted, &p, &plen)) {
+        _libssh2_error(session, LIBSSH2_ERROR_PROTO,
+                       "RSA no p");
+        return -1;
+    }
+
+    if(_libssh2_get_bignum_bytes(decrypted, &q, &qlen)) {
+        _libssh2_error(session, LIBSSH2_ERROR_PROTO,
+                       "RSA no q");
+        return -1;
+    }
+
+    if(_libssh2_get_string(decrypted, &comment, &commentlen)) {
+        _libssh2_error(session, LIBSSH2_ERROR_PROTO,
+                       "RSA no comment");
+        return -1;
+    }
+
+    if((rc = _libssh2_rsa_new(&rsa, e, elen, n, nlen, d, dlen, p, plen,
+                              q, qlen, NULL, 0, NULL, 0,
+                              coeff, coefflen)) != 0) {
+        _libssh2_debug(session,
+                       LIBSSH2_TRACE_AUTH,
+                       "Could not create RSA private key");
+        goto fail;
+    }
+
+    if(rsa != NULL)
+        rc = _libssh2_rsa_new_additional_parameters(rsa);
+
+    if(rsa != NULL && pubkeydata != NULL && method != NULL) {
+        EVP_PKEY *pk = EVP_PKEY_new();
+        EVP_PKEY_set1_RSA(pk, rsa);
+
+        rc = gen_publickey_from_rsa_evp(session, method, method_len,
+                                        pubkeydata, pubkeydata_len,
+                                        pk);
+
+        if(pk)
+            EVP_PKEY_free(pk);
+    }
+
+    if(rsa_ctx != NULL)
+        *rsa_ctx = rsa;
+    else
+        RSA_free(rsa);
+
+    return rc;
+
+fail:
+
+    if(rsa != NULL)
+        RSA_free(rsa);
+
+    return _libssh2_error(session,
+                          LIBSSH2_ERROR_ALLOC,
+                          "Unable to allocate memory for private key data");
+}
+
+static int
+_libssh2_rsa_new_openssh_private(libssh2_rsa_ctx ** rsa,
+                                 LIBSSH2_SESSION * session,
+                                 const char *filename,
+                                 unsigned const char *passphrase)
+{
+    FILE *fp;
+    int rc;
+    unsigned char *buf = NULL;
+    struct string_buf *decrypted = NULL;
+
+    if(session == NULL) {
+        _libssh2_error(session, LIBSSH2_ERROR_PROTO,
+                       "Session is required");
+        return -1;
+    }
+
+    _libssh2_init_if_needed();
+
+    fp = fopen(filename, "r");
+    if(!fp) {
+        _libssh2_error(session, LIBSSH2_ERROR_FILE,
+                       "Unable to open OpenSSH RSA private key file");
+        return -1;
+    }
+
+    rc = _libssh2_openssh_pem_parse(session, passphrase, fp, &decrypted);
+    fclose(fp);
+    if(rc) {
+        return rc;
+    }
+
+    /* We have a new key file, now try and parse it using supported types  */
+    rc = _libssh2_get_string(decrypted, &buf, NULL);
+
+    if(rc != 0 || buf == NULL) {
+        _libssh2_error(session, LIBSSH2_ERROR_PROTO,
+                       "Public key type in decrypted key data not found");
+        return -1;
+    }
+
+    if(strcmp("ssh-rsa", (const char *)buf) == 0) {
+        rc = gen_publickey_from_rsa_openssh_priv_data(session, decrypted,
+                                                      NULL, 0,
+                                                      NULL, 0, rsa);
+    }
+    else {
+        rc = -1;
+    }
+
+    if(decrypted)
+        _libssh2_string_buf_free(session, decrypted);
+
+    return rc;
+}
+
+int
+_libssh2_rsa_new_private(libssh2_rsa_ctx ** rsa,
+                         LIBSSH2_SESSION * session,
+                         const char *filename, unsigned const char *passphrase)
+{
+    int rc;
+
+    pem_read_bio_func read_rsa =
+        (pem_read_bio_func) &PEM_read_bio_RSAPrivateKey;
+    (void) session;
+
+    _libssh2_init_if_needed();
+
+    rc = read_private_key_from_file((void **) rsa, read_rsa,
+                                    filename, passphrase);
+
+    if(rc) {
+        rc = _libssh2_rsa_new_openssh_private(rsa, session,
+                                              filename, passphrase);
+    }
+
+    return rc;
+}
+
+#if LIBSSH2_DSA
+int
+_libssh2_dsa_new_private_frommemory(libssh2_dsa_ctx ** dsa,
+                                    LIBSSH2_SESSION * session,
+                                    const char *filedata, size_t filedata_len,
+                                    unsigned const char *passphrase)
+{
+    int rc;
+
+    pem_read_bio_func read_dsa =
+        (pem_read_bio_func) &PEM_read_bio_DSAPrivateKey;
+    (void) session;
+
+    _libssh2_init_if_needed();
+
+    rc = read_private_key_from_memory((void **)dsa, read_dsa,
+                                      filedata, filedata_len, passphrase);
+
+    if(rc) {
+        rc = read_openssh_private_key_from_memory((void **)dsa, session,
+                            "ssh-dsa", filedata, filedata_len, passphrase);
+    }
+
+    return rc;
+}
+
+static unsigned char *
+gen_publickey_from_dsa(LIBSSH2_SESSION* session, DSA *dsa,
+                       size_t *key_len)
+{
+    int            p_bytes, q_bytes, g_bytes, k_bytes;
+    unsigned long  len;
+    unsigned char *key;
+    unsigned char *p;
+
+    const BIGNUM * p_bn;
+    const BIGNUM * q;
+    const BIGNUM * g;
+    const BIGNUM * pub_key;
+#ifdef HAVE_OPAQUE_STRUCTS
+    DSA_get0_pqg(dsa, &p_bn, &q, &g);
+#else
+    p_bn = dsa->p;
+    q = dsa->q;
+    g = dsa->g;
+#endif
+
+#ifdef HAVE_OPAQUE_STRUCTS
+    DSA_get0_key(dsa, &pub_key, NULL);
+#else
+    pub_key = dsa->pub_key;
+#endif
+    p_bytes = BN_num_bytes(p_bn) + 1;
+    q_bytes = BN_num_bytes(q) + 1;
+    g_bytes = BN_num_bytes(g) + 1;
+    k_bytes = BN_num_bytes(pub_key) + 1;
+
+    /* Key form is "ssh-dss" + p + q + g + pub_key. */
+    len = 4 + 7 + 4 + p_bytes + 4 + q_bytes + 4 + g_bytes + 4 + k_bytes;
+
+    key = LIBSSH2_ALLOC(session, len);
+    if(key == NULL) {
+        return NULL;
+    }
+
+    /* Process key encoding. */
+    p = key;
+
+    _libssh2_htonu32(p, 7);  /* Key type. */
+    p += 4;
+    memcpy(p, "ssh-dss", 7);
+    p += 7;
+
+    p = write_bn(p, p_bn, p_bytes);
+    p = write_bn(p, q, q_bytes);
+    p = write_bn(p, g, g_bytes);
+    p = write_bn(p, pub_key, k_bytes);
+
+    *key_len = (size_t)(p - key);
+    return key;
+}
+
+static int
+gen_publickey_from_dsa_evp(LIBSSH2_SESSION *session,
+                           unsigned char **method,
+                           size_t *method_len,
+                           unsigned char **pubkeydata,
+                           size_t *pubkeydata_len,
+                           EVP_PKEY *pk)
+{
+    DSA*           dsa = NULL;
+    unsigned char *key;
+    unsigned char *method_buf = NULL;
+    size_t  key_len;
+
+    _libssh2_debug(session,
+                   LIBSSH2_TRACE_AUTH,
+                   "Computing public key from DSA private key envelop");
+
+    dsa = EVP_PKEY_get1_DSA(pk);
+    if(dsa == NULL) {
+        /* Assume memory allocation error... what else could it be ? */
+        goto __alloc_error;
+    }
+
+    method_buf = LIBSSH2_ALLOC(session, 7);  /* ssh-dss. */
+    if(method_buf == NULL) {
+        goto __alloc_error;
+    }
+
+    key = gen_publickey_from_dsa(session, dsa, &key_len);
+    if(key == NULL) {
+        goto __alloc_error;
+    }
+    DSA_free(dsa);
+
+    memcpy(method_buf, "ssh-dss", 7);
+    *method         = method_buf;
+    *method_len     = 7;
+    *pubkeydata     = key;
+    *pubkeydata_len = key_len;
+    return 0;
+
+  __alloc_error:
+    if(dsa != NULL) {
+        DSA_free(dsa);
+    }
+    if(method_buf != NULL) {
+        LIBSSH2_FREE(session, method_buf);
+    }
+
+    return _libssh2_error(session,
+                          LIBSSH2_ERROR_ALLOC,
+                          "Unable to allocate memory for private key data");
+}
+
+static int
+gen_publickey_from_dsa_openssh_priv_data(LIBSSH2_SESSION *session,
+                                         struct string_buf *decrypted,
+                                         unsigned char **method,
+                                         size_t *method_len,
+                                         unsigned char **pubkeydata,
+                                         size_t *pubkeydata_len,
+                                         libssh2_dsa_ctx **dsa_ctx)
+{
+    int rc = 0;
+    size_t plen, qlen, glen, pub_len, priv_len;
+    unsigned char *p, *q, *g, *pub_key, *priv_key;
+    DSA *dsa = NULL;
+
+    _libssh2_debug(session,
+                   LIBSSH2_TRACE_AUTH,
+                   "Computing DSA keys from private key data");
+
+    if(_libssh2_get_bignum_bytes(decrypted, &p, &plen)) {
+        _libssh2_error(session, LIBSSH2_ERROR_PROTO,
+                       "DSA no p");
+        return -1;
+    }
+
+    if(_libssh2_get_bignum_bytes(decrypted, &q, &qlen)) {
+        _libssh2_error(session, LIBSSH2_ERROR_PROTO,
+                       "DSA no q");
+        return -1;
+    }
+
+    if(_libssh2_get_bignum_bytes(decrypted, &g, &glen)) {
+        _libssh2_error(session, LIBSSH2_ERROR_PROTO,
+                       "DSA no g");
+        return -1;
+    }
+
+    if(_libssh2_get_bignum_bytes(decrypted, &pub_key, &pub_len)) {
+        _libssh2_error(session, LIBSSH2_ERROR_PROTO,
+                       "DSA no public key");
+        return -1;
+    }
+
+    if(_libssh2_get_bignum_bytes(decrypted, &priv_key, &priv_len)) {
+        _libssh2_error(session, LIBSSH2_ERROR_PROTO,
+                       "DSA no private key");
+        return -1;
+    }
+
+    rc = _libssh2_dsa_new(&dsa, p, plen, q, qlen, g, glen, pub_key, pub_len,
+                          priv_key, priv_len);
+    if(rc != 0) {
+        _libssh2_debug(session,
+                       LIBSSH2_ERROR_PROTO,
+                       "Could not create DSA private key");
+        goto fail;
+    }
+
+    if(dsa != NULL && pubkeydata != NULL && method != NULL) {
+        EVP_PKEY *pk = EVP_PKEY_new();
+        EVP_PKEY_set1_DSA(pk, dsa);
+
+        rc = gen_publickey_from_dsa_evp(session, method, method_len,
+                                        pubkeydata, pubkeydata_len,
+                                        pk);
+
+        if(pk)
+            EVP_PKEY_free(pk);
+    }
+
+    if(dsa_ctx != NULL)
+        *dsa_ctx = dsa;
+    else
+        DSA_free(dsa);
+
+    return rc;
+
+fail:
+
+    if(dsa != NULL)
+        DSA_free(dsa);
+
+    return _libssh2_error(session,
+                          LIBSSH2_ERROR_ALLOC,
+                          "Unable to allocate memory for private key data");
+}
+
+static int
+_libssh2_dsa_new_openssh_private(libssh2_dsa_ctx ** dsa,
+                                 LIBSSH2_SESSION * session,
+                                 const char *filename,
+                                 unsigned const char *passphrase)
+{
+    FILE *fp;
+    int rc;
+    unsigned char *buf = NULL;
+    struct string_buf *decrypted = NULL;
+
+    if(session == NULL) {
+        _libssh2_error(session, LIBSSH2_ERROR_PROTO,
+                       "Session is required");
+        return -1;
+    }
+
+    _libssh2_init_if_needed();
+
+    fp = fopen(filename, "r");
+    if(!fp) {
+        _libssh2_error(session, LIBSSH2_ERROR_FILE,
+                       "Unable to open OpenSSH DSA private key file");
+        return -1;
+    }
+
+    rc = _libssh2_openssh_pem_parse(session, passphrase, fp, &decrypted);
+    fclose(fp);
+    if(rc) {
+        return rc;
+    }
+
+    /* We have a new key file, now try and parse it using supported types  */
+    rc = _libssh2_get_string(decrypted, &buf, NULL);
+
+    if(rc != 0 || buf == NULL) {
+        _libssh2_error(session, LIBSSH2_ERROR_PROTO,
+                       "Public key type in decrypted key data not found");
+        return -1;
+    }
+
+    if(strcmp("ssh-dss", (const char *)buf) == 0) {
+        rc = gen_publickey_from_dsa_openssh_priv_data(session, decrypted,
+                                                      NULL, 0,
+                                                      NULL, 0, dsa);
+    }
+    else {
+        rc = -1;
+    }
+
+    if(decrypted)
+        _libssh2_string_buf_free(session, decrypted);
+
+    return rc;
+}
+
+int
+_libssh2_dsa_new_private(libssh2_dsa_ctx ** dsa,
+                         LIBSSH2_SESSION * session,
+                         const char *filename, unsigned const char *passphrase)
+{
+    int rc;
+
+    pem_read_bio_func read_dsa =
+        (pem_read_bio_func) &PEM_read_bio_DSAPrivateKey;
+    (void) session;
+
+    _libssh2_init_if_needed();
+
+    rc = read_private_key_from_file((void **) dsa, read_dsa,
+                                    filename, passphrase);
+
+    if(rc) {
+        rc = _libssh2_dsa_new_openssh_private(dsa, session,
+                                              filename, passphrase);
+    }
+
+    return rc;
+}
+
+#endif /* LIBSSH_DSA */
+
+#if LIBSSH2_ECDSA
+
+int
+_libssh2_ecdsa_new_private_frommemory(libssh2_ecdsa_ctx ** ec_ctx,
+                                    LIBSSH2_SESSION * session,
+                                    const char *filedata, size_t filedata_len,
+                                    unsigned const char *passphrase)
+{
+    int rc;
+
+    pem_read_bio_func read_ec =
+        (pem_read_bio_func) &PEM_read_bio_ECPrivateKey;
+    (void) session;
+
+    _libssh2_init_if_needed();
+
+    rc = read_private_key_from_memory((void **) ec_ctx, read_ec,
+                                      filedata, filedata_len, passphrase);
+
+    if(rc) {
+        rc = read_openssh_private_key_from_memory((void **)ec_ctx, session,
+                                                  "ssh-ecdsa", filedata,
+                                                  filedata_len, passphrase);
+    }
+
+    return rc;
+}
+
+#endif /* LIBSSH2_ECDSA */
+
+
+#if LIBSSH2_ED25519
+
+int
+_libssh2_curve25519_new(LIBSSH2_SESSION *session, libssh2_x25519_ctx **out_ctx,
+                        unsigned char **out_public_key,
+                        unsigned char **out_private_key)
+{
+    EVP_PKEY *key = NULL;
+    EVP_PKEY_CTX *pctx = NULL;
+    PKCS8_PRIV_KEY_INFO *info = NULL;
+    ASN1_OCTET_STRING *oct = NULL;
+    X509_PUBKEY *pubkey = NULL;
+    libssh2_ed25519_ctx *ctx = NULL;
+    const unsigned char *pkcs, *priv, *pub;
+    int privLen, pubLen, pkcsLen;
+    int rc = -1;
+
+    pctx = EVP_PKEY_CTX_new_id(EVP_PKEY_X25519, NULL);
+    if(pctx == NULL)
+        return -1;
+
+    EVP_PKEY_keygen_init(pctx);
+    EVP_PKEY_keygen(pctx, &key);
+    info = EVP_PKEY2PKCS8(key);
+
+    if(info == NULL || !PKCS8_pkey_get0(NULL, &pkcs, &pkcsLen, NULL, info))
+        goto cleanExit;
+
+    oct = d2i_ASN1_OCTET_STRING(NULL, &pkcs, pkcsLen);
+    if(oct == NULL) {
+        goto cleanExit;
+    }
+
+    priv = ASN1_STRING_get0_data(oct);
+    privLen = ASN1_STRING_length(oct);
+
+    if(privLen != LIBSSH2_ED25519_KEY_LEN)
+        goto cleanExit;
+
+    pubkey = X509_PUBKEY_new();
+    if(pubkey == NULL || !X509_PUBKEY_set(&pubkey, key))
+        goto cleanExit;
+
+    if(!X509_PUBKEY_get0_param(NULL, &pub, &pubLen, NULL, pubkey))
+        goto cleanExit;
+
+    if(pubLen != LIBSSH2_ED25519_KEY_LEN)
+        goto cleanExit;
+
+    if(out_private_key != NULL) {
+        *out_private_key = LIBSSH2_ALLOC(session, LIBSSH2_ED25519_KEY_LEN);
+        if(*out_private_key == NULL)
+            goto cleanExit;
+
+        memcpy(*out_private_key, priv, LIBSSH2_ED25519_KEY_LEN);
+    }
+
+    if(out_public_key != NULL) {
+        *out_public_key = LIBSSH2_ALLOC(session, LIBSSH2_ED25519_KEY_LEN);
+        if(*out_public_key == NULL)
+            goto cleanExit;
+
+        memcpy(*out_public_key, pub, LIBSSH2_ED25519_KEY_LEN);
+    }
+
+    if(out_ctx != NULL) {
+        ctx = malloc(sizeof(libssh2_x25519_ctx));
+        if(ctx == NULL)
+            goto cleanExit;
+
+        ctx->private_key =
+            EVP_PKEY_new_raw_private_key(EVP_PKEY_X25519, NULL,
+                                         (const unsigned char *)priv,
+                                         LIBSSH2_ED25519_KEY_LEN);
+
+        ctx->public_key =
+            EVP_PKEY_new_raw_public_key(EVP_PKEY_X25519, NULL,
+                                        (const unsigned char *)pub,
+                                        LIBSSH2_ED25519_KEY_LEN);
+
+        if(ctx->public_key == NULL || ctx->private_key == NULL) {
+            _libssh2_x25519_free(ctx);
+            goto cleanExit;
+        }
+
+        *out_ctx = ctx;
+    }
+
+    /* success */
+    rc = 0;
+
+cleanExit:
+
+    if(info)
+        PKCS8_PRIV_KEY_INFO_free(info);
+    if(pctx)
+        EVP_PKEY_CTX_free(pctx);
+    if(oct)
+        ASN1_OCTET_STRING_free(oct);
+    if(pubkey)
+        X509_PUBKEY_free(pubkey);
+    if(key)
+        EVP_PKEY_free(key);
+
+    return rc;
+}
+
+static int
+gen_publickey_from_ed25519_openssh_priv_data(LIBSSH2_SESSION *session,
+                                             struct string_buf *decrypted,
+                                             unsigned char **method,
+                                             size_t *method_len,
+                                             unsigned char **pubkeydata,
+                                             size_t *pubkeydata_len,
+                                             libssh2_ed25519_ctx **out_ctx)
+{
+    libssh2_ed25519_ctx *ctx = NULL;
+    unsigned char *method_buf = NULL;
+    unsigned char *key = NULL;
+    int i, ret = 0;
+    unsigned char *pub_key, *priv_key, *buf;
+    size_t key_len = 0, tmp_len = 0;
+    unsigned char *p;
+
+    _libssh2_debug(session,
+                   LIBSSH2_TRACE_AUTH,
+                   "Computing ED25519 keys from private key data");
+
+    if(_libssh2_get_string(decrypted, &pub_key, &tmp_len) ||
+       tmp_len != LIBSSH2_ED25519_KEY_LEN) {
+        _libssh2_error(session, LIBSSH2_ERROR_PROTO,
+                       "Wrong public key length");
+        return -1;
+    }
+
+    if(_libssh2_get_string(decrypted, &priv_key, &tmp_len) ||
+       tmp_len != LIBSSH2_ED25519_PRIVATE_KEY_LEN) {
+        _libssh2_error(session, LIBSSH2_ERROR_PROTO,
+                       "Wrong private key length");
+        ret = -1;
+        goto clean_exit;
+    }
+
+    ctx = _libssh2_ed25519_new_ctx();
+    if(ctx == NULL) {
+        _libssh2_error(session, LIBSSH2_ERROR_ALLOC,
+                       "Unable to allocate memory for ed25519 key");
+        ret = -1;
+        goto clean_exit;
+    }
+
+    /* first 32 bytes of priv_key is the private key, the last 32 bytes are
+       the public key */
+    ctx->private_key =
+        EVP_PKEY_new_raw_private_key(EVP_PKEY_ED25519, NULL,
+                                     (const unsigned char *)priv_key,
+                                     LIBSSH2_ED25519_KEY_LEN);
+
+    ctx->public_key =
+        EVP_PKEY_new_raw_public_key(EVP_PKEY_ED25519, NULL,
+                                    (const unsigned char *)pub_key,
+                                    LIBSSH2_ED25519_KEY_LEN);
+
+    /* comment */
+    if(_libssh2_get_string(decrypted, &buf, &tmp_len)) {
+        _libssh2_error(session, LIBSSH2_ERROR_PROTO,
+                       "Unable to read comment");
+        ret = -1;
+        goto clean_exit;
+    }
+
+    if(tmp_len > 0) {
+        unsigned char *comment = LIBSSH2_CALLOC(session, tmp_len + 1);
+        if(comment != NULL) {
+            memcpy(comment, buf, tmp_len);
+            memcpy(comment + tmp_len, "\0", 1);
+
+            _libssh2_debug(session, LIBSSH2_TRACE_AUTH, "Key comment: %s",
+                           comment);
+
+            LIBSSH2_FREE(session, comment);
+        }
+    }
+
+    /* Padding */
+    i = 1;
+    while(decrypted->dataptr < decrypted->data + decrypted->len) {
+        if(*decrypted->dataptr != i) {
+            _libssh2_error(session, LIBSSH2_ERROR_PROTO,
+                           "Wrong padding");
+            ret = -1;
+            goto clean_exit;
+        }
+        i++;
+        decrypted->dataptr++;
+    }
+
+    if(ret == 0) {
+        _libssh2_debug(session,
+                       LIBSSH2_TRACE_AUTH,
+                       "Computing public key from ED25519 "
+                       "private key envelop");
+
+        method_buf = LIBSSH2_ALLOC(session, 11);  /* ssh-ed25519. */
+        if(method_buf == NULL) {
+            goto clean_exit;
+        }
+
+        /* Key form is: type_len(4) + type(11) + pub_key_len(4) +
+           pub_key(32). */
+        key_len = LIBSSH2_ED25519_KEY_LEN + 19;
+        key = LIBSSH2_CALLOC(session, key_len);
+        if(key == NULL) {
+            goto clean_exit;
+        }
+
+        p = key;
+
+        _libssh2_store_str(&p, "ssh-ed25519", 11);
+        _libssh2_store_str(&p, (const char *)pub_key, LIBSSH2_ED25519_KEY_LEN);
+
+        memcpy(method_buf, "ssh-ed25519", 11);
+
+        if(method != NULL)
+            *method = method_buf;
+        else
+            LIBSSH2_FREE(session, method_buf);
+
+        if(method_len != NULL)
+            *method_len = 11;
+
+        if(pubkeydata != NULL)
+            *pubkeydata = key;
+        else
+            LIBSSH2_FREE(session, key);
+
+        if(pubkeydata_len != NULL)
+            *pubkeydata_len = key_len;
+
+        if(out_ctx != NULL)
+            *out_ctx = ctx;
+        else if(ctx != NULL)
+            _libssh2_ed25519_free(ctx);
+
+        return 0;
+    }
+
+clean_exit:
+
+    if(ctx)
+        _libssh2_ed25519_free(ctx);
+
+    if(method_buf)
+        LIBSSH2_FREE(session, method_buf);
+
+    if(key)
+        LIBSSH2_FREE(session, key);
+
+    return -1;
+}
+
+int
+_libssh2_ed25519_new_private(libssh2_ed25519_ctx ** ed_ctx,
+                             LIBSSH2_SESSION * session,
+                             const char *filename, const uint8_t *passphrase)
+{
+    int rc;
+    FILE *fp;
+    unsigned char *buf;
+    struct string_buf *decrypted = NULL;
+    libssh2_ed25519_ctx *ctx = NULL;
+
+    if(session == NULL) {
+        _libssh2_error(session, LIBSSH2_ERROR_PROTO,
+                       "Session is required");
+        return -1;
+    }
+
+    _libssh2_init_if_needed();
+
+    fp = fopen(filename, "r");
+    if(!fp) {
+        _libssh2_error(session, LIBSSH2_ERROR_FILE,
+                       "Unable to open ED25519 private key file");
+        return -1;
+    }
+
+    rc = _libssh2_openssh_pem_parse(session, passphrase, fp, &decrypted);
+    fclose(fp);
+    if(rc) {
+        return rc;
+    }
+
+    /* We have a new key file, now try and parse it using supported types  */
+    rc = _libssh2_get_string(decrypted, &buf, NULL);
+
+    if(rc != 0 || buf == NULL) {
+        _libssh2_error(session, LIBSSH2_ERROR_PROTO,
+                       "Public key type in decrypted key data not found");
+        return -1;
+    }
+
+    if(strcmp("ssh-ed25519", (const char *)buf) == 0) {
+        rc = gen_publickey_from_ed25519_openssh_priv_data(session,
+                                                          decrypted,
+                                                          NULL,
+                                                          NULL,
+                                                          NULL,
+                                                          NULL,
+                                                          &ctx);
+    }
+    else {
+        rc = -1;
+    }
+
+    if(decrypted)
+        _libssh2_string_buf_free(session, decrypted);
+
+    if(rc == 0) {
+        if(ed_ctx != NULL)
+            *ed_ctx = ctx;
+        else if(ctx != NULL)
+            _libssh2_ed25519_free(ctx);
+    }
+
+    return rc;
+}
+
+int
+_libssh2_ed25519_new_private_frommemory(libssh2_ed25519_ctx ** ed_ctx,
+                                        LIBSSH2_SESSION * session,
+                                        const char *filedata,
+                                        size_t filedata_len,
+                                        unsigned const char *passphrase)
+{
+    return read_openssh_private_key_from_memory((void **)ed_ctx, session,
+                                                "ssh-ed25519",
+                                                filedata, filedata_len,
+                                                passphrase);
+}
+
+int
+_libssh2_ed25519_new_public(libssh2_ed25519_ctx ** ed_ctx,
+                            LIBSSH2_SESSION * session,
+                            const unsigned char *raw_pub_key,
+                            const uint8_t key_len)
+{
+    libssh2_ed25519_ctx *ctx = NULL;
+    EVP_PKEY *public_key = NULL;
+
+    if(ed_ctx == NULL)
+        return -1;
+
+    public_key =
+        EVP_PKEY_new_raw_public_key(EVP_PKEY_ED25519, NULL,
+                                    (const unsigned char *)raw_pub_key,
+                                    key_len);
+    if(public_key == NULL) {
+        return _libssh2_error(session, LIBSSH2_ERROR_PROTO,
+                              "could not create ED25519 public key");
+    }
+
+    ctx = _libssh2_ed25519_new_ctx();
+    if(ctx == NULL) {
+        return _libssh2_error(session, LIBSSH2_ERROR_ALLOC,
+                              "could not alloc public/private key");
+    }
+
+    ctx->public_key = public_key;
+
+    if(ed_ctx != NULL)
+        *ed_ctx = ctx;
+    else if(ctx != NULL)
+        _libssh2_ed25519_free(ctx);
+
+    return 0;
+}
+
+#endif /* LIBSSH2_ED25519 */
+
+int
+_libssh2_rsa_sha1_sign(LIBSSH2_SESSION * session,
+                       libssh2_rsa_ctx * rsactx,
+                       const unsigned char *hash,
+                       size_t hash_len,
+                       unsigned char **signature, size_t *signature_len)
+{
+    int ret;
+    unsigned char *sig;
+    unsigned int sig_len;
+
+    sig_len = RSA_size(rsactx);
+    sig = LIBSSH2_ALLOC(session, sig_len);
+
+    if(!sig) {
+        return -1;
+    }
+
+    ret = RSA_sign(NID_sha1, hash, hash_len, sig, &sig_len, rsactx);
+
+    if(!ret) {
+        LIBSSH2_FREE(session, sig);
+        return -1;
+    }
+
+    *signature = sig;
+    *signature_len = sig_len;
+
+    return 0;
+}
+
+#if LIBSSH2_DSA
+int
+_libssh2_dsa_sha1_sign(libssh2_dsa_ctx * dsactx,
+                       const unsigned char *hash,
+                       unsigned long hash_len, unsigned char *signature)
+{
+    DSA_SIG *sig;
+    const BIGNUM * r;
+    const BIGNUM * s;
+    int r_len, s_len;
+    (void) hash_len;
+
+    sig = DSA_do_sign(hash, SHA_DIGEST_LENGTH, dsactx);
+    if(!sig) {
+        return -1;
+    }
+
+#ifdef HAVE_OPAQUE_STRUCTS
+    DSA_SIG_get0(sig, &r, &s);
+#else
+    r = sig->r;
+    s = sig->s;
+#endif
+    r_len = BN_num_bytes(r);
+    if(r_len < 1 || r_len > 20) {
+        DSA_SIG_free(sig);
+        return -1;
+    }
+    s_len = BN_num_bytes(s);
+    if(s_len < 1 || s_len > 20) {
+        DSA_SIG_free(sig);
+        return -1;
+    }
+
+    memset(signature, 0, 40);
+
+    BN_bn2bin(r, signature + (20 - r_len));
+    BN_bn2bin(s, signature + 20 + (20 - s_len));
+
+    DSA_SIG_free(sig);
+
+    return 0;
+}
+#endif /* LIBSSH_DSA */
+
+#if LIBSSH2_ECDSA
+
+int
+_libssh2_ecdsa_sign(LIBSSH2_SESSION * session, libssh2_ecdsa_ctx * ec_ctx,
+    const unsigned char *hash, unsigned long hash_len,
+    unsigned char **signature, size_t *signature_len)
+{
+    int r_len, s_len;
+    int rc = 0;
+    size_t out_buffer_len = 0;
+    unsigned char *sp;
+    const BIGNUM *pr = NULL, *ps = NULL;
+    unsigned char *temp_buffer = NULL;
+    unsigned char *out_buffer = NULL;
+
+    ECDSA_SIG *sig = ECDSA_do_sign(hash, hash_len, ec_ctx);
+    if(sig == NULL)
+        return -1;
+#ifdef HAVE_OPAQUE_STRUCTS
+    ECDSA_SIG_get0(sig, &pr, &ps);
+#else
+    pr = sig->r;
+    ps = sig->s;
+#endif
+
+    r_len = BN_num_bytes(pr) + 1;
+    s_len = BN_num_bytes(ps) + 1;
+
+    temp_buffer = malloc(r_len + s_len + 8);
+    if(temp_buffer == NULL) {
+        rc = -1;
+        goto clean_exit;
+    }
+
+    sp = temp_buffer;
+    sp = write_bn(sp, pr, r_len);
+    sp = write_bn(sp, ps, s_len);
+
+    out_buffer_len = (size_t)(sp - temp_buffer);
+
+    out_buffer = LIBSSH2_CALLOC(session, out_buffer_len);
+    if(out_buffer == NULL) {
+        rc = -1;
+        goto clean_exit;
+    }
+
+    memcpy(out_buffer, temp_buffer, out_buffer_len);
+
+    *signature = out_buffer;
+    *signature_len = out_buffer_len;
+
+clean_exit:
+
+    if(temp_buffer != NULL)
+        free(temp_buffer);
+
+    if(sig)
+        ECDSA_SIG_free(sig);
+
+    return rc;
+}
+#endif /* LIBSSH2_ECDSA */
+
+int
+_libssh2_sha1_init(libssh2_sha1_ctx *ctx)
+{
+#ifdef HAVE_OPAQUE_STRUCTS
+    *ctx = EVP_MD_CTX_new();
+
+    if(*ctx == NULL)
+        return 0;
+
+    if(EVP_DigestInit(*ctx, EVP_get_digestbyname("sha1")))
+        return 1;
+
+    EVP_MD_CTX_free(*ctx);
+    *ctx = NULL;
+
+    return 0;
+#else
+    EVP_MD_CTX_init(ctx);
+    return EVP_DigestInit(ctx, EVP_get_digestbyname("sha1"));
+#endif
+}
+
+int
+_libssh2_sha1(const unsigned char *message, unsigned long len,
+              unsigned char *out)
+{
+#ifdef HAVE_OPAQUE_STRUCTS
+    EVP_MD_CTX * ctx = EVP_MD_CTX_new();
+
+    if(ctx == NULL)
+        return 1; /* error */
+
+    if(EVP_DigestInit(ctx, EVP_get_digestbyname("sha1"))) {
+        EVP_DigestUpdate(ctx, message, len);
+        EVP_DigestFinal(ctx, out, NULL);
+        EVP_MD_CTX_free(ctx);
+        return 0; /* success */
+    }
+    EVP_MD_CTX_free(ctx);
+#else
+    EVP_MD_CTX ctx;
+
+    EVP_MD_CTX_init(&ctx);
+    if(EVP_DigestInit(&ctx, EVP_get_digestbyname("sha1"))) {
+        EVP_DigestUpdate(&ctx, message, len);
+        EVP_DigestFinal(&ctx, out, NULL);
+        return 0; /* success */
+    }
+#endif
+    return 1; /* error */
+}
+
+int
+_libssh2_sha256_init(libssh2_sha256_ctx *ctx)
+{
+#ifdef HAVE_OPAQUE_STRUCTS
+    *ctx = EVP_MD_CTX_new();
+
+    if(*ctx == NULL)
+        return 0;
+
+    if(EVP_DigestInit(*ctx, EVP_get_digestbyname("sha256")))
+        return 1;
+
+    EVP_MD_CTX_free(*ctx);
+    *ctx = NULL;
+
+    return 0;
+#else
+    EVP_MD_CTX_init(ctx);
+    return EVP_DigestInit(ctx, EVP_get_digestbyname("sha256"));
+#endif
+}
+
+int
+_libssh2_sha256(const unsigned char *message, unsigned long len,
+                unsigned char *out)
+{
+#ifdef HAVE_OPAQUE_STRUCTS
+    EVP_MD_CTX * ctx = EVP_MD_CTX_new();
+
+    if(ctx == NULL)
+        return 1; /* error */
+
+    if(EVP_DigestInit(ctx, EVP_get_digestbyname("sha256"))) {
+        EVP_DigestUpdate(ctx, message, len);
+        EVP_DigestFinal(ctx, out, NULL);
+        EVP_MD_CTX_free(ctx);
+        return 0; /* success */
+    }
+    EVP_MD_CTX_free(ctx);
+#else
+    EVP_MD_CTX ctx;
+
+    EVP_MD_CTX_init(&ctx);
+    if(EVP_DigestInit(&ctx, EVP_get_digestbyname("sha256"))) {
+        EVP_DigestUpdate(&ctx, message, len);
+        EVP_DigestFinal(&ctx, out, NULL);
+        return 0; /* success */
+    }
+#endif
+    return 1; /* error */
+}
+
+int
+_libssh2_sha384_init(libssh2_sha384_ctx *ctx)
+{
+#ifdef HAVE_OPAQUE_STRUCTS
+    *ctx = EVP_MD_CTX_new();
+
+    if(*ctx == NULL)
+        return 0;
+
+    if(EVP_DigestInit(*ctx, EVP_get_digestbyname("sha384")))
+        return 1;
+
+    EVP_MD_CTX_free(*ctx);
+    *ctx = NULL;
+
+    return 0;
+#else
+    EVP_MD_CTX_init(ctx);
+    return EVP_DigestInit(ctx, EVP_get_digestbyname("sha384"));
+#endif
+}
+
+int
+_libssh2_sha384(const unsigned char *message, unsigned long len,
+    unsigned char *out)
+{
+#ifdef HAVE_OPAQUE_STRUCTS
+    EVP_MD_CTX * ctx = EVP_MD_CTX_new();
+
+    if(ctx == NULL)
+        return 1; /* error */
+
+    if(EVP_DigestInit(ctx, EVP_get_digestbyname("sha384"))) {
+        EVP_DigestUpdate(ctx, message, len);
+        EVP_DigestFinal(ctx, out, NULL);
+        EVP_MD_CTX_free(ctx);
+        return 0; /* success */
+    }
+    EVP_MD_CTX_free(ctx);
+#else
+    EVP_MD_CTX ctx;
+
+    EVP_MD_CTX_init(&ctx);
+    if(EVP_DigestInit(&ctx, EVP_get_digestbyname("sha384"))) {
+        EVP_DigestUpdate(&ctx, message, len);
+        EVP_DigestFinal(&ctx, out, NULL);
+        return 0; /* success */
+    }
+#endif
+    return 1; /* error */
+}
+
+int
+_libssh2_sha512_init(libssh2_sha512_ctx *ctx)
+{
+#ifdef HAVE_OPAQUE_STRUCTS
+    *ctx = EVP_MD_CTX_new();
+
+    if(*ctx == NULL)
+        return 0;
+
+    if(EVP_DigestInit(*ctx, EVP_get_digestbyname("sha512")))
+        return 1;
+
+    EVP_MD_CTX_free(*ctx);
+    *ctx = NULL;
+
+    return 0;
+#else
+    EVP_MD_CTX_init(ctx);
+    return EVP_DigestInit(ctx, EVP_get_digestbyname("sha512"));
+#endif
+}
+
+int
+_libssh2_sha512(const unsigned char *message, unsigned long len,
+    unsigned char *out)
+{
+#ifdef HAVE_OPAQUE_STRUCTS
+    EVP_MD_CTX * ctx = EVP_MD_CTX_new();
+
+    if(ctx == NULL)
+        return 1; /* error */
+
+    if(EVP_DigestInit(ctx, EVP_get_digestbyname("sha512"))) {
+        EVP_DigestUpdate(ctx, message, len);
+        EVP_DigestFinal(ctx, out, NULL);
+        EVP_MD_CTX_free(ctx);
+        return 0; /* success */
+    }
+    EVP_MD_CTX_free(ctx);
+#else
+    EVP_MD_CTX ctx;
+
+    EVP_MD_CTX_init(&ctx);
+    if(EVP_DigestInit(&ctx, EVP_get_digestbyname("sha512"))) {
+        EVP_DigestUpdate(&ctx, message, len);
+        EVP_DigestFinal(&ctx, out, NULL);
+        return 0; /* success */
+    }
+#endif
+    return 1; /* error */
+}
+
+int
+_libssh2_md5_init(libssh2_md5_ctx *ctx)
+{
+#ifdef HAVE_OPAQUE_STRUCTS
+    *ctx = EVP_MD_CTX_new();
+
+    if(*ctx == NULL)
+        return 0;
+
+    if(EVP_DigestInit(*ctx, EVP_get_digestbyname("md5")))
+        return 1;
+
+    EVP_MD_CTX_free(*ctx);
+    *ctx = NULL;
+
+    return 0;
+#else
+    EVP_MD_CTX_init(ctx);
+    return EVP_DigestInit(ctx, EVP_get_digestbyname("md5"));
+#endif
+}
+
+#if LIBSSH2_ECDSA
+
+static int
+gen_publickey_from_ec_evp(LIBSSH2_SESSION *session,
+                          unsigned char **method,
+                          size_t *method_len,
+                          unsigned char **pubkeydata,
+                          size_t *pubkeydata_len,
+                          EVP_PKEY *pk)
+{
+    int rc = 0;
+    EC_KEY *ec = NULL;
+    unsigned char *p;
+    unsigned char *method_buf = NULL;
+    unsigned char *key;
+    size_t  key_len = 0;
+    unsigned char *octal_value = NULL;
+    size_t octal_len;
+    const EC_POINT *public_key;
+    const EC_GROUP *group;
+    BN_CTX *bn_ctx;
+    libssh2_curve_type type;
+
+    _libssh2_debug(session,
+       LIBSSH2_TRACE_AUTH,
+       "Computing public key from EC private key envelop");
+
+    bn_ctx = BN_CTX_new();
+    if(bn_ctx == NULL)
+        return -1;
+
+    ec = EVP_PKEY_get1_EC_KEY(pk);
+    if(ec == NULL) {
+        rc = -1;
+        goto clean_exit;
+    }
+
+    public_key = EC_KEY_get0_public_key(ec);
+    group = EC_KEY_get0_group(ec);
+    type = _libssh2_ecdsa_key_get_curve_type(ec);
+
+    method_buf = LIBSSH2_ALLOC(session, 19);
+    if(method_buf == NULL) {
+        return _libssh2_error(session, LIBSSH2_ERROR_ALLOC,
+            "out of memory");
+    }
+
+    if(type == LIBSSH2_EC_CURVE_NISTP256)
+        memcpy(method_buf, "ecdsa-sha2-nistp256", 19);
+    else if(type == LIBSSH2_EC_CURVE_NISTP384)
+        memcpy(method_buf, "ecdsa-sha2-nistp384", 19);
+    else if(type == LIBSSH2_EC_CURVE_NISTP521)
+        memcpy(method_buf, "ecdsa-sha2-nistp521", 19);
+    else {
+        _libssh2_debug(session,
+            LIBSSH2_TRACE_ERROR,
+            "Unsupported EC private key type");
+        rc = -1;
+        goto clean_exit;
+    }
+
+    /* get length */
+    octal_len = EC_POINT_point2oct(group, public_key,
+                                   POINT_CONVERSION_UNCOMPRESSED,
+                                   NULL, 0, bn_ctx);
+    if(octal_len > EC_MAX_POINT_LEN) {
+        rc = -1;
+        goto clean_exit;
+    }
+
+    octal_value = malloc(octal_len);
+    if(octal_value == NULL) {
+        rc = -1;
+        goto clean_exit;
+    }
+
+    /* convert to octal */
+    if(EC_POINT_point2oct(group, public_key, POINT_CONVERSION_UNCOMPRESSED,
+       octal_value, octal_len, bn_ctx) != octal_len) {
+           rc = -1;
+           goto clean_exit;
+    }
+
+    /* Key form is: type_len(4) + type(19) + domain_len(4) + domain(8) +
+       pub_key_len(4) + pub_key(~65). */
+    key_len = 4 + 19 + 4 + 8 + 4 + octal_len;
+    key = LIBSSH2_ALLOC(session, key_len);
+    if(key == NULL) {
+        rc = -1;
+        goto  clean_exit;
+    }
+
+    /* Process key encoding. */
+    p = key;
+
+    /* Key type */
+    _libssh2_store_str(&p, (const char *)method_buf, 19);
+
+    /* Name domain */
+    _libssh2_store_str(&p, (const char *)method_buf + 11, 8);
+
+    /* Public key */
+    _libssh2_store_str(&p, (const char *)octal_value, octal_len);
+
+    *method         = method_buf;
+    *method_len     = 19;
+    *pubkeydata     = key;
+    *pubkeydata_len = key_len;
+
+clean_exit:
+
+    if(ec != NULL)
+        EC_KEY_free(ec);
+
+    if(bn_ctx != NULL) {
+        BN_CTX_free(bn_ctx);
+    }
+
+    if(octal_value != NULL)
+        free(octal_value);
+
+    if(rc == 0)
+        return 0;
+
+    if(method_buf != NULL)
+        LIBSSH2_FREE(session, method_buf);
+
+    return -1;
+}
+
+static int
+gen_publickey_from_ecdsa_openssh_priv_data(LIBSSH2_SESSION *session,
+                                           libssh2_curve_type curve_type,
+                                           struct string_buf *decrypted,
+                                           unsigned char **method,
+                                           size_t *method_len,
+                                           unsigned char **pubkeydata,
+                                           size_t *pubkeydata_len,
+                                           libssh2_ecdsa_ctx **ec_ctx)
+{
+    int rc = 0;
+    size_t curvelen, exponentlen, pointlen;
+    unsigned char *curve, *exponent, *point_buf;
+    EC_KEY *ec_key = NULL;
+    BIGNUM *bn_exponent;
+
+    _libssh2_debug(session,
+                   LIBSSH2_TRACE_AUTH,
+                   "Computing ECDSA keys from private key data");
+
+    if(_libssh2_get_string(decrypted, &curve, &curvelen) ||
+        curvelen == 0) {
+        _libssh2_error(session, LIBSSH2_ERROR_PROTO,
+                       "ECDSA no curve");
+        return -1;
+    }
+
+    if(_libssh2_get_string(decrypted, &point_buf, &pointlen)) {
+        _libssh2_error(session, LIBSSH2_ERROR_PROTO,
+                       "ECDSA no point");
+        return -1;
+    }
+
+    if(_libssh2_get_bignum_bytes(decrypted, &exponent, &exponentlen)) {
+        _libssh2_error(session, LIBSSH2_ERROR_PROTO,
+                       "ECDSA no exponent");
+        return -1;
+    }
+
+    if((rc = _libssh2_ecdsa_curve_name_with_octal_new(&ec_key, point_buf,
+        pointlen, curve_type)) != 0) {
+        _libssh2_error(session, LIBSSH2_ERROR_PROTO,
+                       "ECDSA could not create key");
+        goto fail;
+    }
+
+    bn_exponent = BN_new();
+    if(bn_exponent == NULL) {
+        rc = -1;
+        goto fail;
+    }
+
+    BN_bin2bn(exponent, exponentlen, bn_exponent);
+    rc = (EC_KEY_set_private_key(ec_key, bn_exponent) != 1);
+
+    if(rc == 0 && ec_key != NULL && pubkeydata != NULL && method != NULL) {
+        EVP_PKEY *pk = EVP_PKEY_new();
+        EVP_PKEY_set1_EC_KEY(pk, ec_key);
+
+        rc = gen_publickey_from_ec_evp(session, method, method_len,
+                                       pubkeydata, pubkeydata_len,
+                                       pk);
+
+        if(pk)
+            EVP_PKEY_free(pk);
+    }
+
+    if(ec_ctx != NULL)
+        *ec_ctx = ec_key;
+    else
+        EC_KEY_free(ec_key);
+
+    return rc;
+
+fail:
+
+    if(ec_key != NULL)
+        EC_KEY_free(ec_key);
+
+    return _libssh2_error(session,
+                          LIBSSH2_ERROR_ALLOC,
+                          "Unable to allocate memory for private key data");
+
+
+}
+
+static int
+_libssh2_ecdsa_new_openssh_private(libssh2_ecdsa_ctx ** ec_ctx,
+                                   LIBSSH2_SESSION * session,
+                                   const char *filename,
+                                   unsigned const char *passphrase)
+{
+    FILE *fp;
+    int rc;
+    unsigned char *buf = NULL;
+    libssh2_curve_type type;
+    struct string_buf *decrypted = NULL;
+
+    if(session == NULL) {
+        _libssh2_error(session, LIBSSH2_ERROR_PROTO,
+                           "Session is required");
+        return -1;
+    }
+
+    _libssh2_init_if_needed();
+
+    fp = fopen(filename, "r");
+    if(!fp) {
+        _libssh2_error(session, LIBSSH2_ERROR_FILE,
+                       "Unable to open OpenSSH ECDSA private key file");
+        return -1;
+    }
+
+    rc = _libssh2_openssh_pem_parse(session, passphrase, fp, &decrypted);
+    fclose(fp);
+    if(rc) {
+        return rc;
+    }
+
+    /* We have a new key file, now try and parse it using supported types  */
+    rc = _libssh2_get_string(decrypted, &buf, NULL);
+
+    if(rc != 0 || buf == NULL) {
+        _libssh2_error(session, LIBSSH2_ERROR_PROTO,
+                       "Public key type in decrypted key data not found");
+        return -1;
+    }
+
+    rc = _libssh2_ecdsa_curve_type_from_name((const char *)buf, &type);
+
+    if(rc == 0) {
+        rc = gen_publickey_from_ecdsa_openssh_priv_data(session, type,
+                                                        decrypted, NULL, 0,
+                                                        NULL, 0, ec_ctx);
+    }
+    else {
+        rc = -1;
+    }
+
+    if(decrypted)
+        _libssh2_string_buf_free(session, decrypted);
+
+    return rc;
+}
+
+int
+_libssh2_ecdsa_new_private(libssh2_ecdsa_ctx ** ec_ctx,
+       LIBSSH2_SESSION * session,
+       const char *filename, unsigned const char *passphrase)
+{
+    int rc;
+
+    pem_read_bio_func read_ec = (pem_read_bio_func) &PEM_read_bio_ECPrivateKey;
+    (void) session;
+
+    _libssh2_init_if_needed();
+
+    rc = read_private_key_from_file((void **) ec_ctx, read_ec,
+      filename, passphrase);
+
+    if(rc) {
+        return _libssh2_ecdsa_new_openssh_private(ec_ctx, session,
+                                                  filename, passphrase);
+    }
+
+    return rc;
+}
+
+/*
+ * _libssh2_ecdsa_create_key
+ *
+ * Creates a local private key based on input curve
+ * and returns octal value and octal length
+ *
+ */
+
+int
+_libssh2_ecdsa_create_key(LIBSSH2_SESSION *session,
+                          _libssh2_ec_key **out_private_key,
+                          unsigned char **out_public_key_octal,
+                          size_t *out_public_key_octal_len,
+                          libssh2_curve_type curve_type)
+{
+    int ret = 1;
+    size_t octal_len = 0;
+    unsigned char octal_value[EC_MAX_POINT_LEN];
+    const EC_POINT *public_key = NULL;
+    EC_KEY *private_key = NULL;
+    const EC_GROUP *group = NULL;
+
+    /* create key */
+    BN_CTX *bn_ctx = BN_CTX_new();
+    if(!bn_ctx)
+        return -1;
+
+    private_key = EC_KEY_new_by_curve_name(curve_type);
+    group = EC_KEY_get0_group(private_key);
+
+    EC_KEY_generate_key(private_key);
+    public_key = EC_KEY_get0_public_key(private_key);
+
+    /* get length */
+    octal_len = EC_POINT_point2oct(group, public_key,
+                                   POINT_CONVERSION_UNCOMPRESSED,
+                                   NULL, 0, bn_ctx);
+    if(octal_len > EC_MAX_POINT_LEN) {
+        ret = -1;
+        goto clean_exit;
+    }
+
+    /* convert to octal */
+    if(EC_POINT_point2oct(group, public_key, POINT_CONVERSION_UNCOMPRESSED,
+       octal_value, octal_len, bn_ctx) != octal_len) {
+           ret = -1;
+           goto clean_exit;
+    }
+
+    if(out_private_key != NULL)
+        *out_private_key = private_key;
+
+    if(out_public_key_octal) {
+        *out_public_key_octal = LIBSSH2_ALLOC(session, octal_len);
+        if(*out_public_key_octal == NULL) {
+            ret = -1;
+            goto clean_exit;
+        }
+
+        memcpy(*out_public_key_octal, octal_value, octal_len);
+    }
+
+    if(out_public_key_octal_len != NULL)
+        *out_public_key_octal_len = octal_len;
+
+clean_exit:
+
+    if(bn_ctx)
+        BN_CTX_free(bn_ctx);
+
+    return (ret == 1) ? 0 : -1;
+}
+
+/* _libssh2_ecdh_gen_k
+ *
+ * Computes the shared secret K given a local private key,
+ * remote public key and length
+ */
+
+int
+_libssh2_ecdh_gen_k(_libssh2_bn **k, _libssh2_ec_key *private_key,
+    const unsigned char *server_public_key, size_t server_public_key_len)
+{
+    int ret = 0;
+    int rc;
+    size_t secret_len;
+    unsigned char *secret = NULL;
+    const EC_GROUP *private_key_group;
+    EC_POINT *server_public_key_point;
+
+    BN_CTX *bn_ctx = BN_CTX_new();
+
+    if(!bn_ctx)
+        return -1;
+
+    if(k == NULL)
+        return -1;
+
+    private_key_group = EC_KEY_get0_group(private_key);
+
+    server_public_key_point = EC_POINT_new(private_key_group);
+    if(server_public_key_point == NULL)
+        return -1;
+
+    rc = EC_POINT_oct2point(private_key_group, server_public_key_point,
+                            server_public_key, server_public_key_len, bn_ctx);
+    if(rc != 1) {
+        ret = -1;
+        goto clean_exit;
+    }
+
+    secret_len = (EC_GROUP_get_degree(private_key_group) + 7) / 8;
+    secret = malloc(secret_len);
+    if(!secret) {
+        ret = -1;
+        goto clean_exit;
+    }
+
+    secret_len = ECDH_compute_key(secret, secret_len, server_public_key_point,
+                                  private_key, NULL);
+
+    if(secret_len <= 0 || secret_len > EC_MAX_POINT_LEN) {
+        ret = -1;
+        goto clean_exit;
+    }
+
+    BN_bin2bn(secret, secret_len, *k);
+
+clean_exit:
+
+    if(server_public_key_point != NULL)
+        EC_POINT_free(server_public_key_point);
+
+    if(bn_ctx != NULL)
+        BN_CTX_free(bn_ctx);
+
+    if(secret != NULL)
+        free(secret);
+
+    return ret;
+}
+
+
+#endif /* LIBSSH2_ECDSA */
+
+#if LIBSSH2_ED25519
+
+int
+_libssh2_ed25519_sign(libssh2_ed25519_ctx *ctx, LIBSSH2_SESSION *session,
+                      uint8_t **out_sig, size_t *out_sig_len,
+                      const uint8_t *message, size_t message_len)
+{
+    int rc = -1;
+    EVP_MD_CTX *md_ctx = EVP_MD_CTX_new();
+    size_t sig_len = 0;
+    unsigned char *sig = NULL;
+
+    if(md_ctx != NULL) {
+        if(EVP_DigestSignInit(md_ctx, NULL, NULL, NULL, ctx->private_key) != 1)
+            goto clean_exit;
+        if(EVP_DigestSign(md_ctx, NULL, &sig_len, message, message_len) != 1)
+            goto clean_exit;
+
+        if(sig_len != LIBSSH2_ED25519_SIG_LEN)
+            goto clean_exit;
+
+        sig = LIBSSH2_CALLOC(session, sig_len);
+        if(sig == NULL)
+            goto clean_exit;
+
+        rc = EVP_DigestSign(md_ctx, sig, &sig_len, message, message_len);
+    }
+
+    if(rc == 1) {
+        *out_sig = sig;
+        *out_sig_len = sig_len;
+    }
+    else {
+        *out_sig_len = 0;
+        *out_sig = NULL;
+        LIBSSH2_FREE(session, sig);
+    }
+
+clean_exit:
+
+    if(md_ctx)
+        EVP_MD_CTX_free(md_ctx);
+
+    return (rc == 1 ? 0 : -1);
+}
+
+int
+_libssh2_curve25519_gen_k(_libssh2_bn **k,
+                          uint8_t private_key[LIBSSH2_ED25519_KEY_LEN],
+                          uint8_t server_public_key[LIBSSH2_ED25519_KEY_LEN])
+{
+    int rc = -1;
+    unsigned char out_shared_key[LIBSSH2_ED25519_KEY_LEN];
+    EVP_PKEY *peer_key = NULL, *server_key = NULL;
+    EVP_PKEY_CTX *server_key_ctx = NULL;
+    BN_CTX *bn_ctx = NULL;
+    size_t out_len = 0;
+
+    if(k == NULL || *k == NULL)
+        return -1;
+
+    bn_ctx = BN_CTX_new();
+    if(bn_ctx == NULL)
+        return -1;
+
+    peer_key = EVP_PKEY_new_raw_public_key(EVP_PKEY_X25519, NULL,
+                                           server_public_key,
+                                           LIBSSH2_ED25519_KEY_LEN);
+
+    server_key = EVP_PKEY_new_raw_private_key(EVP_PKEY_X25519, NULL,
+                                              private_key,
+                                              LIBSSH2_ED25519_KEY_LEN);
+
+    if(peer_key == NULL || server_key == NULL) {
+        goto cleanExit;
+    }
+
+    server_key_ctx = EVP_PKEY_CTX_new(server_key, NULL);
+    if(server_key_ctx == NULL) {
+        goto cleanExit;
+    }
+
+    rc = EVP_PKEY_derive_init(server_key_ctx);
+    if(rc <= 0) goto cleanExit;
+
+    rc = EVP_PKEY_derive_set_peer(server_key_ctx, peer_key);
+    if(rc <= 0) goto cleanExit;
+
+    rc = EVP_PKEY_derive(server_key_ctx, NULL, &out_len);
+    if(rc <= 0) goto cleanExit;
+
+    if(out_len != LIBSSH2_ED25519_KEY_LEN) {
+        rc = -1;
+        goto cleanExit;
+    }
+
+    rc = EVP_PKEY_derive(server_key_ctx, out_shared_key, &out_len);
+
+    if(rc == 1 && out_len == LIBSSH2_ED25519_KEY_LEN) {
+        BN_bin2bn(out_shared_key, LIBSSH2_ED25519_KEY_LEN, *k);
+    }
+    else {
+        rc = -1;
+    }
+
+cleanExit:
+
+    if(server_key_ctx)
+        EVP_PKEY_CTX_free(server_key_ctx);
+    if(peer_key)
+        EVP_PKEY_free(peer_key);
+    if(server_key)
+        EVP_PKEY_free(server_key);
+    if(bn_ctx != NULL)
+        BN_CTX_free(bn_ctx);
+
+    return (rc == 1) ? 0 : -1;
+}
+
+
+int
+_libssh2_ed25519_verify(libssh2_ed25519_ctx *ctx, const uint8_t *s,
+                        size_t s_len, const uint8_t *m, size_t m_len)
+{
+    int ret = -1;
+
+    EVP_MD_CTX *md_ctx = EVP_MD_CTX_new();
+    if(NULL == md_ctx)
+        return -1;
+
+    ret = EVP_DigestVerifyInit(md_ctx, NULL, NULL, NULL, ctx->public_key);
+    if(ret != 1)
+        goto clean_exit;
+
+    ret = EVP_DigestVerify(md_ctx, s, s_len, m, m_len);
+
+    clean_exit:
+
+    EVP_MD_CTX_free(md_ctx);
+
+    return (ret == 1) ? 0 : -1;
+}
+
+#endif /* LIBSSH2_ED25519 */
+
+static int
+_libssh2_pub_priv_openssh_keyfile(LIBSSH2_SESSION *session,
+                                  unsigned char **method,
+                                  size_t *method_len,
+                                  unsigned char **pubkeydata,
+                                  size_t *pubkeydata_len,
+                                  const char *privatekey,
+                                  const char *passphrase)
+{
+    FILE *fp;
+    unsigned char *buf = NULL;
+    struct string_buf *decrypted = NULL;
+    int rc = 0;
+
+    if(session == NULL) {
+        _libssh2_error(session, LIBSSH2_ERROR_PROTO,
+                       "Session is required");
+        return -1;
+    }
+
+    _libssh2_init_if_needed();
+
+    fp = fopen(privatekey, "r");
+    if(!fp) {
+        _libssh2_error(session, LIBSSH2_ERROR_FILE,
+                       "Unable to open private key file");
+        return -1;
+    }
+
+    rc = _libssh2_openssh_pem_parse(session, (const unsigned char *)passphrase,
+                                    fp, &decrypted);
+    fclose(fp);
+    if(rc) {
+        _libssh2_error(session, LIBSSH2_ERROR_FILE,
+                       "Not an OpenSSH key file");
+        return rc;
+    }
+
+    /* We have a new key file, now try and parse it using supported types  */
+    rc = _libssh2_get_string(decrypted, &buf, NULL);
+
+    if(rc != 0 || buf == NULL) {
+        _libssh2_error(session, LIBSSH2_ERROR_PROTO,
+                       "Public key type in decrypted key data not found");
+        return -1;
+    }
+
+    rc = -1;
+
+#if LIBSSH2_ED25519
+    if(strcmp("ssh-ed25519", (const char *)buf) == 0) {
+        rc = gen_publickey_from_ed25519_openssh_priv_data(session, decrypted,
+                                                          method, method_len,
+                                                          pubkeydata,
+                                                          pubkeydata_len,
+                                                          NULL);
+    }
+#endif
+#if LIBSSH2_RSA
+    if(strcmp("ssh-rsa", (const char *)buf) == 0) {
+        rc = gen_publickey_from_rsa_openssh_priv_data(session, decrypted,
+                                                      method, method_len,
+                                                      pubkeydata,
+                                                      pubkeydata_len,
+                                                      NULL);
+    }
+#endif
+#if LIBSSH2_DSA
+    if(strcmp("ssh-dss", (const char *)buf) == 0) {
+        rc = gen_publickey_from_dsa_openssh_priv_data(session, decrypted,
+                                                      method, method_len,
+                                                      pubkeydata,
+                                                      pubkeydata_len,
+                                                      NULL);
+    }
+#endif
+#if LIBSSH2_ECDSA
+    {
+        libssh2_curve_type type;
+
+        if(_libssh2_ecdsa_curve_type_from_name((const char *)buf,
+                                               &type) == 0) {
+            rc = gen_publickey_from_ecdsa_openssh_priv_data(session, type,
+                                                            decrypted,
+                                                            method, method_len,
+                                                            pubkeydata,
+                                                            pubkeydata_len,
+                                                            NULL);
+        }
+    }
+#endif
+
+    if(decrypted)
+        _libssh2_string_buf_free(session, decrypted);
+
+    if(rc != 0) {
+        _libssh2_error(session, LIBSSH2_ERROR_FILE,
+                       "Unsupported OpenSSH key type");
+    }
+
+    return rc;
+}
+
+int
+_libssh2_pub_priv_keyfile(LIBSSH2_SESSION *session,
+                          unsigned char **method,
+                          size_t *method_len,
+                          unsigned char **pubkeydata,
+                          size_t *pubkeydata_len,
+                          const char *privatekey,
+                          const char *passphrase)
+{
+    int       st;
+    BIO*      bp;
+    EVP_PKEY* pk;
+    int       pktype;
+    int       rc;
+
+    _libssh2_debug(session,
+                   LIBSSH2_TRACE_AUTH,
+                   "Computing public key from private key file: %s",
+                   privatekey);
+
+    bp = BIO_new_file(privatekey, "r");
+    if(bp == NULL) {
+        return _libssh2_error(session,
+                              LIBSSH2_ERROR_FILE,
+                              "Unable to extract public key from private key "
+                              "file: Unable to open private key file");
+    }
+
+    BIO_reset(bp);
+    pk = PEM_read_bio_PrivateKey(bp, NULL, NULL, (void *)passphrase);
+    BIO_free(bp);
+
+    if(pk == NULL) {
+
+        /* Try OpenSSH format */
+        rc = _libssh2_pub_priv_openssh_keyfile(session,
+                                               method,
+                                               method_len,
+                                               pubkeydata, pubkeydata_len,
+                                               privatekey, passphrase);
+        if(rc != 0) {
+            return _libssh2_error(session,
+                                  LIBSSH2_ERROR_FILE,
+                                  "Unable to extract public key "
+                                  "from private key file: "
+                                  "Wrong passphrase or invalid/unrecognized "
+                                  "private key file format");
+        }
+
+        return 0;
+    }
+
+#ifdef HAVE_OPAQUE_STRUCTS
+    pktype = EVP_PKEY_id(pk);
+#else
+    pktype = pk->type;
+#endif
+
+    switch(pktype) {
+    case EVP_PKEY_RSA :
+        st = gen_publickey_from_rsa_evp(
+            session, method, method_len, pubkeydata, pubkeydata_len, pk);
+        break;
+
+#if LIBSSH2_DSA
+    case EVP_PKEY_DSA :
+        st = gen_publickey_from_dsa_evp(
+            session, method, method_len, pubkeydata, pubkeydata_len, pk);
+        break;
+#endif /* LIBSSH_DSA */
+
+#if LIBSSH2_ECDSA
+    case EVP_PKEY_EC :
+        st = gen_publickey_from_ec_evp(
+            session, method, method_len, pubkeydata, pubkeydata_len, pk);
+    break;
+#endif
+
+    default :
+        st = _libssh2_error(session,
+                            LIBSSH2_ERROR_FILE,
+                            "Unable to extract public key "
+                            "from private key file: "
+                            "Unsupported private key file format");
+        break;
+    }
+
+    EVP_PKEY_free(pk);
+    return st;
+}
+
+static int
+_libssh2_pub_priv_openssh_keyfilememory(LIBSSH2_SESSION *session,
+                                        void **key_ctx,
+                                        const char *key_type,
+                                        unsigned char **method,
+                                        size_t *method_len,
+                                        unsigned char **pubkeydata,
+                                        size_t *pubkeydata_len,
+                                        const char *privatekeydata,
+                                        size_t privatekeydata_len,
+                                        unsigned const char *passphrase)
+{
+    int rc;
+    unsigned char *buf = NULL;
+    struct string_buf *decrypted = NULL;
+
+    if(key_ctx != NULL)
+        *key_ctx = NULL;
+
+    if(session == NULL) {
+        _libssh2_error(session, LIBSSH2_ERROR_PROTO,
+                       "Session is required");
+        return -1;
+    }
+
+    if(key_type != NULL && (strlen(key_type) > 11 || strlen(key_type) < 7)) {
+        _libssh2_error(session, LIBSSH2_ERROR_PROTO,
+                       "type is invalid");
+        return -1;
+    }
+
+    _libssh2_init_if_needed();
+
+    rc = _libssh2_openssh_pem_parse_memory(session, passphrase,
+                                           privatekeydata,
+                                           privatekeydata_len, &decrypted);
+
+    if(rc) {
+        return rc;
+    }
+
+   /* We have a new key file, now try and parse it using supported types  */
+   rc = _libssh2_get_string(decrypted, &buf, NULL);
+
+   if(rc != 0 || buf == NULL) {
+       _libssh2_error(session, LIBSSH2_ERROR_PROTO,
+                      "Public key type in decrypted key data not found");
+       return -1;
+   }
+
+   rc = -1;
+
+#if LIBSSH2_ED25519
+    if(strcmp("ssh-ed25519", (const char *)buf) == 0) {
+        if(key_type == NULL || strcmp("ssh-ed25519", key_type) == 0) {
+            rc = gen_publickey_from_ed25519_openssh_priv_data(session,
+                                                              decrypted,
+                                                              method,
+                                                              method_len,
+                                                              pubkeydata,
+                                                              pubkeydata_len,
+                                              (libssh2_ed25519_ctx**)key_ctx);
+        }
+   }
+#endif
+#if LIBSSH2_RSA
+    if(strcmp("ssh-rsa", (const char *)buf) == 0) {
+        if(key_type == NULL || strcmp("ssh-rsa", key_type) == 0) {
+            rc = gen_publickey_from_rsa_openssh_priv_data(session, decrypted,
+                                                          method, method_len,
+                                                          pubkeydata,
+                                                          pubkeydata_len,
+                                                (libssh2_rsa_ctx**)key_ctx);
+        }
+   }
+#endif
+#if LIBSSH2_DSA
+    if(strcmp("ssh-dss", (const char *)buf) == 0) {
+        if(key_type == NULL || strcmp("ssh-dss", key_type) == 0) {
+            rc = gen_publickey_from_dsa_openssh_priv_data(session, decrypted,
+                                                         method, method_len,
+                                                          pubkeydata,
+                                                          pubkeydata_len,
+                                                 (libssh2_dsa_ctx**)key_ctx);
+        }
+   }
+#endif
+#if LIBSSH2_ECDSA
+{
+   libssh2_curve_type type;
+
+   if(_libssh2_ecdsa_curve_type_from_name((const char *)buf, &type) == 0) {
+       if(key_type == NULL || strcmp("ssh-ecdsa", key_type) == 0) {
+           rc = gen_publickey_from_ecdsa_openssh_priv_data(session, type,
+                                                           decrypted,
+                                                           method, method_len,
+                                                           pubkeydata,
+                                                           pubkeydata_len,
+                                               (libssh2_ecdsa_ctx**)key_ctx);
+        }
+    }
+}
+#endif
+
+    if(decrypted)
+        _libssh2_string_buf_free(session, decrypted);
+
+    return rc;
+}
+
+int
+read_openssh_private_key_from_memory(void **key_ctx, LIBSSH2_SESSION *session,
+                                     const char *key_type,
+                                     const char *filedata,
+                                     size_t filedata_len,
+                                     unsigned const char *passphrase)
+{
+    return _libssh2_pub_priv_openssh_keyfilememory(session, key_ctx, key_type,
+                                                   NULL, NULL, NULL, NULL,
+                                                   filedata, filedata_len,
+                                                   passphrase);
+}
+
+int
+_libssh2_pub_priv_keyfilememory(LIBSSH2_SESSION *session,
+                                unsigned char **method,
+                                size_t *method_len,
+                                unsigned char **pubkeydata,
+                                size_t *pubkeydata_len,
+                                const char *privatekeydata,
+                                size_t privatekeydata_len,
+                                const char *passphrase)
+{
+    int       st;
+    BIO*      bp;
+    EVP_PKEY* pk;
+    int       pktype;
+
+    _libssh2_debug(session,
+                   LIBSSH2_TRACE_AUTH,
+                   "Computing public key from private key.");
+
+    bp = BIO_new_mem_buf((char *)privatekeydata, privatekeydata_len);
+    if(!bp) {
+        return -1;
+    }
+
+    BIO_reset(bp);
+    pk = PEM_read_bio_PrivateKey(bp, NULL, NULL, (void *)passphrase);
+    BIO_free(bp);
+
+    if(pk == NULL) {
+        /* Try OpenSSH format */
+        st = _libssh2_pub_priv_openssh_keyfilememory(session, NULL, NULL,
+                                                     method,
+                                                     method_len,
+                                                     pubkeydata,
+                                                     pubkeydata_len,
+                                                     privatekeydata,
+                                                     privatekeydata_len,
+                                           (unsigned const char *)passphrase);
+        if(st != 0) {
+            return _libssh2_error(session,
+                                  LIBSSH2_ERROR_FILE,
+                                  "Unable to extract public key "
+                                  "from private key file: "
+                                  "Wrong passphrase or invalid/unrecognized "
+                                  "private key file format");
+        }
+
+        return 0;
+    }
+
+#ifdef HAVE_OPAQUE_STRUCTS
+    pktype = EVP_PKEY_id(pk);
+#else
+    pktype = pk->type;
+#endif
+
+    switch(pktype) {
+    case EVP_PKEY_RSA :
+        st = gen_publickey_from_rsa_evp(session, method, method_len,
+                                        pubkeydata, pubkeydata_len, pk);
+        break;
+#if LIBSSH2_DSA
+    case EVP_PKEY_DSA :
+        st = gen_publickey_from_dsa_evp(session, method, method_len,
+                                        pubkeydata, pubkeydata_len, pk);
+        break;
+#endif /* LIBSSH_DSA */
+#if LIBSSH2_ECDSA
+    case EVP_PKEY_EC :
+        st = gen_publickey_from_ec_evp(session, method, method_len,
+                                       pubkeydata, pubkeydata_len, pk);
+        break;
+#endif /* LIBSSH2_ECDSA */
+    default :
+        st = _libssh2_error(session,
+                            LIBSSH2_ERROR_FILE,
+                            "Unable to extract public key "
+                            "from private key file: "
+                            "Unsupported private key file format");
+        break;
+    }
+
+    EVP_PKEY_free(pk);
+    return st;
+}
+
+void
+_libssh2_dh_init(_libssh2_dh_ctx *dhctx)
+{
+    *dhctx = BN_new();                          /* Random from client */
+}
+
+int
+_libssh2_dh_key_pair(_libssh2_dh_ctx *dhctx, _libssh2_bn *public,
+                     _libssh2_bn *g, _libssh2_bn *p, int group_order,
+                     _libssh2_bn_ctx *bnctx)
+{
+    /* Generate x and e */
+    BN_rand(*dhctx, group_order * 8 - 1, 0, -1);
+    BN_mod_exp(public, g, *dhctx, p, bnctx);
+    return 0;
+}
+
+int
+_libssh2_dh_secret(_libssh2_dh_ctx *dhctx, _libssh2_bn *secret,
+                   _libssh2_bn *f, _libssh2_bn *p,
+                   _libssh2_bn_ctx *bnctx)
+{
+    /* Compute the shared secret */
+    BN_mod_exp(secret, f, *dhctx, p, bnctx);
+    return 0;
+}
+
+void
+_libssh2_dh_dtor(_libssh2_dh_ctx *dhctx)
+{
+    BN_clear_free(*dhctx);
+    *dhctx = NULL;
+}
+
+#endif /* LIBSSH2_OPENSSL */

+ 409 - 0
libssh2/libssh2/src/openssl.h

@@ -0,0 +1,409 @@
+/* Copyright (C) 2009, 2010 Simon Josefsson
+ * Copyright (C) 2006, 2007 The Written Word, Inc.  All rights reserved.
+ *
+ * Author: Simon Josefsson
+ *
+ * Redistribution and use in source and binary forms,
+ * with or without modification, are permitted provided
+ * that the following conditions are met:
+ *
+ *   Redistributions of source code must retain the above
+ *   copyright notice, this list of conditions and the
+ *   following disclaimer.
+ *
+ *   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.
+ *
+ *   Neither the name of the copyright holder nor the names
+ *   of any other contributors may be used to endorse or
+ *   promote products derived from this software without
+ *   specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+ * CONTRIBUTORS "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 COPYRIGHT OWNER OR
+ * CONTRIBUTORS 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 <openssl/opensslconf.h>
+#include <openssl/sha.h>
+#include <openssl/rsa.h>
+#ifndef OPENSSL_NO_ENGINE
+#include <openssl/engine.h>
+#endif
+#ifndef OPENSSL_NO_DSA
+#include <openssl/dsa.h>
+#endif
+#ifndef OPENSSL_NO_MD5
+#include <openssl/md5.h>
+#endif
+#include <openssl/evp.h>
+#include <openssl/hmac.h>
+#include <openssl/bn.h>
+#include <openssl/pem.h>
+#include <openssl/rand.h>
+
+#if OPENSSL_VERSION_NUMBER >= 0x10100000L && \
+    !defined(LIBRESSL_VERSION_NUMBER)
+# define HAVE_OPAQUE_STRUCTS 1
+#endif
+
+#ifdef OPENSSL_NO_RSA
+# define LIBSSH2_RSA 0
+#else
+# define LIBSSH2_RSA 1
+#endif
+
+#ifdef OPENSSL_NO_DSA
+# define LIBSSH2_DSA 0
+#else
+# define LIBSSH2_DSA 1
+#endif
+
+#ifdef OPENSSL_NO_ECDSA
+# define LIBSSH2_ECDSA 0
+#else
+# define LIBSSH2_ECDSA 1
+#endif
+
+#if OPENSSL_VERSION_NUMBER >= 0x10101000L && \
+!defined(LIBRESSL_VERSION_NUMBER)
+# define LIBSSH2_ED25519 1
+#else
+# define LIBSSH2_ED25519 0
+#endif
+
+
+#ifdef OPENSSL_NO_MD5
+# define LIBSSH2_MD5 0
+#else
+# define LIBSSH2_MD5 1
+#endif
+
+#ifdef OPENSSL_NO_RIPEMD
+# define LIBSSH2_HMAC_RIPEMD 0
+#else
+# define LIBSSH2_HMAC_RIPEMD 1
+#endif
+
+#define LIBSSH2_HMAC_SHA256 1
+#define LIBSSH2_HMAC_SHA512 1
+
+#if OPENSSL_VERSION_NUMBER >= 0x00907000L && !defined(OPENSSL_NO_AES)
+# define LIBSSH2_AES_CTR 1
+# define LIBSSH2_AES 1
+#else
+# define LIBSSH2_AES_CTR 0
+# define LIBSSH2_AES 0
+#endif
+
+#ifdef OPENSSL_NO_BF
+# define LIBSSH2_BLOWFISH 0
+#else
+# define LIBSSH2_BLOWFISH 1
+#endif
+
+#ifdef OPENSSL_NO_RC4
+# define LIBSSH2_RC4 0
+#else
+# define LIBSSH2_RC4 1
+#endif
+
+#ifdef OPENSSL_NO_CAST
+# define LIBSSH2_CAST 0
+#else
+# define LIBSSH2_CAST 1
+#endif
+
+#ifdef OPENSSL_NO_DES
+# define LIBSSH2_3DES 0
+#else
+# define LIBSSH2_3DES 1
+#endif
+
+#define EC_MAX_POINT_LEN ((528 * 2 / 8) + 1)
+
+#define _libssh2_random(buf, len) RAND_bytes ((buf), (len))
+
+#define libssh2_prepare_iovec(vec, len)  /* Empty. */
+
+#ifdef HAVE_OPAQUE_STRUCTS
+#define libssh2_sha1_ctx EVP_MD_CTX *
+#else
+#define libssh2_sha1_ctx EVP_MD_CTX
+#endif
+
+/* returns 0 in case of failure */
+int _libssh2_sha1_init(libssh2_sha1_ctx *ctx);
+#define libssh2_sha1_init(x) _libssh2_sha1_init(x)
+#ifdef HAVE_OPAQUE_STRUCTS
+#define libssh2_sha1_update(ctx, data, len) EVP_DigestUpdate(ctx, data, len)
+#define libssh2_sha1_final(ctx, out) do { \
+                                         EVP_DigestFinal(ctx, out, NULL); \
+                                         EVP_MD_CTX_free(ctx); \
+                                     } while(0)
+#else
+#define libssh2_sha1_update(ctx, data, len) EVP_DigestUpdate(&(ctx), data, len)
+#define libssh2_sha1_final(ctx, out) EVP_DigestFinal(&(ctx), out, NULL)
+#endif
+int _libssh2_sha1(const unsigned char *message, unsigned long len,
+                  unsigned char *out);
+#define libssh2_sha1(x,y,z) _libssh2_sha1(x,y,z)
+
+#ifdef HAVE_OPAQUE_STRUCTS
+#define libssh2_sha256_ctx EVP_MD_CTX *
+#else
+#define libssh2_sha256_ctx EVP_MD_CTX
+#endif
+
+/* returns 0 in case of failure */
+int _libssh2_sha256_init(libssh2_sha256_ctx *ctx);
+#define libssh2_sha256_init(x) _libssh2_sha256_init(x)
+#ifdef HAVE_OPAQUE_STRUCTS
+#define libssh2_sha256_update(ctx, data, len) EVP_DigestUpdate(ctx, data, len)
+#define libssh2_sha256_final(ctx, out) do { \
+                                           EVP_DigestFinal(ctx, out, NULL); \
+                                           EVP_MD_CTX_free(ctx); \
+                                       } while(0)
+#else
+#define libssh2_sha256_update(ctx, data, len) \
+    EVP_DigestUpdate(&(ctx), data, len)
+#define libssh2_sha256_final(ctx, out) EVP_DigestFinal(&(ctx), out, NULL)
+#endif
+int _libssh2_sha256(const unsigned char *message, unsigned long len,
+                  unsigned char *out);
+#define libssh2_sha256(x,y,z) _libssh2_sha256(x,y,z)
+
+#ifdef HAVE_OPAQUE_STRUCTS
+#define libssh2_sha384_ctx EVP_MD_CTX *
+#else
+#define libssh2_sha384_ctx EVP_MD_CTX
+#endif
+
+/* returns 0 in case of failure */
+int _libssh2_sha384_init(libssh2_sha384_ctx *ctx);
+#define libssh2_sha384_init(x) _libssh2_sha384_init(x)
+#ifdef HAVE_OPAQUE_STRUCTS
+#define libssh2_sha384_update(ctx, data, len) EVP_DigestUpdate(ctx, data, len)
+#define libssh2_sha384_final(ctx, out) do { \
+                                            EVP_DigestFinal(ctx, out, NULL); \
+                                            EVP_MD_CTX_free(ctx); \
+                                       } while(0)
+#else
+#define libssh2_sha384_update(ctx, data, len)   \
+    EVP_DigestUpdate(&(ctx), data, len)
+#define libssh2_sha384_final(ctx, out) EVP_DigestFinal(&(ctx), out, NULL)
+#endif
+int _libssh2_sha384(const unsigned char *message, unsigned long len,
+                    unsigned char *out);
+#define libssh2_sha384(x,y,z) _libssh2_sha384(x,y,z)
+
+#ifdef HAVE_OPAQUE_STRUCTS
+#define libssh2_sha512_ctx EVP_MD_CTX *
+#else
+#define libssh2_sha512_ctx EVP_MD_CTX
+#endif
+
+/* returns 0 in case of failure */
+int _libssh2_sha512_init(libssh2_sha512_ctx *ctx);
+#define libssh2_sha512_init(x) _libssh2_sha512_init(x)
+#ifdef HAVE_OPAQUE_STRUCTS
+#define libssh2_sha512_update(ctx, data, len) EVP_DigestUpdate(ctx, data, len)
+#define libssh2_sha512_final(ctx, out) do { \
+                                            EVP_DigestFinal(ctx, out, NULL); \
+                                            EVP_MD_CTX_free(ctx); \
+                                       } while(0)
+#else
+#define libssh2_sha512_update(ctx, data, len)   \
+    EVP_DigestUpdate(&(ctx), data, len)
+#define libssh2_sha512_final(ctx, out) EVP_DigestFinal(&(ctx), out, NULL)
+#endif
+int _libssh2_sha512(const unsigned char *message, unsigned long len,
+                    unsigned char *out);
+#define libssh2_sha512(x,y,z) _libssh2_sha512(x,y,z)
+
+#ifdef HAVE_OPAQUE_STRUCTS
+#define libssh2_md5_ctx EVP_MD_CTX *
+#else
+#define libssh2_md5_ctx EVP_MD_CTX
+#endif
+
+/* returns 0 in case of failure */
+int _libssh2_md5_init(libssh2_md5_ctx *ctx);
+#define libssh2_md5_init(x) _libssh2_md5_init(x)
+#ifdef HAVE_OPAQUE_STRUCTS
+#define libssh2_md5_update(ctx, data, len) EVP_DigestUpdate(ctx, data, len)
+#define libssh2_md5_final(ctx, out) do { \
+                                        EVP_DigestFinal(ctx, out, NULL); \
+                                        EVP_MD_CTX_free(ctx); \
+                                    } while(0)
+#else
+#define libssh2_md5_update(ctx, data, len) EVP_DigestUpdate(&(ctx), data, len)
+#define libssh2_md5_final(ctx, out) EVP_DigestFinal(&(ctx), out, NULL)
+#endif
+
+#ifdef HAVE_OPAQUE_STRUCTS
+#define libssh2_hmac_ctx HMAC_CTX *
+#define libssh2_hmac_ctx_init(ctx) ctx = HMAC_CTX_new()
+#define libssh2_hmac_sha1_init(ctx, key, keylen) \
+  HMAC_Init_ex(*(ctx), key, keylen, EVP_sha1(), NULL)
+#define libssh2_hmac_md5_init(ctx, key, keylen) \
+  HMAC_Init_ex(*(ctx), key, keylen, EVP_md5(), NULL)
+#define libssh2_hmac_ripemd160_init(ctx, key, keylen) \
+  HMAC_Init_ex(*(ctx), key, keylen, EVP_ripemd160(), NULL)
+#define libssh2_hmac_sha256_init(ctx, key, keylen) \
+  HMAC_Init_ex(*(ctx), key, keylen, EVP_sha256(), NULL)
+#define libssh2_hmac_sha512_init(ctx, key, keylen) \
+  HMAC_Init_ex(*(ctx), key, keylen, EVP_sha512(), NULL)
+
+#define libssh2_hmac_update(ctx, data, datalen) \
+  HMAC_Update(ctx, data, datalen)
+#define libssh2_hmac_final(ctx, data) HMAC_Final(ctx, data, NULL)
+#define libssh2_hmac_cleanup(ctx) HMAC_CTX_free(*(ctx))
+#else
+#define libssh2_hmac_ctx HMAC_CTX
+#define libssh2_hmac_ctx_init(ctx) \
+  HMAC_CTX_init(&ctx)
+#define libssh2_hmac_sha1_init(ctx, key, keylen) \
+  HMAC_Init_ex(ctx, key, keylen, EVP_sha1(), NULL)
+#define libssh2_hmac_md5_init(ctx, key, keylen) \
+  HMAC_Init_ex(ctx, key, keylen, EVP_md5(), NULL)
+#define libssh2_hmac_ripemd160_init(ctx, key, keylen) \
+  HMAC_Init_ex(ctx, key, keylen, EVP_ripemd160(), NULL)
+#define libssh2_hmac_sha256_init(ctx, key, keylen) \
+  HMAC_Init_ex(ctx, key, keylen, EVP_sha256(), NULL)
+#define libssh2_hmac_sha512_init(ctx, key, keylen) \
+  HMAC_Init_ex(ctx, key, keylen, EVP_sha512(), NULL)
+
+#define libssh2_hmac_update(ctx, data, datalen) \
+  HMAC_Update(&(ctx), data, datalen)
+#define libssh2_hmac_final(ctx, data) HMAC_Final(&(ctx), data, NULL)
+#define libssh2_hmac_cleanup(ctx) HMAC_cleanup(ctx)
+#endif
+
+extern void _libssh2_openssl_crypto_init(void);
+extern void _libssh2_openssl_crypto_exit(void);
+#define libssh2_crypto_init() _libssh2_openssl_crypto_init()
+#define libssh2_crypto_exit() _libssh2_openssl_crypto_exit()
+
+#define libssh2_rsa_ctx RSA
+
+#define _libssh2_rsa_free(rsactx) RSA_free(rsactx)
+
+#define libssh2_dsa_ctx DSA
+
+#define _libssh2_dsa_free(dsactx) DSA_free(dsactx)
+
+#ifdef LIBSSH2_ECDSA
+#define libssh2_ecdsa_ctx EC_KEY
+#define _libssh2_ecdsa_free(ecdsactx) EC_KEY_free(ecdsactx)
+#define _libssh2_ec_key EC_KEY
+
+typedef enum {
+    LIBSSH2_EC_CURVE_NISTP256 = NID_X9_62_prime256v1,
+    LIBSSH2_EC_CURVE_NISTP384 = NID_secp384r1,
+    LIBSSH2_EC_CURVE_NISTP521 = NID_secp521r1
+}
+libssh2_curve_type;
+#else
+#define _libssh2_ec_key void
+#endif /* LIBSSH2_ECDSA */
+
+#ifdef LIBSSH2_ED25519
+
+typedef struct {
+    EVP_PKEY *public_key;
+    EVP_PKEY *private_key;
+} libssh2_curve25519_keys;
+
+#define libssh2_ed25519_ctx libssh2_curve25519_keys
+#define libssh2_x25519_ctx libssh2_curve25519_keys
+
+#define _libssh2_ed25519_new_ctx() calloc(1, sizeof(libssh2_ed25519_ctx))
+#define _libssh2_ed25519_free(ctx) do { \
+ if(ctx) { \
+  if(ctx->public_key) EVP_PKEY_free(ctx->public_key); \
+  if(ctx->private_key) EVP_PKEY_free(ctx->private_key); \
+  free(ctx); \
+ } \
+} while(0)
+
+#define _libssh2_x25519_free(ctx) _libssh2_ed25519_free(ctx)
+
+#endif /* ED25519 */
+
+#define _libssh2_cipher_type(name) const EVP_CIPHER *(*name)(void)
+#ifdef HAVE_OPAQUE_STRUCTS
+#define _libssh2_cipher_ctx EVP_CIPHER_CTX *
+#else
+#define _libssh2_cipher_ctx EVP_CIPHER_CTX
+#endif
+
+#define _libssh2_cipher_aes256 EVP_aes_256_cbc
+#define _libssh2_cipher_aes192 EVP_aes_192_cbc
+#define _libssh2_cipher_aes128 EVP_aes_128_cbc
+#ifdef HAVE_EVP_AES_128_CTR
+#define _libssh2_cipher_aes128ctr EVP_aes_128_ctr
+#define _libssh2_cipher_aes192ctr EVP_aes_192_ctr
+#define _libssh2_cipher_aes256ctr EVP_aes_256_ctr
+#else
+#define _libssh2_cipher_aes128ctr _libssh2_EVP_aes_128_ctr
+#define _libssh2_cipher_aes192ctr _libssh2_EVP_aes_192_ctr
+#define _libssh2_cipher_aes256ctr _libssh2_EVP_aes_256_ctr
+#endif
+#define _libssh2_cipher_blowfish EVP_bf_cbc
+#define _libssh2_cipher_arcfour EVP_rc4
+#define _libssh2_cipher_cast5 EVP_cast5_cbc
+#define _libssh2_cipher_3des EVP_des_ede3_cbc
+
+#ifdef HAVE_OPAQUE_STRUCTS
+#define _libssh2_cipher_dtor(ctx) EVP_CIPHER_CTX_free(*(ctx))
+#else
+#define _libssh2_cipher_dtor(ctx) EVP_CIPHER_CTX_cleanup(ctx)
+#endif
+
+#define _libssh2_bn BIGNUM
+#define _libssh2_bn_ctx BN_CTX
+#define _libssh2_bn_ctx_new() BN_CTX_new()
+#define _libssh2_bn_ctx_free(bnctx) BN_CTX_free(bnctx)
+#define _libssh2_bn_init() BN_new()
+#define _libssh2_bn_init_from_bin() _libssh2_bn_init()
+#define _libssh2_bn_set_word(bn, val) BN_set_word(bn, val)
+#define _libssh2_bn_from_bin(bn, len, val) BN_bin2bn(val, len, bn)
+#define _libssh2_bn_to_bin(bn, val) BN_bn2bin(bn, val)
+#define _libssh2_bn_bytes(bn) BN_num_bytes(bn)
+#define _libssh2_bn_bits(bn) BN_num_bits(bn)
+#define _libssh2_bn_free(bn) BN_clear_free(bn)
+
+#define _libssh2_dh_ctx BIGNUM *
+#define libssh2_dh_init(dhctx) _libssh2_dh_init(dhctx)
+#define libssh2_dh_key_pair(dhctx, public, g, p, group_order, bnctx) \
+        _libssh2_dh_key_pair(dhctx, public, g, p, group_order, bnctx)
+#define libssh2_dh_secret(dhctx, secret, f, p, bnctx) \
+        _libssh2_dh_secret(dhctx, secret, f, p, bnctx)
+#define libssh2_dh_dtor(dhctx) _libssh2_dh_dtor(dhctx)
+extern void _libssh2_dh_init(_libssh2_dh_ctx *dhctx);
+extern int _libssh2_dh_key_pair(_libssh2_dh_ctx *dhctx, _libssh2_bn *public,
+                                _libssh2_bn *g, _libssh2_bn *p,
+                                int group_order,
+                                _libssh2_bn_ctx *bnctx);
+extern int _libssh2_dh_secret(_libssh2_dh_ctx *dhctx, _libssh2_bn *secret,
+                              _libssh2_bn *f, _libssh2_bn *p,
+                              _libssh2_bn_ctx *bnctx);
+extern void _libssh2_dh_dtor(_libssh2_dh_ctx *dhctx);
+
+const EVP_CIPHER *_libssh2_EVP_aes_128_ctr(void);
+const EVP_CIPHER *_libssh2_EVP_aes_192_ctr(void);
+const EVP_CIPHER *_libssh2_EVP_aes_256_ctr(void);

+ 2411 - 0
libssh2/libssh2/src/os400qc3.c

@@ -0,0 +1,2411 @@
+/*
+ * Copyright (C) 2015-2016 Patrick Monnerat, D+H <patrick.monnerat@dh.com>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms,
+ * with or without modification, are permitted provided
+ * that the following conditions are met:
+ *
+ *   Redistributions of source code must retain the above
+ *   copyright notice, this list of conditions and the
+ *   following disclaimer.
+ *
+ *   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.
+ *
+ *   Neither the name of the copyright holder nor the names
+ *   of any other contributors may be used to endorse or
+ *   promote products derived from this software without
+ *   specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+ * CONTRIBUTORS "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 COPYRIGHT OWNER OR
+ * CONTRIBUTORS 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 "libssh2_priv.h"
+
+#ifdef LIBSSH2_OS400QC3 /* compile only if we build with OS/400 QC3 library */
+
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+
+#include <stdio.h>
+#include <stdarg.h>
+#include <alloca.h>
+#include <sys/uio.h>
+
+#include <arpa/inet.h>
+
+
+#ifdef OS400_DEBUG
+/* In debug mode, all system library errors cause an exception. */
+#define set_EC_length(ec, length)   ((ec).Bytes_Provided =                  \
+                                     (ec).Bytes_Available = 0)
+#else
+#define set_EC_length(ec, length)   ((ec).Bytes_Provided = (length))
+#endif
+
+
+/* Ensure va_list operations are not on an array. */
+typedef struct {
+    va_list     list;
+}       valiststr;
+
+
+typedef int (*loadkeyproc)(LIBSSH2_SESSION *session,
+                           const unsigned char *data, unsigned int datalen,
+                           const unsigned char *passphrase, void *loadkeydata);
+
+/* Public key extraction data. */
+typedef struct {
+    const char *            method;
+    const unsigned char *   data;
+    unsigned int            length;
+}       loadpubkeydata;
+
+
+/* Support for ASN.1 elements. */
+
+typedef struct {
+    char *          header;         /* Pointer to header byte. */
+    char *          beg;            /* Pointer to element data. */
+    char *          end;            /* Pointer to 1st byte after element. */
+    unsigned char   class;          /* ASN.1 element class. */
+    unsigned char   tag;            /* ASN.1 element tag. */
+    unsigned char   constructed;    /* Element is constructed. */
+}       asn1Element;
+
+#define ASN1_INTEGER        2
+#define ASN1_BIT_STRING     3
+#define ASN1_OCTET_STRING   4
+#define ASN1_NULL           5
+#define ASN1_OBJ_ID         6
+#define ASN1_SEQ            16
+
+#define ASN1_CONSTRUCTED    0x20
+
+/* rsaEncryption OID: 1.2.840.113549.1.1.1 */
+static unsigned char    OID_rsaEncryption[] =
+                            {9, 40 + 2, 0x86, 0x48, 0x86, 0xF7, 0x0D, 1, 1, 1};
+static int  sshrsapubkey(LIBSSH2_SESSION *session, char **sshpubkey,
+                         asn1Element *params, asn1Element *key,
+                         const char *method);
+
+#if LIBSSH2_DSA != 0
+/* dsaEncryption OID: 1.2.840.10040.4.1 */
+static unsigned char    OID_dsaEncryption[] =
+                            {7, 40 + 2, 0x86, 0x48, 0xCE, 0x38, 4, 1};
+static int  sshdsapubkey(LIBSSH2_SESSION *session, char **sshpubkey,
+                         asn1Element *params, asn1Element *key,
+                         const char *method);
+#endif
+
+static unsigned char    OID_dhKeyAgreement[] =
+                            {9, 40 + 2, 0x86, 0x48, 0x86, 0xF7, 0x0D, 1, 3, 1};
+
+
+/* PKCS#5 support. */
+
+typedef struct pkcs5params  pkcs5params;
+struct pkcs5params {
+    int         cipher;         /* Encryption cipher. */
+    int         blocksize;      /* Cipher block size. */
+    char        mode;           /* Block encryption mode. */
+    char        padopt;         /* Pad option. */
+    char        padchar;        /* Pad character. */
+    int         (*kdf)(LIBSSH2_SESSION *session, char **dk,
+                       const unsigned char *passphrase, pkcs5params *pkcs5);
+    int         hash;           /* KDF hash algorithm. */
+    size_t      hashlen;        /* KDF hash digest length. */
+    char *      salt;           /* Salt. */
+    size_t      saltlen;        /* Salt length. */
+    char *      iv;             /* Initialization vector. */
+    size_t      ivlen;          /* Initialization vector length. */
+    int         itercount;      /* KDF iteration count. */
+    int         dklen;          /* Derived key length (#bytes). */
+    int         effkeysize;     /* RC2 effective key size (#bits) or 0. */
+};
+
+typedef struct pkcs5algo    pkcs5algo;
+struct pkcs5algo {
+    const unsigned char *   oid;
+    int         (*parse)(LIBSSH2_SESSION *session, pkcs5params *pkcs5,
+                         pkcs5algo *algo, asn1Element *param);
+    int         cipher;         /* Encryption cipher. */
+    size_t      blocksize;      /* Cipher block size. */
+    char        mode;           /* Block encryption mode. */
+    char        padopt;         /* Pad option. */
+    char        padchar;        /* Pad character. */
+    size_t      keylen;         /* Key length (#bytes). */
+    int         hash;           /* Hash algorithm. */
+    size_t      hashlen;        /* Hash digest length. */
+    size_t      saltlen;        /* Salt length. */
+    size_t      ivlen;          /* Initialisation vector length. */
+    int         effkeysize;     /* RC2 effective key size (#bits) or 0. */
+};
+
+/* id-PBES2 OID: 1.2.840.113549.1.5.13 */
+static const unsigned char  OID_id_PBES2[] = {
+    9, 40 + 2, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x05, 0x0D
+};
+static int  parse_pbes2(LIBSSH2_SESSION *session, pkcs5params *pkcs5,
+                        pkcs5algo *algo, asn1Element *param);
+static const pkcs5algo  PBES2 = {
+    OID_id_PBES2,   parse_pbes2,    0,  0,  '\0',   '\0',   '\0',   0,
+    0,  0,  0,  0,  0
+};
+
+/* id-PBKDF2 OID: 1.2.840.113549.1.5.12 */
+static const unsigned char  OID_id_PBKDF2[] = {
+    9, 40 + 2, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x05, 0x0C
+};
+static int  parse_pbkdf2(LIBSSH2_SESSION *session, pkcs5params *pkcs5,
+                         pkcs5algo *algo, asn1Element *param);
+static const pkcs5algo  PBKDF2 = {
+    OID_id_PBKDF2,  parse_pbkdf2,   0,  0,  '\0',   '\0',   '\0',
+    SHA_DIGEST_LENGTH,  Qc3_SHA1,   SHA_DIGEST_LENGTH,  8,  8,  0
+};
+
+/* id-hmacWithSHA1 OID: 1.2.840.113549.2.7 */
+static const unsigned char  OID_id_hmacWithSHA1[] = {
+    8, 40 + 2, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x02, 0x07
+};
+static int  parse_hmacWithSHA1(LIBSSH2_SESSION *session, pkcs5params *pkcs5,
+                               pkcs5algo *algo, asn1Element *param);
+static const pkcs5algo  hmacWithSHA1 = {
+    OID_id_hmacWithSHA1,    parse_hmacWithSHA1, 0,  0,  '\0',   '\0',   '\0',
+    SHA_DIGEST_LENGTH,  Qc3_SHA1,   SHA_DIGEST_LENGTH,  8,  8,  0
+};
+
+/* desCBC OID: 1.3.14.3.2.7 */
+static const unsigned char  OID_desCBC[] = {5, 40 + 3, 0x0E, 0x03, 0x02, 0x07};
+static int  parse_iv(LIBSSH2_SESSION *session, pkcs5params *pkcs5,
+                     pkcs5algo *algo, asn1Element *param);
+static const pkcs5algo  desCBC = {
+    OID_desCBC, parse_iv,   Qc3_DES,    8,  Qc3_CBC,    Qc3_Pad_Counter,
+   '\0',   8,   0,  0,  8,  8,  0
+};
+
+/* des-EDE3-CBC OID: 1.2.840.113549.3.7 */
+static const unsigned char  OID_des_EDE3_CBC[] = {
+    8, 40 + 2, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x03, 0x07
+};
+static const pkcs5algo  des_EDE3_CBC = {
+    OID_des_EDE3_CBC,   parse_iv,   Qc3_TDES,   8,  Qc3_CBC, Qc3_Pad_Counter,
+    '\0',   24, 0,  0,  8,  8,  0
+};
+
+/* rc2CBC OID: 1.2.840.113549.3.2 */
+static const unsigned char  OID_rc2CBC[] = {
+    8, 40 + 2, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x03, 0x02
+};
+static int  parse_rc2(LIBSSH2_SESSION *session, pkcs5params *pkcs5,
+                      pkcs5algo *algo, asn1Element *param);
+static const pkcs5algo  rc2CBC = {
+    OID_rc2CBC, parse_rc2,  Qc3_RC2,    8,  Qc3_CBC,    Qc3_Pad_Counter,
+    '\0',   0,  0,  0,  8,  0,  32
+};
+
+/* pbeWithMD5AndDES-CBC OID: 1.2.840.113549.1.5.3 */
+static const unsigned char  OID_pbeWithMD5AndDES_CBC[] = {
+    9, 40 + 2, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x05, 0x03
+};
+static int  parse_pbes1(LIBSSH2_SESSION *session, pkcs5params *pkcs5,
+                        pkcs5algo *algo, asn1Element *param);
+static const pkcs5algo  pbeWithMD5AndDES_CBC = {
+    OID_pbeWithMD5AndDES_CBC,   parse_pbes1,    Qc3_DES,    8,  Qc3_CBC,
+    Qc3_Pad_Counter,    '\0',   8,  Qc3_MD5,    MD5_DIGEST_LENGTH,  8,  0,  0
+};
+
+/* pbeWithMD5AndRC2-CBC OID: 1.2.840.113549.1.5.6 */
+static const unsigned char  OID_pbeWithMD5AndRC2_CBC[] = {
+    9, 40 + 2, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x05, 0x06
+};
+static const pkcs5algo  pbeWithMD5AndRC2_CBC = {
+    OID_pbeWithMD5AndRC2_CBC,   parse_pbes1,    Qc3_RC2,    8,  Qc3_CBC,
+    Qc3_Pad_Counter,    '\0',   0,  Qc3_MD5,    MD5_DIGEST_LENGTH,  8,  0,  64
+};
+
+/* pbeWithSHA1AndDES-CBC OID: 1.2.840.113549.1.5.10 */
+static const unsigned char  OID_pbeWithSHA1AndDES_CBC[] = {
+    9, 40 + 2, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x05, 0x0A
+};
+static const pkcs5algo  pbeWithSHA1AndDES_CBC = {
+    OID_pbeWithSHA1AndDES_CBC,   parse_pbes1,    Qc3_DES,    8,  Qc3_CBC,
+    Qc3_Pad_Counter,    '\0',   8,  Qc3_SHA1,   SHA_DIGEST_LENGTH,  8,  0, 0
+};
+
+/* pbeWithSHA1AndRC2-CBC OID: 1.2.840.113549.1.5.11 */
+static const unsigned char  OID_pbeWithSHA1AndRC2_CBC[] = {
+    9, 40 + 2, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x05, 0x0B
+};
+static const pkcs5algo  pbeWithSHA1AndRC2_CBC = {
+    OID_pbeWithSHA1AndRC2_CBC,   parse_pbes1,    Qc3_RC2,    8,  Qc3_CBC,
+    Qc3_Pad_Counter,    '\0',   0,  Qc3_SHA1,   SHA_DIGEST_LENGTH,  8,  0,  64
+};
+
+/* rc5-CBC-PAD OID: 1.2.840.113549.3.9: RC5 not implemented in Qc3. */
+/* pbeWithMD2AndDES-CBC OID: 1.2.840.113549.1.5.1: MD2 not implemented. */
+/* pbeWithMD2AndRC2-CBC OID: 1.2.840.113549.1.5.4: MD2 not implemented. */
+
+static const pkcs5algo *    pbestable[] = {
+    &pbeWithMD5AndDES_CBC,
+    &pbeWithMD5AndRC2_CBC,
+    &pbeWithSHA1AndDES_CBC,
+    &pbeWithSHA1AndRC2_CBC,
+    &PBES2,
+    NULL
+};
+
+static const pkcs5algo *    pbkdf2table[] = {
+    &PBKDF2,
+    NULL
+};
+
+static const pkcs5algo *    pbes2enctable[] = {
+    &desCBC,
+    &des_EDE3_CBC,
+    &rc2CBC,
+    NULL
+};
+
+static const pkcs5algo *    kdf2prftable[] = {
+    &hmacWithSHA1,
+    NULL
+};
+
+
+/* Public key extraction support. */
+static struct {
+    unsigned char *oid;
+    int             (*sshpubkey)(LIBSSH2_SESSION *session, char **pubkey,
+                                 asn1Element *params, asn1Element *key,
+                                 const char *method);
+    const char *    method;
+}       pka[] = {
+#if LIBSSH2_RSA != 0
+    {   OID_rsaEncryption,  sshrsapubkey,   "ssh-rsa"   },
+#endif
+#if LIBSSH2_DSA != 0
+    {   OID_dsaEncryption,  sshdsapubkey,   "ssh-dss"   },
+#endif
+    {   NULL,               NULL,           NULL        }
+};
+
+/* Define ASCII strings. */
+static const char   beginencprivkeyhdr[] =
+                                    "-----BEGIN ENCRYPTED PRIVATE KEY-----";
+static const char   endencprivkeyhdr[] = "-----END ENCRYPTED PRIVATE KEY-----";
+static const char   beginprivkeyhdr[] = "-----BEGIN PRIVATE KEY-----";
+static const char   endprivkeyhdr[] = "-----END PRIVATE KEY-----";
+static const char   beginrsaprivkeyhdr[] = "-----BEGIN RSA PRIVATE KEY-----";
+static const char   endrsaprivkeyhdr[] = "-----END RSA PRIVATE KEY-----";
+static const char   fopenrmode[] = "r";
+static const char   fopenrbmode[] = "rb";
+
+
+/* The rest of character literals in this module are in EBCDIC. */
+#pragma convert(37)
+
+#include <qusec.h>
+#include <qc3prng.h>
+#include <qc3dtaen.h>
+#include <qc3dtade.h>
+#include <qc3ctx.h>
+#include <qc3hash.h>
+#include <qc3hmac.h>
+#include <qc3pbext.h>
+#include <qc3sigvr.h>
+#include <qc3sigcl.h>
+#include <qc3pbext.h>
+#include <qc3dh.h>
+
+static Qc3_Format_KEYD0100_T    nulltoken = {""};
+
+static int      zero = 0;
+static int      rsaprivate[] = { Qc3_RSA_Private };
+static char     anycsp[] = { Qc3_Any_CSP };
+static char     binstring[] = { Qc3_Bin_String };
+static char     berstring[] = { Qc3_BER_String };
+static char     qc3clear[] = { Qc3_Clear };
+
+static const Qus_EC_t ecnull = {0};     /* Error causes an exception. */
+
+static asn1Element  lastbytebitcount = {
+    (char *) &zero, NULL, (char *) &zero + 1
+};
+
+
+/*******************************************************************
+ *
+ * OS/400 QC3 crypto-library backend: ASN.1 support.
+ *
+ *******************************************************************/
+
+static char *
+getASN1Element(asn1Element *elem, char *beg, char *end)
+{
+    unsigned char b;
+    unsigned long len;
+    asn1Element lelem;
+
+    /* Get a single ASN.1 element into `elem', parse ASN.1 string at `beg'
+     * ending at `end'.
+     * Returns a pointer in source string after the parsed element, or NULL
+     * if an error occurs.
+     */
+
+    if(beg >= end || !*beg)
+        return NULL;
+
+    /* Process header byte. */
+    elem->header = beg;
+    b = (unsigned char) *beg++;
+    elem->constructed = (b & 0x20) != 0;
+    elem->class = (b >> 6) & 3;
+    b &= 0x1F;
+    if(b == 0x1F)
+        return NULL;            /* Long tag values not supported here. */
+    elem->tag = b;
+
+    /* Process length. */
+    if(beg >= end)
+        return NULL;
+    b = (unsigned char) *beg++;
+    if(!(b & 0x80))
+        len = b;
+    else if(!(b &= 0x7F)) {
+        /* Unspecified length. Since we have all the data, we can determine the
+         * effective length by skipping element until an end element is
+         * found.
+         */
+        if(!elem->constructed)
+            return NULL;
+        elem->beg = beg;
+        while(beg < end && *beg) {
+            beg = getASN1Element(&lelem, beg, end);
+        if(!beg)
+            return NULL;
+        }
+        if(beg >= end)
+            return NULL;
+        elem->end = beg;
+        return beg + 1;
+    }
+    else if(beg + b > end)
+        return NULL;                        /* Does not fit in source. */
+    else {
+        /* Get long length. */
+        len = 0;
+        do {
+            if(len & 0xFF000000L)
+                return NULL;    /* Lengths > 32 bits are not supported. */
+            len = (len << 8) | (unsigned char) *beg++;
+        } while(--b);
+    }
+    if((unsigned long) (end - beg) < len)
+        return NULL;            /* Element data does not fit in source. */
+    elem->beg = beg;
+    elem->end = beg + len;
+    return elem->end;
+}
+
+static asn1Element *
+asn1_new(unsigned int type, unsigned int length)
+{
+    asn1Element *e;
+    unsigned int hdrl = 2;
+    unsigned int i;
+    unsigned char *buf;
+
+    e = (asn1Element *) malloc(sizeof *e);
+
+    if(e) {
+        if(length >= 0x80)
+            for(i = length; i; i >>= 8)
+                hdrl++;
+
+        buf = (unsigned char *) malloc(hdrl + length);
+
+        if(buf) {
+            e->header = buf;
+            e->beg = buf + hdrl;
+            e->end = e->beg + length;
+            e->class = (type >> 6) & 0x03;
+            e->tag = type & 0x1F;
+            e->constructed = (type >> 5) & 0x01;
+            e->header[0] = type;
+
+            if(length < 0x80)
+                e->header[1] = length;
+            else {
+                e->header[1] = (hdrl - 2) | 0x80;
+                do {
+                    e->header[--hdrl] = length;
+                    length >>= 8;
+                } while(length);
+            }
+        }
+        else {
+            free((char *) e);
+            e = NULL;
+        }
+    }
+
+    return e;
+}
+
+static asn1Element *
+asn1_new_from_bytes(const unsigned char *data, unsigned int length)
+{
+    asn1Element *e;
+    asn1Element te;
+
+    getASN1Element(&te,
+                   (unsigned char *) data, (unsigned char *) data + length);
+    e = asn1_new(te.tag, te.end - te.beg);
+
+    if(e)
+        memcpy(e->header, data, e->end - e->header);
+
+    return e;
+}
+
+static void
+asn1delete(asn1Element *e)
+{
+    if(e) {
+        if(e->header)
+            free((char *) e->header);
+        free((char *) e);
+    }
+}
+
+static asn1Element *
+asn1uint(_libssh2_bn *bn)
+{
+    asn1Element *e;
+    int bits;
+    int length;
+    unsigned char *p;
+
+    if(!bn)
+        return NULL;
+
+    bits = _libssh2_bn_bits(bn);
+    length = (bits + 8) >> 3;
+    e = asn1_new(ASN1_INTEGER, length);
+
+    if(e) {
+        p = e->beg;
+        if(!(bits & 0x07))
+            *p++ = 0;
+        _libssh2_bn_to_bin(bn, p);
+    }
+
+    return e;
+}
+
+static asn1Element *
+asn1containerv(unsigned int type, valiststr args)
+{
+    valiststr va;
+    asn1Element *e;
+    asn1Element *p;
+    unsigned char *bp;
+    unsigned int length = 0;
+
+    memcpy((char *) &va, (char *) &args, sizeof args);
+    while((p = va_arg(va.list, asn1Element *)))
+        length += p->end - p->header;
+    va_end(va.list);
+    e = asn1_new(type, length);
+    if(e) {
+        bp = e->beg;
+        while((p = va_arg(args.list, asn1Element *))) {
+            memcpy(bp, p->header, p->end - p->header);
+            bp += p->end - p->header;
+        }
+    }
+    return e;
+}
+
+/* VARARGS1 */
+static asn1Element *
+asn1container(unsigned int type, ...)
+{
+    valiststr va;
+    asn1Element *e;
+
+    va_start(va.list, type);
+    e = asn1containerv(type, va);
+    va_end(va.list);
+    return e;
+}
+
+static asn1Element *
+asn1bytes(unsigned int type, const unsigned char *bytes, unsigned int length)
+{
+    asn1Element *e;
+
+    e = asn1_new(type, length);
+    if(e && length)
+        memcpy(e->beg, bytes, length);
+    return e;
+}
+
+static asn1Element *
+rsapublickey(_libssh2_bn *e, _libssh2_bn *m)
+{
+    asn1Element *publicexponent;
+    asn1Element *modulus;
+    asn1Element *rsapubkey;
+
+    /* Build a PKCS#1 RSAPublicKey. */
+
+    modulus = asn1uint(m);
+    publicexponent = asn1uint(e);
+    rsapubkey = asn1container(ASN1_SEQ | ASN1_CONSTRUCTED,
+                              modulus, publicexponent, NULL);
+    asn1delete(modulus);
+    asn1delete(publicexponent);
+
+    if(!modulus || !publicexponent) {
+        asn1delete(rsapubkey);
+        rsapubkey = NULL;
+    }
+
+    return rsapubkey;
+}
+
+static asn1Element *
+rsaprivatekey(_libssh2_bn *e, _libssh2_bn *m, _libssh2_bn *d,
+              _libssh2_bn *p, _libssh2_bn *q,
+              _libssh2_bn *exp1, _libssh2_bn *exp2, _libssh2_bn *coeff)
+{
+    asn1Element *version;
+    asn1Element *modulus;
+    asn1Element *publicexponent;
+    asn1Element *privateexponent;
+    asn1Element *prime1;
+    asn1Element *prime2;
+    asn1Element *exponent1;
+    asn1Element *exponent2;
+    asn1Element *coefficient;
+    asn1Element *rsaprivkey;
+
+    /* Build a PKCS#1 RSAPrivateKey. */
+    version = asn1bytes(ASN1_INTEGER, "\0", 1);
+    modulus = asn1uint(m);
+    publicexponent = asn1uint(e);
+    privateexponent = asn1uint(d);
+    prime1 = asn1uint(p);
+    prime2 = asn1uint(q);
+    exponent1 = asn1uint(exp1);
+    exponent2 = asn1uint(exp2);
+    coefficient = asn1uint(coeff);
+    rsaprivkey = asn1container(ASN1_SEQ | ASN1_CONSTRUCTED, version, modulus,
+                               publicexponent, privateexponent, prime1, prime2,
+                               exponent1, exponent2, coefficient, NULL);
+    asn1delete(version);
+    asn1delete(modulus);
+    asn1delete(publicexponent);
+    asn1delete(privateexponent);
+    asn1delete(prime1);
+    asn1delete(prime2);
+    asn1delete(exponent1);
+    asn1delete(exponent2);
+    asn1delete(coefficient);
+
+    if(!version || !modulus || !publicexponent || !privateexponent ||
+        !prime1 || !prime2 || !exponent1 || !exponent2 || !coefficient) {
+        asn1delete(rsaprivkey);
+        rsaprivkey = NULL;
+    }
+
+    return rsaprivkey;
+}
+
+static asn1Element *
+subjectpublickeyinfo(asn1Element *pubkey, const unsigned char *algo,
+                     asn1Element *parameters)
+{
+    asn1Element *subjpubkey;
+    asn1Element *algorithm;
+    asn1Element *algorithmid;
+    asn1Element *subjpubkeyinfo;
+    unsigned int algosize = *algo++;
+
+    algorithm = asn1bytes(ASN1_OBJ_ID, algo, algosize);
+    algorithmid = asn1container(ASN1_SEQ | ASN1_CONSTRUCTED,
+                                algorithm, parameters, NULL);
+    subjpubkey = asn1container(ASN1_BIT_STRING, &lastbytebitcount,
+                               pubkey, NULL);
+    subjpubkeyinfo = asn1container(ASN1_SEQ | ASN1_CONSTRUCTED,
+                                   algorithmid, subjpubkey, NULL);
+    asn1delete(algorithm);
+    asn1delete(algorithmid);
+    asn1delete(subjpubkey);
+    if(!algorithm || !algorithmid || !subjpubkey) {
+        asn1delete(subjpubkeyinfo);
+        subjpubkeyinfo = NULL;
+    }
+    return subjpubkeyinfo;
+}
+
+static asn1Element *
+rsasubjectpublickeyinfo(asn1Element *pubkey)
+{
+    asn1Element *parameters;
+    asn1Element *subjpubkeyinfo;
+
+    parameters = asn1bytes(ASN1_NULL, NULL, 0);
+    subjpubkeyinfo = subjectpublickeyinfo(pubkey,
+                                          OID_rsaEncryption, parameters);
+    asn1delete(parameters);
+    if(!parameters) {
+        asn1delete(subjpubkeyinfo);
+        subjpubkeyinfo = NULL;
+    }
+    return subjpubkeyinfo;
+}
+
+static asn1Element *
+privatekeyinfo(asn1Element *privkey, const unsigned char *algo,
+               asn1Element *parameters)
+{
+    asn1Element *version;
+    asn1Element *privatekey;
+    asn1Element *algorithm;
+    asn1Element *privatekeyalgorithm;
+    asn1Element *privkeyinfo;
+    unsigned int algosize = *algo++;
+
+    /* Build a PKCS#8 PrivateKeyInfo. */
+    version = asn1bytes(ASN1_INTEGER, "\0", 1);
+    algorithm = asn1bytes(ASN1_OBJ_ID, algo, algosize);
+    privatekeyalgorithm = asn1container(ASN1_SEQ | ASN1_CONSTRUCTED,
+                                        algorithm, parameters, NULL);
+    privatekey = asn1container(ASN1_OCTET_STRING, privkey, NULL);
+    privkeyinfo = asn1container(ASN1_SEQ | ASN1_CONSTRUCTED, version,
+                                privatekeyalgorithm, privatekey, NULL);
+    asn1delete(version);
+    asn1delete(algorithm);
+    asn1delete(privatekeyalgorithm);
+    if(!version || !algorithm || !privatekeyalgorithm) {
+        asn1delete(privkeyinfo);
+        privkeyinfo = NULL;
+    }
+    return privkeyinfo;
+}
+
+static asn1Element *
+rsaprivatekeyinfo(asn1Element *privkey)
+{
+    asn1Element *parameters;
+    asn1Element *privkeyinfo;
+
+    parameters = asn1bytes(ASN1_NULL, NULL, 0);
+    privkeyinfo = privatekeyinfo(privkey, OID_rsaEncryption, parameters);
+    asn1delete(parameters);
+    if(!parameters) {
+        asn1delete(privkeyinfo);
+        privkeyinfo = NULL;
+    }
+    return privkeyinfo;
+}
+
+/*******************************************************************
+ *
+ * OS/400 QC3 crypto-library backend: big numbers support.
+ *
+ *******************************************************************/
+
+
+_libssh2_bn *
+_libssh2_bn_init(void)
+{
+    _libssh2_bn *bignum;
+
+    bignum = (_libssh2_bn *) malloc(sizeof *bignum);
+    if(bignum) {
+        bignum->bignum = NULL;
+        bignum->length = 0;
+    }
+
+    return bignum;
+}
+
+void
+_libssh2_bn_free(_libssh2_bn *bn)
+{
+    if(bn) {
+        if(bn->bignum) {
+#ifdef LIBSSH2_CLEAR_MEMORY
+            if(bn->length)
+                memset((char *) bn->bignum, 0, bn->length);
+#endif
+            free(bn->bignum);
+        }
+
+        free((char *) bn);
+    }
+}
+
+static int
+_libssh2_bn_resize(_libssh2_bn *bn, size_t newlen)
+{
+    unsigned char *bignum;
+
+    if(!bn)
+        return -1;
+    if(newlen == bn->length)
+        return 0;
+
+    if(!bn->bignum)
+        bignum = (unsigned char *) malloc(newlen);
+    else {
+#ifdef LIBSSH2_CLEAR_MEMORY
+        if(newlen < bn->length)
+            memset((char *) bn->bignum + newlen, 0, bn->length - newlen);
+#endif
+        if(!newlen) {
+            free((char *) bn->bignum);
+            bn->bignum = NULL;
+            bn->length = 0;
+            return 0;
+        }
+        bignum = (unsigned char *) realloc((char *) bn->bignum, newlen);
+    }
+
+    if(!bignum)
+        return -1;
+
+    if(newlen > bn->length)
+        memset((char *) bignum + bn->length, 0, newlen - bn->length);
+
+    bn->bignum = bignum;
+    bn->length = newlen;
+    return 0;
+}
+
+unsigned long
+_libssh2_bn_bits(_libssh2_bn *bn)
+{
+    unsigned int i;
+    unsigned char b;
+
+    if(bn && bn->bignum) {
+        for(i = bn->length; i--;)
+            b = bn->bignum[i];
+            if(b) {
+                i *= 8;
+                do {
+                    i++;
+                } while(b >>= 1);
+                return i;
+            }
+    }
+
+    return 0;
+}
+
+int
+_libssh2_bn_from_bin(_libssh2_bn *bn, int len, const unsigned char *val)
+{
+    int i;
+
+    if(!bn || (len && !val))
+        return -1;
+
+    for(; len && !*val; len--)
+        val++;
+
+    if(_libssh2_bn_resize(bn, len))
+        return -1;
+
+    for(i = len; i--;)
+        bn->bignum[i] = *val++;
+
+    return 0;
+}
+
+int
+_libssh2_bn_set_word(_libssh2_bn *bn, unsigned long val)
+{
+    val = htonl(val);
+    return _libssh2_bn_from_bin(bn, sizeof val, (unsigned char *) &val);
+}
+
+int
+_libssh2_bn_to_bin(_libssh2_bn *bn, unsigned char *val)
+{
+    int i;
+
+    if(!bn || !val)
+        return -1;
+
+    for(i = bn->length; i--;)
+        *val++ = bn->bignum[i];
+
+    return 0;
+}
+
+static int
+_libssh2_bn_from_bn(_libssh2_bn *to, _libssh2_bn *from)
+{
+    int i;
+
+    if(!to || !from)
+        return -1;
+
+    if(_libssh2_bn_resize(to, from->length))
+        return -1;
+
+    for(i = to->length; i--;)
+        to->bignum[i] = from->bignum[i];
+
+    return 0;
+}
+
+void
+_libssh2_random(unsigned char *buf, int len)
+{
+    Qc3GenPRNs(buf, len,
+        Qc3PRN_TYPE_NORMAL, Qc3PRN_NO_PARITY, (char *) &ecnull);
+}
+
+
+/*******************************************************************
+ *
+ * OS/400 QC3 crypto-library backend: crypto context support.
+ *
+ *******************************************************************/
+
+static _libssh2_os400qc3_crypto_ctx *
+libssh2_init_crypto_ctx(_libssh2_os400qc3_crypto_ctx *ctx)
+{
+    if(!ctx)
+        ctx = (_libssh2_os400qc3_crypto_ctx *) malloc(sizeof *ctx);
+
+    if(ctx) {
+        memset((char *) ctx, 0, sizeof *ctx);
+        ctx->hash.Final_Op_Flag = Qc3_Continue;
+    }
+
+    return ctx;
+}
+
+static int
+null_token(const char *token)
+{
+    return !memcmp(token, nulltoken.Key_Context_Token,
+                   sizeof nulltoken.Key_Context_Token);
+}
+
+void
+_libssh2_os400qc3_crypto_dtor(_libssh2_os400qc3_crypto_ctx *x)
+{
+    if(!x)
+        return;
+    if(!null_token(x->hash.Alg_Context_Token)) {
+        Qc3DestroyAlgorithmContext(x->hash.Alg_Context_Token,
+                                   (char *) &ecnull);
+        memset(x->hash.Alg_Context_Token, 0, sizeof x->hash.Alg_Context_Token);
+    }
+    if(!null_token(x->key.Key_Context_Token)) {
+        Qc3DestroyKeyContext(x->key.Key_Context_Token, (char *) &ecnull);
+        memset(x->key.Key_Context_Token, 0, sizeof x->key.Key_Context_Token);
+    }
+    if(x->kek) {
+        _libssh2_os400qc3_crypto_dtor(x->kek);
+        free((char *) x->kek);
+        x->kek = NULL;
+    }
+}
+
+/*******************************************************************
+ *
+ * OS/400 QC3 crypto-library backend: hash algorithms support.
+ *
+ *******************************************************************/
+
+int
+libssh2_os400qc3_hash_init(Qc3_Format_ALGD0100_T *x, unsigned int algorithm)
+{
+    Qc3_Format_ALGD0500_T algd;
+    Qus_EC_t errcode;
+
+    if(!x)
+        return 0;
+
+    memset((char *) x, 0, sizeof *x);
+    x->Final_Op_Flag = Qc3_Continue;
+    algd.Hash_Alg = algorithm;
+    set_EC_length(errcode, sizeof errcode);
+    Qc3CreateAlgorithmContext((char *) &algd, Qc3_Alg_Hash,
+                              x->Alg_Context_Token, &errcode);
+    return errcode.Bytes_Available? 0: 1;
+}
+
+void
+libssh2_os400qc3_hash_update(Qc3_Format_ALGD0100_T *ctx,
+                             unsigned char *data, int len)
+{
+    char dummy[64];
+
+    ctx->Final_Op_Flag = Qc3_Continue;
+    Qc3CalculateHash((char *) data, &len, Qc3_Data, (char *) ctx,
+                     Qc3_Alg_Token, anycsp, NULL, dummy, (char *) &ecnull);
+}
+
+void
+libssh2_os400qc3_hash_final(Qc3_Format_ALGD0100_T *ctx, unsigned char *out)
+{
+    char data;
+
+    ctx->Final_Op_Flag = Qc3_Final;
+    Qc3CalculateHash(&data, &zero, Qc3_Data, (char *) ctx, Qc3_Alg_Token,
+                     anycsp, NULL, (char *) out, (char *) &ecnull);
+    Qc3DestroyAlgorithmContext(ctx->Alg_Context_Token, (char *) &ecnull);
+    memset(ctx->Alg_Context_Token, 0, sizeof ctx->Alg_Context_Token);
+}
+
+int
+libssh2_os400qc3_hash(const unsigned char *message, unsigned long len,
+                      unsigned char *out, unsigned int algo)
+{
+    Qc3_Format_ALGD0100_T ctx;
+
+    if(!libssh2_os400qc3_hash_init(&ctx, algo))
+        return 1;
+
+    libssh2_os400qc3_hash_update(&ctx, (unsigned char *) message, len);
+    libssh2_os400qc3_hash_final(&ctx, out);
+    return 0;
+}
+
+void
+libssh2_os400qc3_hmac_init(_libssh2_os400qc3_crypto_ctx *ctx,
+                           int algo, size_t minkeylen, void *key, int keylen)
+{
+    if(keylen < minkeylen) {
+        char *lkey = alloca(minkeylen);
+
+        /* Pad key with zeroes if too short. */
+        if(!lkey)
+            return;
+        memcpy(lkey, (char *) key, keylen);
+        memset(lkey + keylen, 0, minkeylen - keylen);
+        key = (void *) lkey;
+        keylen = minkeylen;
+    }
+    libssh2_os400qc3_hash_init(&ctx->hash, algo);
+    Qc3CreateKeyContext((char *) key, &keylen, binstring, &algo, qc3clear,
+                        NULL, NULL, ctx->key.Key_Context_Token,
+                        (char *) &ecnull);
+}
+
+void
+libssh2_os400qc3_hmac_update(_libssh2_os400qc3_crypto_ctx *ctx,
+                             unsigned char *data, int len)
+{
+    char dummy[64];
+
+    ctx->hash.Final_Op_Flag = Qc3_Continue;
+    Qc3CalculateHMAC((char *) data, &len, Qc3_Data, (char *) &ctx->hash,
+                     Qc3_Alg_Token, ctx->key.Key_Context_Token, Qc3_Key_Token,
+                     anycsp, NULL, dummy, (char *) &ecnull);
+}
+
+void
+libssh2_os400qc3_hmac_final(_libssh2_os400qc3_crypto_ctx *ctx,
+                            unsigned char *out)
+{
+    char data;
+
+    ctx->hash.Final_Op_Flag = Qc3_Final;
+    Qc3CalculateHMAC((char *) data, &zero, Qc3_Data, (char *) &ctx->hash,
+                     Qc3_Alg_Token, ctx->key.Key_Context_Token, Qc3_Key_Token,
+                     anycsp, NULL, (char *) out, (char *) &ecnull);
+}
+
+
+/*******************************************************************
+ *
+ * OS/400 QC3 crypto-library backend: cipher algorithms support.
+ *
+ *******************************************************************/
+
+int
+_libssh2_cipher_init(_libssh2_cipher_ctx *h, _libssh2_cipher_type(algo),
+                     unsigned char *iv, unsigned char *secret, int encrypt)
+{
+    Qc3_Format_ALGD0200_T algd;
+    Qus_EC_t errcode;
+
+    (void) encrypt;
+
+    if(!h)
+        return -1;
+
+    libssh2_init_crypto_ctx(h);
+    algd.Block_Cipher_Alg = algo.algo;
+    algd.Block_Length = algo.size;
+    algd.Mode = algo.mode;
+    algd.Pad_Option = Qc3_No_Pad;
+    algd.Pad_Character = 0;
+    algd.Reserved = 0;
+    algd.MAC_Length = 0;
+    algd.Effective_Key_Size = 0;
+    memset(algd.Init_Vector, 0, sizeof algd.Init_Vector);
+    if(algo.mode != Qc3_ECB && algo.size)
+        memcpy(algd.Init_Vector, iv, algo.size);
+    set_EC_length(errcode, sizeof errcode);
+    Qc3CreateAlgorithmContext((char *) &algd, algo.fmt,
+                              h->hash.Alg_Context_Token, &errcode);
+    if(errcode.Bytes_Available)
+        return -1;
+    Qc3CreateKeyContext((char *) secret, &algo.keylen, binstring,
+                        &algo.algo, qc3clear, NULL, NULL,
+                        h->key.Key_Context_Token, (char *) &errcode);
+    if(errcode.Bytes_Available) {
+        _libssh2_os400qc3_crypto_dtor(h);
+        return -1;
+    }
+
+    return 0;
+}
+
+int
+_libssh2_cipher_crypt(_libssh2_cipher_ctx *ctx,
+                      _libssh2_cipher_type(algo),
+                      int encrypt, unsigned char *block, size_t blocksize)
+{
+    Qus_EC_t errcode;
+    int outlen;
+    int blksize = blocksize;
+
+    (void) algo;
+
+    set_EC_length(errcode, sizeof errcode);
+    if(encrypt)
+        Qc3EncryptData((char *) block, &blksize, Qc3_Data,
+                       ctx->hash.Alg_Context_Token, Qc3_Alg_Token,
+                       ctx->key.Key_Context_Token, Qc3_Key_Token, anycsp, NULL,
+                       (char *) block, &blksize, &outlen, (char *) &errcode);
+    else
+        Qc3DecryptData((char *) block, &blksize,
+                       ctx->hash.Alg_Context_Token, Qc3_Alg_Token,
+                       ctx->key.Key_Context_Token, Qc3_Key_Token, anycsp, NULL,
+                       (char *) block, &blksize, &outlen, (char *) &errcode);
+
+    return errcode.Bytes_Available? -1: 0;
+}
+
+
+/*******************************************************************
+ *
+ * OS/400 QC3 crypto-library backend: RSA support.
+ *
+ *******************************************************************/
+
+int
+_libssh2_rsa_new(libssh2_rsa_ctx **rsa,
+                 const unsigned char *edata, unsigned long elen,
+                 const unsigned char *ndata, unsigned long nlen,
+                 const unsigned char *ddata, unsigned long dlen,
+                 const unsigned char *pdata, unsigned long plen,
+                 const unsigned char *qdata, unsigned long qlen,
+                 const unsigned char *e1data, unsigned long e1len,
+                 const unsigned char *e2data, unsigned long e2len,
+                 const unsigned char *coeffdata, unsigned long coefflen)
+{
+    libssh2_rsa_ctx *ctx;
+    _libssh2_bn *e = _libssh2_bn_init_from_bin();
+    _libssh2_bn *n = _libssh2_bn_init_from_bin();
+    _libssh2_bn *d = NULL;
+    _libssh2_bn *p = NULL;
+    _libssh2_bn *q = NULL;
+    _libssh2_bn *e1 = NULL;
+    _libssh2_bn *e2 = NULL;
+    _libssh2_bn *coeff = NULL;
+    asn1Element *key = NULL;
+    asn1Element *structkey = NULL;
+    Qc3_Format_ALGD0400_T algd;
+    Qus_EC_t errcode;
+    int keytype;
+    int ret = 0;
+    int i;
+
+    ctx = libssh2_init_crypto_ctx(NULL);
+    if(!ctx)
+        ret = -1;
+    if(!ret) {
+        _libssh2_bn_from_bin(e, elen, edata);
+        _libssh2_bn_from_bin(n, nlen, ndata);
+        if(!e || !n)
+            ret = -1;
+    }
+    if(!ret && ddata) {
+        /* Private key. */
+        d = _libssh2_bn_init_from_bin();
+        _libssh2_bn_from_bin(d, dlen, ddata);
+        p = _libssh2_bn_init_from_bin();
+        _libssh2_bn_from_bin(p, plen, pdata);
+        q = _libssh2_bn_init_from_bin();
+        _libssh2_bn_from_bin(q, qlen, qdata);
+        e1 = _libssh2_bn_init_from_bin();
+        _libssh2_bn_from_bin(e1, e1len, e1data);
+        e2 = _libssh2_bn_init_from_bin();
+        _libssh2_bn_from_bin(e2, e2len, e2data);
+        coeff = _libssh2_bn_init_from_bin();
+        _libssh2_bn_from_bin(coeff, coefflen, coeffdata);
+        if(!d || !p || !q ||!e1 || !e2 || !coeff)
+            ret = -1;
+
+        if(!ret) {
+            /* Build a PKCS#8 private key. */
+            key = rsaprivatekey(e, n, d, p, q, e1, e2, coeff);
+            structkey = rsaprivatekeyinfo(key);
+        }
+        keytype = Qc3_RSA_Private;
+    }
+    else if(!ret) {
+        key = rsapublickey(e, n);
+        structkey = rsasubjectpublickeyinfo(key);
+        keytype = Qc3_RSA_Public;
+    }
+    if(!key || !structkey)
+        ret = -1;
+
+    set_EC_length(errcode, sizeof errcode);
+
+    if(!ret) {
+        /* Create the algorithm context. */
+        algd.Public_Key_Alg = Qc3_RSA;
+        algd.PKA_Block_Format = Qc3_PKCS1_01;
+        memset(algd.Reserved, 0, sizeof algd.Reserved);
+        algd.Signing_Hash_Alg = Qc3_SHA1;
+        Qc3CreateAlgorithmContext((char *) &algd, Qc3_Alg_Public_Key,
+                                  ctx->hash.Alg_Context_Token, &errcode);
+        if(errcode.Bytes_Available)
+            ret = -1;
+        ctx->hash.Final_Op_Flag = Qc3_Continue;
+    }
+
+    /* Create the key context. */
+    if(!ret) {
+        i = structkey->end - structkey->header;
+        Qc3CreateKeyContext(structkey->header, &i, berstring, &keytype,
+                            qc3clear, NULL, NULL, ctx->key.Key_Context_Token,
+                            (char *) &errcode);
+        if(errcode.Bytes_Available)
+            ret = -1;
+    }
+
+    _libssh2_bn_free(e);
+    _libssh2_bn_free(n);
+    _libssh2_bn_free(d);
+    _libssh2_bn_free(p);
+    _libssh2_bn_free(q);
+    _libssh2_bn_free(e1);
+    _libssh2_bn_free(e2);
+    _libssh2_bn_free(coeff);
+    asn1delete(key);
+    asn1delete(structkey);
+    if(ret && ctx) {
+        _libssh2_rsa_free(ctx);
+        ctx = NULL;
+    }
+    *rsa = ctx;
+    return ret;
+}
+
+
+/*******************************************************************
+ *
+ * OS/400 QC3 crypto-library backend: Diffie-Hellman support.
+ *
+ *******************************************************************/
+
+void
+_libssh2_os400qc3_dh_init(_libssh2_dh_ctx *dhctx)
+{
+    memset((char *) dhctx, 0, sizeof *dhctx);
+}
+
+int
+_libssh2_os400qc3_dh_key_pair(_libssh2_dh_ctx *dhctx, _libssh2_bn *public,
+                              _libssh2_bn *g, _libssh2_bn *p, int group_order)
+{
+    asn1Element *prime;
+    asn1Element *base;
+    asn1Element *dhparameter;
+    asn1Element *dhkeyagreement;
+    asn1Element *pkcs3;
+    int pkcs3len;
+    char *pubkey;
+    int pubkeysize;
+    int pubkeylen;
+    Qus_EC_t errcode;
+
+    (void) group_order;
+
+    /* Build the PKCS#3 structure. */
+
+    base = asn1uint(g);
+    prime = asn1uint(p);
+    dhparameter = asn1container(ASN1_SEQ | ASN1_CONSTRUCTED,
+                                prime, base, NULL);
+    asn1delete(base);
+    asn1delete(prime);
+    dhkeyagreement = asn1bytes(ASN1_OBJ_ID,
+                               OID_dhKeyAgreement + 1, OID_dhKeyAgreement[0]);
+    pkcs3 = asn1container(ASN1_SEQ | ASN1_CONSTRUCTED,
+                          dhkeyagreement, dhparameter, NULL);
+    asn1delete(dhkeyagreement);
+    asn1delete(dhparameter);
+    if(!base || !prime || !dhparameter ||
+        !dhkeyagreement || !dhparameter || !pkcs3) {
+        asn1delete(pkcs3);
+        return -1;
+    }
+    pkcs3len = pkcs3->end - pkcs3->header;
+    pubkeysize = (_libssh2_bn_bits(p) + 7) >> 3;
+    pubkey = alloca(pubkeysize);
+    set_EC_length(errcode, sizeof errcode);
+    Qc3GenDHKeyPair((char *) pkcs3->header, &pkcs3len, anycsp, NULL,
+                    dhctx->token, pubkey, &pubkeysize, &pubkeylen, &errcode);
+    asn1delete(pkcs3);
+    if(errcode.Bytes_Available)
+        return -1;
+    return _libssh2_bn_from_bin(public, pubkeylen, (unsigned char *) pubkey);
+}
+
+int
+_libssh2_os400qc3_dh_secret(_libssh2_dh_ctx *dhctx, _libssh2_bn *secret,
+                            _libssh2_bn *f, _libssh2_bn *p)
+{
+    char *pubkey;
+    int pubkeysize;
+    char *secretbuf;
+    int secretbufsize;
+    int secretbuflen;
+    Qus_EC_t errcode;
+
+    pubkeysize = (_libssh2_bn_bits(f) + 7) >> 3;
+    pubkey = alloca(pubkeysize);
+    _libssh2_bn_to_bin(f, pubkey);
+    secretbufsize = (_libssh2_bn_bits(p) + 7) >> 3;
+    secretbuf = alloca(pubkeysize);
+    set_EC_length(errcode, sizeof errcode);
+    Qc3CalculateDHSecretKey(dhctx->token, pubkey, &pubkeysize,
+                            secretbuf, &secretbufsize, &secretbuflen,
+                            &errcode);
+    if(errcode.Bytes_Available)
+        return -1;
+    return _libssh2_bn_from_bin(secret,
+                                secretbuflen, (unsigned char *) secretbuf);
+}
+
+void
+_libssh2_os400qc3_dh_dtor(_libssh2_dh_ctx *dhctx)
+{
+    if(!null_token(dhctx->token)) {
+        Qc3DestroyAlgorithmContext(dhctx->token, (char *) &ecnull);
+        memset((char *) dhctx, 0, sizeof *dhctx);
+    }
+}
+
+
+/*******************************************************************
+ *
+ * OS/400 QC3 crypto-library backend: PKCS#5 supplement.
+ *
+ *******************************************************************/
+
+static int
+oidcmp(const asn1Element *e, const unsigned char *oid)
+{
+    int i = e->end - e->beg - *oid++;
+
+    if(*e->header != ASN1_OBJ_ID)
+        return -2;
+    if(!i)
+        i = memcmp(e->beg, oid, oid[-1]);
+    return i;
+}
+
+static int
+asn1getword(asn1Element *e, unsigned long *v)
+{
+    unsigned long a;
+    const unsigned char *cp;
+
+    if(*e->header != ASN1_INTEGER)
+        return -1;
+    for(cp = e->beg; cp < e->end && !*cp; cp++)
+        ;
+    if(e->end - cp > sizeof a)
+        return -1;
+    for(a = 0; cp < e->end; cp++)
+        a = (a << 8) | *cp;
+    *v = a;
+    return 0;
+}
+
+static int
+pbkdf1(LIBSSH2_SESSION *session, char **dk, const unsigned char *passphrase,
+       pkcs5params *pkcs5)
+{
+    int i;
+    Qc3_Format_ALGD0100_T hctx;
+    int len = pkcs5->saltlen;
+    char *data = (char *) pkcs5->salt;
+
+    *dk = NULL;
+    if(pkcs5->dklen > pkcs5->hashlen)
+        return -1;
+
+    /* Allocate the derived key buffer. */
+    *dk = LIBSSH2_ALLOC(session, pkcs5->hashlen);
+    if(!*dk)
+        return -1;
+
+    /* Initial hash. */
+    libssh2_os400qc3_hash_init(&hctx, pkcs5->hash);
+    libssh2_os400qc3_hash_update(&hctx, (unsigned char *) passphrase,
+                                 strlen(passphrase));
+    hctx.Final_Op_Flag = Qc3_Final;
+    Qc3CalculateHash((char *) pkcs5->salt, &len, Qc3_Data, (char *) &hctx,
+                     Qc3_Alg_Token, anycsp, NULL, *dk, (char *) &ecnull);
+
+    /* Iterate. */
+    len = pkcs5->hashlen;
+    for(i = 1; i < pkcs5->itercount; i++)
+        Qc3CalculateHash((char *) *dk, &len, Qc3_Data, (char *) &hctx,
+                         Qc3_Alg_Token, anycsp, NULL, *dk, (char *) &ecnull);
+
+    /* Special stuff for PBES1: split derived key into 8-byte key and 8-byte
+       initialization vector. */
+    pkcs5->dklen = 8;
+    pkcs5->ivlen = 8;
+    pkcs5->iv = *dk + 8;
+
+    /* Clean-up and exit. */
+    Qc3DestroyAlgorithmContext(hctx.Alg_Context_Token, (char *) &ecnull);
+    return 0;
+}
+
+static int
+pbkdf2(LIBSSH2_SESSION *session, char **dk, const unsigned char *passphrase,
+       pkcs5params *pkcs5)
+{
+    size_t i;
+    size_t k;
+    int j;
+    int l;
+    uint32_t ni;
+    unsigned long long t;
+    char *mac;
+    char *buf;
+    _libssh2_os400qc3_crypto_ctx hctx;
+
+    *dk = NULL;
+    t = ((unsigned long long) pkcs5->dklen + pkcs5->hashlen - 1) /
+        pkcs5->hashlen;
+    if(t > 0xFFFFFFFF)
+        return -1;
+    mac = alloca(pkcs5->hashlen);
+    if(!mac)
+        return -1;
+
+    /* Allocate the derived key buffer. */
+    l = t;
+    buf = LIBSSH2_ALLOC(session, l * pkcs5->hashlen);
+    if(!buf)
+        return -1;
+    *dk = buf;
+
+    /* Create an HMAC context for our computations. */
+    libssh2_os400qc3_hmac_init(&hctx, pkcs5->hash, pkcs5->hashlen,
+                               (void *) passphrase, strlen(passphrase));
+
+    /* Process each hLen-size blocks. */
+    for(i = 1; i <= l; i++) {
+        ni = htonl(i);
+        libssh2_os400qc3_hmac_update(&hctx, pkcs5->salt, pkcs5->saltlen);
+        libssh2_os400qc3_hmac_update(&hctx, (char *) &ni, sizeof ni);
+        libssh2_os400qc3_hmac_final(&hctx, mac);
+        memcpy(buf, mac, pkcs5->hashlen);
+        for(j = 1; j < pkcs5->itercount; j++) {
+            libssh2_os400qc3_hmac_update(&hctx, mac, pkcs5->hashlen);
+            libssh2_os400qc3_hmac_final(&hctx, mac);
+            for(k = 0; k < pkcs5->hashlen; k++)
+                buf[k] ^= mac[k];
+        }
+        buf += pkcs5->hashlen;
+    }
+
+    /* Computation done. Release HMAC context. */
+    _libssh2_os400qc3_crypto_dtor(&hctx);
+    return 0;
+}
+
+static int
+parse_pkcs5_algorithm(LIBSSH2_SESSION *session, pkcs5params *pkcs5,
+                      asn1Element *algid, pkcs5algo **algotable)
+{
+    asn1Element oid;
+    asn1Element param;
+    char *cp;
+
+    cp = getASN1Element(&oid, algid->beg, algid->end);
+    if(!cp || *oid.header != ASN1_OBJ_ID)
+        return -1;
+    param.header = NULL;
+    if(cp < algid->end)
+        cp = getASN1Element(&param, cp, algid->end);
+    if(cp != algid->end)
+        return -1;
+    for(; *algotable; algotable++)
+        if(!oidcmp(&oid, (*algotable)->oid))
+            return (*(*algotable)->parse)(session, pkcs5, *algotable,
+                                          param.header? &param: NULL);
+    return -1;
+}
+
+static int
+parse_pbes2(LIBSSH2_SESSION *session, pkcs5params *pkcs5,
+            pkcs5algo *algo, asn1Element *param)
+{
+    asn1Element keyDerivationFunc;
+    asn1Element encryptionScheme;
+    char *cp;
+
+    if(!param || *param->header != (ASN1_SEQ | ASN1_CONSTRUCTED))
+        return -1;
+    cp = getASN1Element(&keyDerivationFunc, param->beg, param->end);
+    if(!cp || *keyDerivationFunc.header != (ASN1_SEQ | ASN1_CONSTRUCTED))
+        return -1;
+    if(getASN1Element(&encryptionScheme, cp, param->end) != param->end ||
+        *encryptionScheme.header != (ASN1_SEQ | ASN1_CONSTRUCTED))
+        return -1;
+    if(parse_pkcs5_algorithm(session, pkcs5, &encryptionScheme, pbes2enctable))
+        return -1;
+    if(parse_pkcs5_algorithm(session, pkcs5, &keyDerivationFunc, pbkdf2table))
+        return -1;
+    return 0;
+}
+
+static int
+parse_pbkdf2(LIBSSH2_SESSION *session, pkcs5params *pkcs5,
+             pkcs5algo *algo, asn1Element *param)
+{
+    asn1Element salt;
+    asn1Element iterationCount;
+    asn1Element keyLength;
+    asn1Element prf;
+    unsigned long itercount;
+    char *cp;
+
+    if(!param || *param->header != (ASN1_SEQ | ASN1_CONSTRUCTED))
+        return -1;
+    cp = getASN1Element(&salt, param->beg, param->end);
+    /* otherSource not supported. */
+    if(!cp || *salt.header != ASN1_OCTET_STRING)
+        return -1;
+    cp = getASN1Element(&iterationCount, cp, param->end);
+    if(!cp || *iterationCount.header != ASN1_INTEGER)
+        return -1;
+    keyLength.header = prf.header = NULL;
+    if(cp < param->end) {
+        cp = getASN1Element(&prf, cp, param->end);
+        if(!cp)
+            return -1;
+        if(*prf.header == ASN1_INTEGER) {
+            keyLength = prf;
+            prf.header = NULL;
+            if(cp < param->end)
+                cp = getASN1Element(&prf, cp, param->end);
+        }
+        if(cp != param->end)
+            return -1;
+    }
+    pkcs5->hash = algo->hash;
+    pkcs5->hashlen = algo->hashlen;
+    if(prf.header) {
+        if(*prf.header != (ASN1_SEQ | ASN1_CONSTRUCTED))
+            return -1;
+        if(parse_pkcs5_algorithm(session, pkcs5, &prf, kdf2prftable))
+            return -1;
+    }
+    pkcs5->saltlen = salt.end - salt.beg;
+    pkcs5->salt = salt.beg;
+    if(asn1getword(&iterationCount, &itercount) ||
+        !itercount || itercount > 100000)
+        return -1;
+    pkcs5->itercount = itercount;
+    pkcs5->kdf = pbkdf2;
+    return 0;
+}
+
+static int
+parse_hmacWithSHA1(LIBSSH2_SESSION *session, pkcs5params *pkcs5,
+                   pkcs5algo *algo, asn1Element *param)
+{
+    if(!param || *param->header != ASN1_NULL)
+        return -1;
+    pkcs5->hash = algo->hash;
+    pkcs5->hashlen = algo->hashlen;
+    return 0;
+}
+
+static int
+parse_iv(LIBSSH2_SESSION *session, pkcs5params *pkcs5,
+         pkcs5algo *algo, asn1Element *param)
+{
+    if(!param || *param->header != ASN1_OCTET_STRING ||
+        param->end - param->beg != algo->ivlen)
+        return -1;
+    pkcs5->cipher = algo->cipher;
+    pkcs5->blocksize = algo->blocksize;
+    pkcs5->mode = algo->mode;
+    pkcs5->padopt = algo->padopt;
+    pkcs5->padchar = algo->padchar;
+    pkcs5->dklen = algo->keylen;
+    pkcs5->ivlen = algo->ivlen;
+    pkcs5->iv = param->beg;
+    return 0;
+}
+
+static int
+parse_rc2(LIBSSH2_SESSION *session, pkcs5params *pkcs5,
+          pkcs5algo *algo, asn1Element *param)
+{
+    asn1Element iv;
+    unsigned long effkeysize;
+    char *cp;
+
+    if(!param || *param->header != (ASN1_SEQ | ASN1_CONSTRUCTED))
+        return -1;
+    cp = getASN1Element(&iv, param->beg, param->end);
+    if(!cp)
+        return -1;
+    effkeysize = algo->effkeysize;
+    if(*iv.header == ASN1_INTEGER) {
+        if(asn1getword(&iv, &effkeysize) || effkeysize > 1024)
+            return -1;
+
+        cp = getASN1Element(&iv, cp, param->end);
+        if(effkeysize < 256)
+            switch(effkeysize) {
+            case 160:
+                effkeysize = 40;
+            case 120:
+                effkeysize = 64;
+            case 58:
+                effkeysize = 128;
+                break;
+            default:
+                return -1;
+            }
+    }
+    if(effkeysize > 1024 || cp != param->end ||
+        *iv.header != ASN1_OCTET_STRING || iv.end - iv.beg != algo->ivlen)
+        return -1;
+    pkcs5->cipher = algo->cipher;
+    pkcs5->blocksize = algo->blocksize;
+    pkcs5->mode = algo->mode;
+    pkcs5->padopt = algo->padopt;
+    pkcs5->padchar = algo->padchar;
+    pkcs5->ivlen = algo->ivlen;
+    pkcs5->iv = iv.beg;
+    pkcs5->effkeysize = effkeysize;
+    pkcs5->dklen = (effkeysize + 8 - 1) / 8;
+    return 0;
+}
+
+static int
+parse_pbes1(LIBSSH2_SESSION *session, pkcs5params *pkcs5,
+            pkcs5algo *algo, asn1Element *param)
+{
+    asn1Element salt;
+    asn1Element iterationCount;
+    unsigned long itercount;
+    char *cp;
+
+    if(!param || *param->header != (ASN1_SEQ | ASN1_CONSTRUCTED))
+        return -1;
+
+    cp = getASN1Element(&salt, param->beg, param->end);
+    if(!cp || *salt.header != ASN1_OCTET_STRING ||
+        salt.end - salt.beg != algo->saltlen)
+        return -1;
+    if(getASN1Element(&iterationCount, cp, param->end) != param->end ||
+        *iterationCount.header != ASN1_INTEGER)
+        return -1;
+    if(asn1getword(&iterationCount, &itercount) ||
+        !itercount || itercount > 100000)
+        return -1;
+    pkcs5->cipher = algo->cipher;
+    pkcs5->blocksize = algo->blocksize;
+    pkcs5->mode = algo->mode;
+    pkcs5->padopt = algo->padopt;
+    pkcs5->padchar = algo->padchar;
+    pkcs5->hash = algo->hash;
+    pkcs5->hashlen = algo->hashlen;
+    pkcs5->dklen = 16;
+    pkcs5->saltlen = algo->saltlen;
+    pkcs5->effkeysize = algo->effkeysize;
+    pkcs5->salt = salt.beg;
+    pkcs5->kdf = pbkdf1;
+    pkcs5->itercount = itercount;
+    return 0;
+}
+
+static int
+pkcs8kek(LIBSSH2_SESSION *session, _libssh2_os400qc3_crypto_ctx **ctx,
+         const unsigned char *data, unsigned int datalen,
+         const unsigned char *passphrase, asn1Element *privkeyinfo)
+{
+    asn1Element encprivkeyinfo;
+    asn1Element pkcs5alg;
+    pkcs5params pkcs5;
+    size_t pplen;
+    char *cp;
+    unsigned long t;
+    int i;
+    char *dk = NULL;
+    Qc3_Format_ALGD0200_T algd;
+    Qus_EC_t errcode;
+
+    /* Determine if the PKCS#8 data is encrypted and, if so, set-up a
+       key encryption key and algorithm in context.
+       Return 1 if encrypted, 0, if not, -1 if error. */
+
+    *ctx = NULL;
+    privkeyinfo->beg = (char *) data;
+    privkeyinfo->end = privkeyinfo->beg + datalen;
+
+    /* If no passphrase is given, it cannot be an encrypted key. */
+    if(!passphrase || !*passphrase)
+        return 0;
+
+    /* Parse PKCS#8 data, checking if ASN.1 format is PrivateKeyInfo or
+       EncryptedPrivateKeyInfo. */
+    if(getASN1Element(&encprivkeyinfo, privkeyinfo->beg, privkeyinfo->end) !=
+        (char *) data + datalen ||
+        *encprivkeyinfo.header != (ASN1_SEQ | ASN1_CONSTRUCTED))
+        return -1;
+    cp = getASN1Element(&pkcs5alg, encprivkeyinfo.beg, encprivkeyinfo.end);
+    if(!cp)
+        return -1;
+
+    switch(*pkcs5alg.header) {
+    case ASN1_INTEGER:                          /* Version. */
+        return 0;       /* This is a PrivateKeyInfo --> not encrypted. */
+    case ASN1_SEQ | ASN1_CONSTRUCTED:           /* AlgorithIdentifier. */
+        break;          /* This is an EncryptedPrivateKeyInfo --> encrypted. */
+    default:
+        return -1;      /* Unrecognized: error. */
+    }
+
+    /* Get the encrypted key data. */
+    if(getASN1Element(privkeyinfo, cp, encprivkeyinfo.end) !=
+        encprivkeyinfo.end || *privkeyinfo->header != ASN1_OCTET_STRING)
+        return -1;
+
+    /* PKCS#5: parse the PBES AlgorithmIdentifier and recursively get all
+       encryption parameters. */
+    memset((char *) &pkcs5, 0, sizeof pkcs5);
+    if(parse_pkcs5_algorithm(session, &pkcs5, &pkcs5alg, pbestable))
+        return -1;
+
+    /* Compute the derived key. */
+    if((*pkcs5.kdf)(session, &dk, passphrase, &pkcs5))
+        return -1;
+
+    /* Prepare the algorithm descriptor. */
+    memset((char *) &algd, 0, sizeof algd);
+    algd.Block_Cipher_Alg = pkcs5.cipher;
+    algd.Block_Length = pkcs5.blocksize;
+    algd.Mode = pkcs5.mode;
+    algd.Pad_Option = pkcs5.padopt;
+    algd.Pad_Character = pkcs5.padchar;
+    algd.Effective_Key_Size = pkcs5.effkeysize;
+    memcpy(algd.Init_Vector, pkcs5.iv, pkcs5.ivlen);
+
+    /* Create the key and algorithm context tokens. */
+    *ctx = libssh2_init_crypto_ctx(NULL);
+    if(!*ctx) {
+        LIBSSH2_FREE(session, dk);
+        return -1;
+    }
+    libssh2_init_crypto_ctx(*ctx);
+    set_EC_length(errcode, sizeof errcode);
+    Qc3CreateKeyContext(dk, &pkcs5.dklen, binstring, &algd.Block_Cipher_Alg,
+                        qc3clear, NULL, NULL, (*ctx)->key.Key_Context_Token,
+                        (char *) &errcode);
+    LIBSSH2_FREE(session, dk);
+    if(errcode.Bytes_Available) {
+        free((char *) *ctx);
+        *ctx = NULL;
+        return -1;
+    }
+
+    Qc3CreateAlgorithmContext((char *) &algd, Qc3_Alg_Block_Cipher,
+                              (*ctx)->hash.Alg_Context_Token, &errcode);
+    if(errcode.Bytes_Available) {
+        Qc3DestroyKeyContext((*ctx)->key.Key_Context_Token, (char *) &ecnull);
+        free((char *) *ctx);
+        *ctx = NULL;
+        return -1;
+    }
+    return 1;       /* Tell it's encrypted. */
+}
+
+static int
+rsapkcs8privkey(LIBSSH2_SESSION *session,
+                const unsigned char *data, unsigned int datalen,
+                const unsigned char *passphrase, void *loadkeydata)
+{
+    libssh2_rsa_ctx *ctx = (libssh2_rsa_ctx *) loadkeydata;
+    char keyform = Qc3_Clear;
+    char *kek = NULL;
+    char *kea = NULL;
+    _libssh2_os400qc3_crypto_ctx *kekctx;
+    asn1Element pki;
+    int pkilen;
+    Qus_EC_t errcode;
+
+    switch(pkcs8kek(session, &kekctx, data, datalen, passphrase, &pki)) {
+    case 1:
+        keyform = Qc3_Encrypted;
+        kek = kekctx->key.Key_Context_Token;
+        kea = kekctx->hash.Alg_Context_Token;
+    case 0:
+        break;
+    default:
+        return -1;
+    }
+
+    set_EC_length(errcode, sizeof errcode);
+    pkilen = pki.end - pki.beg;
+    Qc3CreateKeyContext((unsigned char *) pki.beg, &pkilen, berstring,
+                        rsaprivate, &keyform, kek, kea,
+                        ctx->key.Key_Context_Token, (char *) &errcode);
+    if(errcode.Bytes_Available) {
+        if(kekctx)
+            _libssh2_os400qc3_crypto_dtor(kekctx);
+        return -1;
+    }
+    ctx->kek = kekctx;
+    return 0;
+}
+
+static char *
+storewithlength(char *p, const char *data, int length)
+{
+    _libssh2_htonu32(p, length);
+    if(length)
+        memcpy(p + 4, data, length);
+    return p + 4 + length;
+}
+
+static int
+sshrsapubkey(LIBSSH2_SESSION *session, char **sshpubkey,
+             asn1Element *params, asn1Element *key, const char *method)
+{
+    int methlen = strlen(method);
+    asn1Element keyseq;
+    asn1Element m;
+    asn1Element e;
+    int len;
+    char *cp;
+
+    if(getASN1Element(&keyseq, key->beg + 1, key->end) != key->end ||
+        *keyseq.header != (ASN1_SEQ | ASN1_CONSTRUCTED))
+        return -1;
+    if(!getASN1Element(&m, keyseq.beg, keyseq.end) ||
+        *m.header != ASN1_INTEGER)
+        return -1;
+    if(getASN1Element(&e, m.end, keyseq.end) != keyseq.end ||
+        *e.header != ASN1_INTEGER)
+        return -1;
+    len = 4 + methlen + 4 + (e.end - e.beg) + 4 + (m.end - m.beg);
+    cp = LIBSSH2_ALLOC(session, len);
+    if(!cp)
+        return -1;
+    *sshpubkey = cp;
+    cp = storewithlength(cp, method, methlen);
+    cp = storewithlength(cp, e.beg, e.end - e.beg);
+    cp = storewithlength(cp, m.beg, m.end - m.beg);
+    return len;
+}
+
+static int
+rsapkcs8pubkey(LIBSSH2_SESSION *session,
+               const unsigned char *data, unsigned int datalen,
+               const unsigned char *passphrase, void *loadkeydata)
+{
+    loadpubkeydata *p = (loadpubkeydata *) loadkeydata;
+    char *buf;
+    int len;
+    char *cp;
+    int i;
+    char keyform = Qc3_Clear;
+    char *kek = NULL;
+    char *kea = NULL;
+    _libssh2_os400qc3_crypto_ctx *kekctx;
+    asn1Element subjpubkeyinfo;
+    asn1Element algorithmid;
+    asn1Element algorithm;
+    asn1Element subjpubkey;
+    asn1Element parameters;
+    asn1Element pki;
+    int pkilen;
+    Qus_EC_t errcode;
+
+    buf = alloca(datalen);
+    if(!buf)
+        return -1;
+
+    switch(pkcs8kek(session, &kekctx, data, datalen, passphrase, &pki)) {
+    case 1:
+        keyform = Qc3_Encrypted;
+        kek = kekctx->key.Key_Context_Token;
+        kea = kekctx->hash.Alg_Context_Token;
+    case 0:
+        break;
+    default:
+        return -1;
+    }
+
+    set_EC_length(errcode, sizeof errcode);
+    pkilen = pki.end - pki.beg;
+    Qc3ExtractPublicKey(pki.beg, &pkilen, berstring, &keyform,
+                        kek, kea, buf, (int *) &datalen, &len, &errcode);
+    _libssh2_os400qc3_crypto_dtor(kekctx);
+    if(errcode.Bytes_Available)
+        return -1;
+    /* Get the algorithm OID and key data from SubjectPublicKeyInfo. */
+    if(getASN1Element(&subjpubkeyinfo, buf, buf + len) != buf + len ||
+        *subjpubkeyinfo.header != (ASN1_SEQ | ASN1_CONSTRUCTED))
+        return -1;
+    cp = getASN1Element(&algorithmid, subjpubkeyinfo.beg, subjpubkeyinfo.end);
+    if(!cp || *algorithmid.header != (ASN1_SEQ | ASN1_CONSTRUCTED))
+        return -1;
+    if(!getASN1Element(&algorithm, algorithmid.beg, algorithmid.end) ||
+        *algorithm.header != ASN1_OBJ_ID)
+        return -1;
+    if(getASN1Element(&subjpubkey, cp, subjpubkeyinfo.end) !=
+        subjpubkeyinfo.end || *subjpubkey.header != ASN1_BIT_STRING)
+        return -1;
+    /* Check for supported algorithm. */
+    for(i = 0; pka[i].oid; i++)
+        if(!oidcmp(&algorithm, pka[i].oid)) {
+            len = (*pka[i].sshpubkey)(session, &p->data, &algorithmid,
+                                      &subjpubkey, pka[i].method);
+            if(len < 0)
+                return -1;
+            p->length = len;
+            p->method = pka[i].method;
+            return 0;
+        }
+    return -1;                              /* Algorithm not supported. */
+}
+
+static int
+pkcs1topkcs8(LIBSSH2_SESSION *session,
+             const unsigned char **data8, unsigned int *datalen8,
+             const unsigned char *data1, unsigned int datalen1)
+{
+    asn1Element *prvk;
+    asn1Element *pkcs8;
+    unsigned char *data;
+
+    *data8 = NULL;
+    *datalen8 = 0;
+    if(datalen1 < 2)
+        return -1;
+    prvk = asn1_new_from_bytes(data1, datalen1);
+    if(!prvk)
+        return -1;
+    pkcs8 = rsaprivatekeyinfo(prvk);
+    asn1delete(prvk);
+    if(!prvk) {
+        asn1delete(pkcs8);
+        pkcs8 = NULL;
+    }
+    if(!pkcs8)
+        return -1;
+    data = (unsigned char *) LIBSSH2_ALLOC(session,
+                                           pkcs8->end - pkcs8->header);
+    if(!data) {
+        asn1delete(pkcs8);
+        return -1;
+    }
+    *data8 = data;
+    *datalen8 = pkcs8->end - pkcs8->header;
+    memcpy((char *) data, (char *) pkcs8->header, *datalen8);
+    asn1delete(pkcs8);
+    return 0;
+}
+
+static int
+rsapkcs1privkey(LIBSSH2_SESSION *session,
+                const unsigned char *data, unsigned int datalen,
+                const unsigned char *passphrase, void *loadkeydata)
+{
+    const unsigned char *data8;
+    unsigned int datalen8;
+    int ret;
+
+    if(pkcs1topkcs8(session, &data8, &datalen8, data, datalen))
+        return -1;
+    ret = rsapkcs8privkey(session, data8, datalen8, passphrase, loadkeydata);
+    LIBSSH2_FREE(session, (char *) data8);
+    return ret;
+}
+
+static int
+rsapkcs1pubkey(LIBSSH2_SESSION *session,
+               const unsigned char *data, unsigned int datalen,
+               const unsigned char *passphrase, void *loadkeydata)
+{
+    const unsigned char *data8;
+    unsigned int datalen8;
+    int ret;
+
+    if(pkcs1topkcs8(session, &data8, &datalen8, data, datalen))
+        return -1;
+    ret = rsapkcs8pubkey(session, data8, datalen8, passphrase, loadkeydata);
+    LIBSSH2_FREE(session, (char *) data8);
+    return ret;
+}
+
+static int
+try_pem_load(LIBSSH2_SESSION *session, FILE *fp,
+             const unsigned char *passphrase,
+             const char *header, const char *trailer,
+             loadkeyproc proc, void *loadkeydata)
+{
+    unsigned char *data = NULL;
+    unsigned int datalen = 0;
+    int c;
+    int ret;
+
+    fseek(fp, 0L, SEEK_SET);
+    for(;;) {
+        ret = _libssh2_pem_parse(session, header, trailer,
+                                 passphrase,
+                                 fp, &data, &datalen);
+
+        if(!ret) {
+            ret = (*proc)(session, data, datalen, passphrase, loadkeydata);
+            if(!ret)
+                return 0;
+        }
+
+        if(data) {
+            LIBSSH2_FREE(session, data);
+            data = NULL;
+        }
+        c = getc(fp);
+
+        if(c == EOF)
+            break;
+
+        ungetc(c, fp);
+    }
+
+    return -1;
+}
+
+static int
+load_rsa_private_file(LIBSSH2_SESSION *session, const char *filename,
+                      unsigned const char *passphrase,
+                      loadkeyproc proc1, loadkeyproc proc8, void *loadkeydata)
+{
+    FILE *fp = fopen(filename, fopenrmode);
+    unsigned char *data = NULL;
+    size_t datalen = 0;
+    int ret;
+    long filesize;
+
+    if(!fp)
+        return -1;
+
+    /* Try with "ENCRYPTED PRIVATE KEY" PEM armor.
+       --> PKCS#8 EncryptedPrivateKeyInfo */
+    ret = try_pem_load(session, fp, passphrase, beginencprivkeyhdr,
+                       endencprivkeyhdr, proc8, loadkeydata);
+
+    /* Try with "PRIVATE KEY" PEM armor.
+       --> PKCS#8 PrivateKeyInfo or EncryptedPrivateKeyInfo */
+    if(ret)
+        ret = try_pem_load(session, fp, passphrase, beginprivkeyhdr,
+                           endprivkeyhdr, proc8, loadkeydata);
+
+    /* Try with "RSA PRIVATE KEY" PEM armor.
+       --> PKCS#1 RSAPrivateKey */
+    if(ret)
+        ret = try_pem_load(session, fp, passphrase, beginrsaprivkeyhdr,
+                           endrsaprivkeyhdr, proc1, loadkeydata);
+    fclose(fp);
+
+    if(ret) {
+        /* Try DER encoding. */
+        fp = fopen(filename, fopenrbmode);
+        fseek(fp, 0L, SEEK_END);
+        filesize = ftell(fp);
+
+        if(filesize <= 32768) {        /* Limit to a reasonable size. */
+            datalen = filesize;
+            data = (unsigned char *) alloca(datalen);
+            if(data) {
+                fseek(fp, 0L, SEEK_SET);
+                fread(data, datalen, 1, fp);
+
+                /* Try as PKCS#8 DER data.
+                   --> PKCS#8 PrivateKeyInfo or EncryptedPrivateKeyInfo */
+                ret = (*proc8)(session, data, datalen, passphrase,
+                               loadkeydata);
+
+                /* Try as PKCS#1 DER data.
+                   --> PKCS#1 RSAPrivateKey */
+                if(ret)
+                    ret = (*proc1)(session, data, datalen, passphrase,
+                                   loadkeydata);
+            }
+        }
+        fclose(fp);
+    }
+
+    return ret;
+}
+
+int
+_libssh2_rsa_new_private(libssh2_rsa_ctx **rsa, LIBSSH2_SESSION *session,
+                         const char *filename, unsigned const char *passphrase)
+{
+    libssh2_rsa_ctx *ctx = libssh2_init_crypto_ctx(NULL);
+    int ret;
+    Qc3_Format_ALGD0400_T algd;
+    Qus_EC_t errcode;
+
+    if(!ctx)
+        return -1;
+    ret = load_rsa_private_file(session, filename, passphrase,
+                                rsapkcs1privkey, rsapkcs8privkey,
+                                (void *) ctx);
+    if(!ret) {
+        /* Create the algorithm context. */
+        algd.Public_Key_Alg = Qc3_RSA;
+        algd.PKA_Block_Format = Qc3_PKCS1_01;
+        memset(algd.Reserved, 0, sizeof algd.Reserved);
+        algd.Signing_Hash_Alg = Qc3_SHA1;
+        set_EC_length(errcode, sizeof errcode);
+        Qc3CreateAlgorithmContext((char *) &algd, Qc3_Alg_Public_Key,
+                                  ctx->hash.Alg_Context_Token, &errcode);
+        if(errcode.Bytes_Available)
+            ret = -1;
+    }
+    if(ret) {
+        _libssh2_os400qc3_crypto_dtor(ctx);
+        ctx = NULL;
+    }
+    *rsa = ctx;
+    return ret;
+}
+
+int
+_libssh2_pub_priv_keyfile(LIBSSH2_SESSION *session,
+                          unsigned char **method, size_t *method_len,
+                          unsigned char **pubkeydata, size_t *pubkeydata_len,
+                          const char *privatekey, const char *passphrase)
+
+{
+    loadpubkeydata p;
+    int ret;
+
+    *method = NULL;
+    *method_len = 0;
+    *pubkeydata = NULL;
+    *pubkeydata_len = 0;
+
+    ret = load_rsa_private_file(session, privatekey, passphrase,
+                                rsapkcs1pubkey, rsapkcs8pubkey, (void *) &p);
+    if(!ret) {
+        *method_len = strlen(p.method);
+        *method = LIBSSH2_ALLOC(session, *method_len);
+        if(*method)
+            memcpy((char *) *method, p.method, *method_len);
+        else
+            ret = -1;
+    }
+
+    if(ret) {
+        if(*method)
+            LIBSSH2_FREE(session, *method);
+        if(p.data)
+            LIBSSH2_FREE(session, (void *) p.data);
+        *method = NULL;
+        *method_len = 0;
+    }
+    else {
+        *pubkeydata = (unsigned char *) p.data;
+        *pubkeydata_len = p.length;
+    }
+
+    return ret;
+}
+
+int
+_libssh2_rsa_new_private_frommemory(libssh2_rsa_ctx **rsa,
+                                    LIBSSH2_SESSION *session,
+                                    const char *filedata,
+                                    size_t filedata_len,
+                                    unsigned const char *passphrase)
+{
+    libssh2_rsa_ctx *ctx = libssh2_init_crypto_ctx(NULL);
+    unsigned char *data = NULL;
+    unsigned int datalen = 0;
+    int ret;
+    Qc3_Format_ALGD0400_T algd;
+    Qus_EC_t errcode;
+
+    if(!ctx)
+        return -1;
+
+    /* Try with "ENCRYPTED PRIVATE KEY" PEM armor.
+       --> PKCS#8 EncryptedPrivateKeyInfo */
+    ret = _libssh2_pem_parse_memory(session,
+                                    beginencprivkeyhdr, endencprivkeyhdr,
+                                    filedata, filedata_len, &data, &datalen);
+
+    /* Try with "PRIVATE KEY" PEM armor.
+       --> PKCS#8 PrivateKeyInfo or EncryptedPrivateKeyInfo */
+    if(ret)
+        ret = _libssh2_pem_parse_memory(session,
+                                        beginprivkeyhdr, endprivkeyhdr,
+                                        filedata, filedata_len,
+                                        &data, &datalen);
+
+    if(!ret) {
+        /* Process PKCS#8. */
+        ret = rsapkcs8privkey(session,
+                              data, datalen, passphrase, (void *) &ctx);
+    }
+    else {
+        /* Try with "RSA PRIVATE KEY" PEM armor.
+           --> PKCS#1 RSAPrivateKey */
+        ret = _libssh2_pem_parse_memory(session,
+                                        beginrsaprivkeyhdr, endrsaprivkeyhdr,
+                                        filedata, filedata_len,
+                                        &data, &datalen);
+        if(!ret)
+            ret = rsapkcs1privkey(session,
+                                  data, datalen, passphrase, (void *) &ctx);
+    }
+
+    if(ret) {
+        /* Try as PKCS#8 DER data.
+           --> PKCS#8 PrivateKeyInfo or EncryptedPrivateKeyInfo */
+        ret = rsapkcs8privkey(session, filedata, filedata_len,
+                              passphrase, (void *) &ctx);
+
+        /* Try as PKCS#1 DER data.
+           --> PKCS#1 RSAPrivateKey */
+        if(ret)
+            ret = rsapkcs1privkey(session, filedata, filedata_len,
+                                  passphrase, (void *) &ctx);
+    }
+
+    if(data)
+        LIBSSH2_FREE(session, data);
+
+    if(!ret) {
+        /* Create the algorithm context. */
+        algd.Public_Key_Alg = Qc3_RSA;
+        algd.PKA_Block_Format = Qc3_PKCS1_01;
+        memset(algd.Reserved, 0, sizeof algd.Reserved);
+        algd.Signing_Hash_Alg = Qc3_SHA1;
+        set_EC_length(errcode, sizeof errcode);
+        Qc3CreateAlgorithmContext((char *) &algd, Qc3_Alg_Public_Key,
+                                  ctx->hash.Alg_Context_Token, &errcode);
+        if(errcode.Bytes_Available)
+            ret = -1;
+    }
+
+    if(ret) {
+        _libssh2_os400qc3_crypto_dtor(ctx);
+        ctx = NULL;
+    }
+
+    *rsa = ctx;
+    return ret;
+}
+
+int
+_libssh2_pub_priv_keyfilememory(LIBSSH2_SESSION *session,
+                                unsigned char **method, size_t *method_len,
+                                unsigned char **pubkeydata,
+                                size_t *pubkeydata_len,
+                                const char *privatekeydata,
+                                size_t privatekeydata_len,
+                                const char *passphrase)
+{
+    loadpubkeydata p;
+    unsigned char *data = NULL;
+    unsigned int datalen = 0;
+    const char *meth;
+    int ret;
+
+    *method = NULL;
+    *method_len = 0;
+    *pubkeydata = NULL;
+    *pubkeydata_len = 0;
+
+    /* Try with "ENCRYPTED PRIVATE KEY" PEM armor.
+       --> PKCS#8 EncryptedPrivateKeyInfo */
+    ret = _libssh2_pem_parse_memory(session,
+                                    beginencprivkeyhdr, endencprivkeyhdr,
+                                    privatekeydata, privatekeydata_len,
+                                    &data, &datalen);
+
+    /* Try with "PRIVATE KEY" PEM armor.
+       --> PKCS#8 PrivateKeyInfo or EncryptedPrivateKeyInfo */
+    if(ret)
+        ret = _libssh2_pem_parse_memory(session,
+                                        beginprivkeyhdr, endprivkeyhdr,
+                                        privatekeydata, privatekeydata_len,
+                                        &data, &datalen);
+
+    if(!ret) {
+        /* Process PKCS#8. */
+        ret = rsapkcs8pubkey(session,
+                             data, datalen, passphrase, (void *) &p);
+    }
+    else {
+        /* Try with "RSA PRIVATE KEY" PEM armor.
+           --> PKCS#1 RSAPrivateKey */
+        ret = _libssh2_pem_parse_memory(session,
+                                        beginrsaprivkeyhdr, endrsaprivkeyhdr,
+                                        privatekeydata, privatekeydata_len,
+                                        &data, &datalen);
+        if(!ret)
+            ret = rsapkcs1pubkey(session,
+                                 data, datalen, passphrase, (void *) &p);
+    }
+
+    if(ret) {
+        /* Try as PKCS#8 DER data.
+           --> PKCS#8 PrivateKeyInfo or EncryptedPrivateKeyInfo */
+        ret = rsapkcs8pubkey(session, privatekeydata, privatekeydata_len,
+                             passphrase, (void *) &p);
+
+        /* Try as PKCS#1 DER data.
+           --> PKCS#1 RSAPrivateKey */
+        if(ret)
+            ret = rsapkcs1pubkey(session, privatekeydata, privatekeydata_len,
+                                 passphrase, (void *) &p);
+    }
+
+    if(data)
+        LIBSSH2_FREE(session, data);
+
+    if(!ret) {
+        *method_len = strlen(p.method);
+        *method = LIBSSH2_ALLOC(session, *method_len);
+        if(*method)
+            memcpy((char *) *method, p.method, *method_len);
+        else
+            ret = -1;
+    }
+    if(ret) {
+        if(*method)
+            LIBSSH2_FREE(session, *method);
+        if(p.data)
+            LIBSSH2_FREE(session, (void *) p.data);
+        *method = NULL;
+        *method_len = 0;
+    }
+    else {
+        *pubkeydata = (unsigned char *) p.data;
+        *pubkeydata_len = p.length;
+    }
+
+    return ret;
+}
+
+int
+_libssh2_rsa_sha1_verify(libssh2_rsa_ctx *rsa,
+                         const unsigned char *sig, unsigned long sig_len,
+                         const unsigned char *m, unsigned long m_len)
+{
+    Qus_EC_t errcode;
+    int slen = sig_len;
+    int mlen = m_len;
+
+    set_EC_length(errcode, sizeof errcode);
+    Qc3VerifySignature((char *) sig, &slen, (char *) m, &mlen, Qc3_Data,
+                       rsa->hash.Alg_Context_Token, Qc3_Alg_Token,
+                       rsa->key.Key_Context_Token, Qc3_Key_Token, anycsp,
+                       NULL, (char *) &errcode);
+    return errcode.Bytes_Available? -1: 0;
+}
+
+int
+_libssh2_os400qc3_rsa_sha1_signv(LIBSSH2_SESSION *session,
+                                 unsigned char **signature,
+                                 size_t *signature_len,
+                                 int veccount,
+                                 const struct iovec vector[],
+                                 libssh2_rsa_ctx *ctx)
+{
+    Qus_EC_t errcode;
+    int siglen;
+    unsigned char *sig;
+    char sigbuf[8192];
+    int sigbufsize = sizeof sigbuf;
+
+    ctx->hash.Final_Op_Flag = Qc3_Final;
+    set_EC_length(errcode, sizeof errcode);
+    Qc3CalculateSignature((char *) vector, &veccount, Qc3_Array,
+                          (char *) &ctx->hash, Qc3_Alg_Token,
+                          (char *) &ctx->key, Qc3_Key_Token,
+                          anycsp, NULL, sigbuf, &sigbufsize, &siglen,
+                          (char *) &errcode);
+    ctx->hash.Final_Op_Flag = Qc3_Continue;
+    if(errcode.Bytes_Available)
+        return -1;
+    sig = LIBSSH2_ALLOC(session, siglen);
+    if(!sig)
+        return -1;
+    memcpy((char *) sig, sigbuf, siglen);
+    *signature = sig;
+    *signature_len = siglen;
+    return 0;
+}
+
+#endif /* LIBSSH2_OS400QC3 */
+
+/* vim: set expandtab ts=4 sw=4: */

+ 373 - 0
libssh2/libssh2/src/os400qc3.h

@@ -0,0 +1,373 @@
+/*
+ * Copyright (C) 2015-2016 Patrick Monnerat, D+H <patrick.monnerat@dh.com>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms,
+ * with or without modification, are permitted provided
+ * that the following conditions are met:
+ *
+ *   Redistributions of source code must retain the above
+ *   copyright notice, this list of conditions and the
+ *   following disclaimer.
+ *
+ *   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.
+ *
+ *   Neither the name of the copyright holder nor the names
+ *   of any other contributors may be used to endorse or
+ *   promote products derived from this software without
+ *   specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+ * CONTRIBUTORS "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 COPYRIGHT OWNER OR
+ * CONTRIBUTORS 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 LIBSSH2_OS400QC3_H
+#define LIBSSH2_OS400QC3_H
+
+#include <stdlib.h>
+#include <string.h>
+
+#include <qc3cci.h>
+
+
+/* Redefine character/string literals as always EBCDIC. */
+#undef Qc3_Alg_Token
+#define Qc3_Alg_Token       "\xC1\xD3\xC7\xC4\xF0\xF1\xF0\xF0"  /* ALGD0100 */
+#undef Qc3_Alg_Block_Cipher
+#define Qc3_Alg_Block_Cipher "\xC1\xD3\xC7\xC4\xF0\xF2\xF0\xF0" /* ALGD0200 */
+#undef Qc3_Alg_Block_CipherAuth
+#define Qc3_Alg_Block_CipherAuth                                            \
+                            "\xC1\xD3\xC7\xC4\xF0\xF2\xF1\xF0"  /* ALGD0210 */
+#undef Qc3_Alg_Stream_Cipher
+#define Qc3_Alg_Stream_Cipher                                               \
+                            "\xC1\xD3\xC7\xC4\xF0\xF3\xF0\xF0"  /* ALGD0300 */
+#undef Qc3_Alg_Public_Key
+#define Qc3_Alg_Public_Key  "\xC1\xD3\xC7\xC4\xF0\xF4\xF0\xF0"  /* ALGD0400 */
+#undef Qc3_Alg_Hash
+#define Qc3_Alg_Hash        "\xC1\xD3\xC7\xC4\xF0\xF5\xF0\xF0"  /* ALGD0500 */
+#undef Qc3_Data
+#define Qc3_Data            "\xC4\xC1\xE3\xC1\xF0\xF1\xF0\xF0"  /* DATA0100 */
+#undef Qc3_Array
+#define Qc3_Array           "\xC4\xC1\xE3\xC1\xF0\xF2\xF0\xF0"  /* DATA0200 */
+#undef Qc3_Key_Token
+#define Qc3_Key_Token       "\xD2\xC5\xE8\xC4\xF0\xF1\xF0\xF0"  /* KEYD0100 */
+#undef Qc3_Key_Parms
+#define Qc3_Key_Parms       "\xD2\xC5\xE8\xC4\xF0\xF2\xF0\xF0"  /* KEYD0200 */
+#undef Qc3_Key_KSLabel
+#define Qc3_Key_KSLabel     "\xD2\xC5\xE8\xC4\xF0\xF4\xF0\xF0"  /* KEYD0400 */
+#undef Qc3_Key_PKCS5
+#define Qc3_Key_PKCS5       "\xD2\xC5\xE8\xC4\xF0\xF5\xF0\xF0"  /* KEYD0500 */
+#undef Qc3_Key_PEMCert
+#define Qc3_Key_PEMCert     "\xD2\xC5\xE8\xC4\xF0\xF6\xF0\xF0"  /* KEYD0600 */
+#undef Qc3_Key_CSLabel
+#define Qc3_Key_CSLabel     "\xD2\xC5\xE8\xC4\xF0\xF7\xF0\xF0"  /* KEYD0700 */
+#undef Qc3_Key_CSDN
+#define Qc3_Key_CSDN        "\xD2\xC5\xE8\xC4\xF0\xF8\xF0\xF0"  /* KEYD0800 */
+#undef Qc3_Key_AppID
+#define Qc3_Key_AppID       "\xD2\xC5\xE8\xC4\xF0\xF9\xF0\xF0"  /* KEYD0900 */
+
+#undef Qc3_ECB
+#define Qc3_ECB             '\xF0'      /* '0' */
+#undef Qc3_CBC
+#define Qc3_CBC             '\xF1'      /* '1' */
+#undef Qc3_OFB
+#define Qc3_OFB             '\xF2'      /* '2' */
+#undef Qc3_CFB1Bit
+#define Qc3_CFB1Bit         '\xF3'      /* '3' */
+#undef Qc3_CFB8Bit
+#define Qc3_CFB8Bit         '\xF4'      /* '4' */
+#undef Qc3_CFB64Bit
+#define Qc3_CFB64Bit        '\xF5'      /* '5' */
+#undef Qc3_CUSP
+#define Qc3_CUSP            '\xF6'      /* '6' */
+#undef Qc3_CTR
+#define Qc3_CTR             '\xF7'      /* '7' */
+#undef Qc3_CCM
+#define Qc3_CCM             '\xF8'      /* '8' */
+#undef Qc3_No_Pad
+#define Qc3_No_Pad          '\xF0'      /* '0' */
+#undef Qc3_Pad_Char
+#define Qc3_Pad_Char        '\xF1'      /* '1' */
+#undef Qc3_Pad_Counter
+#define Qc3_Pad_Counter     '\xF2'      /* '2' */
+#undef Qc3_PKCS1_00
+#define Qc3_PKCS1_00        '\xF0'      /* '0' */
+#undef Qc3_PKCS1_01
+#define Qc3_PKCS1_01        '\xF1'      /* '1' */
+#undef Qc3_PKCS1_02
+#define Qc3_PKCS1_02        '\xF2'      /* '2' */
+#undef Qc3_ISO9796
+#define Qc3_ISO9796         '\xF3'      /* '3' */
+#undef Qc3_Zero_Pad
+#define Qc3_Zero_Pad        '\xF4'      /* '4' */
+#undef Qc3_ANSI_X931
+#define Qc3_ANSI_X931       '\xF5'      /* '5' */
+#undef Qc3_OAEP
+#define Qc3_OAEP            '\xF6'      /* '6' */
+#undef Qc3_Bin_String
+#define Qc3_Bin_String      '\xF0'      /* '0' */
+#undef Qc3_BER_String
+#define Qc3_BER_String      '\xF1'      /* '1' */
+#undef Qc3_MK_Struct
+#define Qc3_MK_Struct       '\xF3'      /* '3' */
+#undef Qc3_KSLabel_Struct
+#define Qc3_KSLabel_Struct  '\xF4'      /* '4' */
+#undef Qc3_PKCS5_Struct
+#define Qc3_PKCS5_Struct    '\xF5'      /* '5' */
+#undef Qc3_PEMCert_String
+#define Qc3_PEMCert_String  '\xF6'      /* '6' */
+#undef Qc3_CSLabel_String
+#define Qc3_CSLabel_String  '\xF7'      /* '7' */
+#undef Qc3_CSDN_String
+#define Qc3_CSDN_String     '\xF8'      /* '8' */
+#undef Qc3_Clear
+#define Qc3_Clear           '\xF0'      /* '0' */
+#undef Qc3_Encrypted
+#define Qc3_Encrypted       '\xF1'      /* '1' */
+#undef Qc3_MK_Encrypted
+#define Qc3_MK_Encrypted    '\xF2'      /* '2' */
+#undef Qc3_Any_CSP
+#define Qc3_Any_CSP         '\xF0'      /* '0' */
+#undef Qc3_Sfw_CSP
+#define Qc3_Sfw_CSP         '\xF1'      /* '1' */
+#undef Qc3_Hdw_CSP
+#define Qc3_Hdw_CSP         '\xF2'      /* '2' */
+#undef Qc3_Continue
+#define Qc3_Continue        '\xF0'      /* '0' */
+#undef Qc3_Final
+#define Qc3_Final           '\xF1'      /* '1' */
+#undef Qc3_MK_New
+#define Qc3_MK_New          '\xF0'      /* '0' */
+#undef Qc3_MK_Current
+#define Qc3_MK_Current      '\xF1'      /* '1' */
+#undef Qc3_MK_Old
+#define Qc3_MK_Old          '\xF2'      /* '2' */
+#undef Qc3_MK_Pending
+#define Qc3_MK_Pending      '\xF3'      /* '3' */
+
+
+/* Define which features are supported. */
+#define LIBSSH2_MD5             1
+#define LIBSSH2_HMAC_RIPEMD     0
+#define LIBSSH2_HMAC_SHA256     1
+#define LIBSSH2_HMAC_SHA512     1
+
+#define LIBSSH2_AES             1
+#define LIBSSH2_AES_CTR         1
+#define LIBSSH2_BLOWFISH        0
+#define LIBSSH2_RC4             1
+#define LIBSSH2_CAST            0
+#define LIBSSH2_3DES            1
+
+#define LIBSSH2_RSA             1
+#define LIBSSH2_DSA             0
+
+#define MD5_DIGEST_LENGTH       16
+#define SHA_DIGEST_LENGTH       20
+#define SHA256_DIGEST_LENGTH    32
+#define SHA512_DIGEST_LENGTH    64
+
+
+/*******************************************************************
+ *
+ * OS/400 QC3 crypto-library backend: global handles structures.
+ *
+ *******************************************************************/
+
+/* HMAC & private key algorithms support structure. */
+typedef struct _libssh2_os400qc3_crypto_ctx _libssh2_os400qc3_crypto_ctx;
+struct _libssh2_os400qc3_crypto_ctx {
+    Qc3_Format_ALGD0100_T           hash;           /* Hash algorithm. */
+    Qc3_Format_KEYD0100_T           key;            /* Key. */
+    _libssh2_os400qc3_crypto_ctx *  kek;            /* Key encryption. */
+};
+
+typedef struct {        /* Big number. */
+    unsigned char *         bignum;         /* Number bits, little-endian. */
+    unsigned int            length;         /* Length of bignum (# bytes). */
+}       _libssh2_bn;
+
+typedef struct {        /* Algorithm description. */
+    char *                  fmt;            /* Format of Qc3 structure. */
+    int                     algo;           /* Algorithm identifier. */
+    unsigned char           size;           /* Block length. */
+    unsigned char           mode;           /* Block mode. */
+    int                     keylen;         /* Key length. */
+}       _libssh2_os400qc3_cipher_t;
+
+typedef struct {        /* Diffie-Hellman context. */
+    char                    token[8];       /* Context token. */
+}       _libssh2_os400qc3_dh_ctx;
+
+/*******************************************************************
+ *
+ * OS/400 QC3 crypto-library backend: Define global types/codes.
+ *
+ *******************************************************************/
+
+#define libssh2_crypto_init()
+#define libssh2_crypto_exit()
+
+#define libssh2_sha1_ctx        Qc3_Format_ALGD0100_T
+#define libssh2_sha256_ctx      Qc3_Format_ALGD0100_T
+#define libssh2_md5_ctx         Qc3_Format_ALGD0100_T
+#define libssh2_hmac_ctx        _libssh2_os400qc3_crypto_ctx
+#define _libssh2_cipher_ctx     _libssh2_os400qc3_crypto_ctx
+
+#define libssh2_sha1_init(x)    libssh2_os400qc3_hash_init(x, Qc3_SHA1)
+#define libssh2_sha1_update(ctx, data, len)                                 \
+                                libssh2_os400qc3_hash_update(&(ctx), data, len)
+#define libssh2_sha1_final(ctx, out)                                        \
+                                libssh2_os400qc3_hash_final(&(ctx), out)
+#define libssh2_sha256_init(x)  libssh2_os400qc3_hash_init(x, Qc3_SHA256)
+#define libssh2_sha256_update(ctx, data, len)                               \
+                                libssh2_os400qc3_hash_update(&(ctx), data, len)
+#define libssh2_sha256_final(ctx, out)                                      \
+                                libssh2_os400qc3_hash_final(&(ctx), out)
+#define libssh2_sha256(message,  len, out)                                   \
+                                libssh2_os400qc3_hash(message, len, out,    \
+                                                      Qc3_SHA256)
+#define libssh2_md5_init(x)     libssh2_os400qc3_hash_init(x, Qc3_MD5)
+#define libssh2_md5_update(ctx, data, len)                                  \
+                                libssh2_os400qc3_hash_update(&(ctx), data, len)
+#define libssh2_md5_final(ctx, out)                                         \
+                                libssh2_os400qc3_hash_final(&(ctx), out)
+#define libssh2_hmac_ctx_init(ctx)                                          \
+                                memset((char *) &(ctx), 0,                  \
+                                       sizeof(libssh2_hmac_ctx))
+#define libssh2_hmac_md5_init(ctx, key, keylen)                         \
+    libssh2_os400qc3_hmac_init(ctx, Qc3_MD5,                            \
+                               MD5_DIGEST_LENGTH,                       \
+                               key, keylen)
+#define libssh2_hmac_sha1_init(ctx, key, keylen)                        \
+    libssh2_os400qc3_hmac_init(ctx, Qc3_SHA1,                           \
+                               SHA_DIGEST_LENGTH,                       \
+                               key, keylen)
+#define libssh2_hmac_sha256_init(ctx, key, keylen)                      \
+    libssh2_os400qc3_hmac_init(ctx, Qc3_SHA256,                         \
+                               SHA256_DIGEST_LENGTH,                    \
+                               key, keylen)
+#define libssh2_hmac_sha512_init(ctx, key, keylen)                      \
+    libssh2_os400qc3_hmac_init(ctx, Qc3_SHA512,                         \
+                               SHA512_DIGEST_LENGTH,                    \
+                               key, keylen)
+#define libssh2_hmac_update(ctx, data, datalen)                         \
+    libssh2_os400qc3_hmac_update(&(ctx),                                \
+                                 data, datalen)
+#define libssh2_hmac_final(ctx, data)           \
+    libssh2_os400qc3_hmac_final(&(ctx), data)
+#define libssh2_hmac_cleanup(ctx)               \
+    _libssh2_os400qc3_crypto_dtor(ctx)
+
+
+#define _libssh2_bn_ctx         int                 /* Not used. */
+
+#define _libssh2_bn_ctx_new()           0
+#define _libssh2_bn_ctx_free(bnctx)     ((void) 0)
+
+#define _libssh2_bn_init_from_bin() _libssh2_bn_init()
+#define _libssh2_bn_bytes(bn)   ((bn)->length)
+
+#define _libssh2_cipher_type(name)  _libssh2_os400qc3_cipher_t name
+#define _libssh2_cipher_aes128 {Qc3_Alg_Block_Cipher, Qc3_AES, 16,          \
+                                Qc3_CBC, 16}
+#define _libssh2_cipher_aes192 {Qc3_Alg_Block_Cipher, Qc3_AES, 24,          \
+                                Qc3_CBC, 24}
+#define _libssh2_cipher_aes256 {Qc3_Alg_Block_Cipher, Qc3_AES, 32,          \
+                                Qc3_CBC, 32}
+#define _libssh2_cipher_aes128ctr {Qc3_Alg_Block_Cipher, Qc3_AES, 16,       \
+                                   Qc3_CTR, 16}
+#define _libssh2_cipher_aes192ctr {Qc3_Alg_Block_Cipher, Qc3_AES, 24,       \
+                                   Qc3_CTR, 24}
+#define _libssh2_cipher_aes256ctr {Qc3_Alg_Block_Cipher, Qc3_AES, 32,       \
+                                   Qc3_CTR, 32}
+#define _libssh2_cipher_3des {Qc3_Alg_Block_Cipher, Qc3_TDES, 0,            \
+                              Qc3_CBC, 24}
+#define _libssh2_cipher_arcfour {Qc3_Alg_Stream_Cipher, Qc3_RC4, 0, 0, 16}
+
+#define _libssh2_cipher_dtor(ctx) _libssh2_os400qc3_crypto_dtor(ctx)
+
+#define libssh2_rsa_ctx         _libssh2_os400qc3_crypto_ctx
+#define _libssh2_rsa_free(ctx)  (_libssh2_os400qc3_crypto_dtor(ctx),        \
+                                 free((char *) ctx))
+#define libssh2_prepare_iovec(vec, len) memset((char *) (vec), 0,           \
+                                               (len) * sizeof(struct iovec))
+#define _libssh2_rsa_sha1_signv(session, sig, siglen, count, vector, ctx)   \
+            _libssh2_os400qc3_rsa_sha1_signv(session, sig, siglen,          \
+                                             count, vector, ctx)
+
+#define _libssh2_dh_ctx         _libssh2_os400qc3_dh_ctx
+#define libssh2_dh_init(dhctx)  _libssh2_os400qc3_dh_init(dhctx)
+#define libssh2_dh_key_pair(dhctx, public, g, p, group_order, bnctx)        \
+            _libssh2_os400qc3_dh_key_pair(dhctx, public, g, p, group_order)
+#define libssh2_dh_secret(dhctx, secret, f, p, bnctx)                       \
+            _libssh2_os400qc3_dh_secret(dhctx, secret, f, p)
+#define libssh2_dh_dtor(dhctx)  _libssh2_os400qc3_dh_dtor(dhctx)
+
+
+/*******************************************************************
+ *
+ * OS/400 QC3 crypto-library backend: Support procedure prototypes.
+ *
+ *******************************************************************/
+
+extern _libssh2_bn *    _libssh2_bn_init(void);
+extern void     _libssh2_bn_free(_libssh2_bn *bn);
+extern unsigned long    _libssh2_bn_bits(_libssh2_bn *bn);
+extern int      _libssh2_bn_from_bin(_libssh2_bn *bn, int len,
+                                     const unsigned char *v);
+extern int      _libssh2_bn_set_word(_libssh2_bn *bn, unsigned long val);
+extern int      _libssh2_bn_to_bin(_libssh2_bn *bn, unsigned char *val);
+extern void     _libssh2_random(unsigned char *buf, int len);
+extern void     _libssh2_os400qc3_crypto_dtor(_libssh2_os400qc3_crypto_ctx *x);
+extern int      libssh2_os400qc3_hash_init(Qc3_Format_ALGD0100_T *x,
+                                           unsigned int algo);
+extern void     libssh2_os400qc3_hash_update(Qc3_Format_ALGD0100_T *ctx,
+                                             unsigned char *data, int len);
+extern void     libssh2_os400qc3_hash_final(Qc3_Format_ALGD0100_T *ctx,
+                                            unsigned char *out);
+extern int      libssh2_os400qc3_hash(const unsigned char *message,
+                                      unsigned long len, unsigned char *out,
+                                      unsigned int algo);
+extern void     libssh2_os400qc3_hmac_init(_libssh2_os400qc3_crypto_ctx *x,
+                                           int algo, size_t minkeylen,
+                                           void *key, int keylen);
+extern void     libssh2_os400qc3_hmac_update(_libssh2_os400qc3_crypto_ctx *ctx,
+                                             const unsigned char *data,
+                                             int len);
+extern void     libssh2_os400qc3_hmac_final(_libssh2_os400qc3_crypto_ctx *ctx,
+                                            unsigned char *out);
+extern int      _libssh2_os400qc3_rsa_sha1_signv(LIBSSH2_SESSION *session,
+                                                 unsigned char **signature,
+                                                 size_t *signature_len,
+                                                 int veccount,
+                                                 const struct iovec vector[],
+                                                 libssh2_rsa_ctx *ctx);
+extern void     _libssh2_os400qc3_dh_init(_libssh2_dh_ctx *dhctx);
+extern int      _libssh2_os400qc3_dh_key_pair(_libssh2_dh_ctx *dhctx,
+                                              _libssh2_bn *public,
+                                              _libssh2_bn *g,
+                                              _libssh2_bn *p, int group_order);
+extern int      _libssh2_os400qc3_dh_secret(_libssh2_dh_ctx *dhctx,
+                                            _libssh2_bn *secret,
+                                            _libssh2_bn *f, _libssh2_bn *p);
+extern void     _libssh2_os400qc3_dh_dtor(_libssh2_dh_ctx *dhctx);
+
+#endif
+
+/* vim: set expandtab ts=4 sw=4: */

+ 1288 - 0
libssh2/libssh2/src/packet.c

@@ -0,0 +1,1288 @@
+/* Copyright (c) 2004-2007, Sara Golemon <sarag@libssh2.org>
+ * Copyright (c) 2005,2006 Mikhail Gusarov
+ * Copyright (c) 2009-2014 by Daniel Stenberg
+ * Copyright (c) 2010 Simon Josefsson
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms,
+ * with or without modification, are permitted provided
+ * that the following conditions are met:
+ *
+ *   Redistributions of source code must retain the above
+ *   copyright notice, this list of conditions and the
+ *   following disclaimer.
+ *
+ *   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.
+ *
+ *   Neither the name of the copyright holder nor the names
+ *   of any other contributors may be used to endorse or
+ *   promote products derived from this software without
+ *   specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+ * CONTRIBUTORS "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 COPYRIGHT OWNER OR
+ * CONTRIBUTORS 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 "libssh2_priv.h"
+#include <errno.h>
+#include <fcntl.h>
+
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
+#ifdef HAVE_SYS_TIME_H
+#include <sys/time.h>
+#endif
+
+#ifdef HAVE_INTTYPES_H
+#include <inttypes.h>
+#endif
+
+/* Needed for struct iovec on some platforms */
+#ifdef HAVE_SYS_UIO_H
+#include <sys/uio.h>
+#endif
+
+#include <sys/types.h>
+
+#include "transport.h"
+#include "channel.h"
+#include "packet.h"
+
+/*
+ * libssh2_packet_queue_listener
+ *
+ * Queue a connection request for a listener
+ */
+static inline int
+packet_queue_listener(LIBSSH2_SESSION * session, unsigned char *data,
+                      unsigned long datalen,
+                      packet_queue_listener_state_t *listen_state)
+{
+    /*
+     * Look for a matching listener
+     */
+    /* 17 = packet_type(1) + channel(4) + reason(4) + descr(4) + lang(4) */
+    unsigned long packet_len = 17 + (sizeof(FwdNotReq) - 1);
+    unsigned char *p;
+    LIBSSH2_LISTENER *listn = _libssh2_list_first(&session->listeners);
+    char failure_code = SSH_OPEN_ADMINISTRATIVELY_PROHIBITED;
+    int rc;
+
+    (void) datalen;
+
+    if(listen_state->state == libssh2_NB_state_idle) {
+        unsigned char *s = data + (sizeof("forwarded-tcpip") - 1) + 5;
+        listen_state->sender_channel = _libssh2_ntohu32(s);
+        s += 4;
+
+        listen_state->initial_window_size = _libssh2_ntohu32(s);
+        s += 4;
+        listen_state->packet_size = _libssh2_ntohu32(s);
+        s += 4;
+
+        listen_state->host_len = _libssh2_ntohu32(s);
+        s += 4;
+        listen_state->host = s;
+        s += listen_state->host_len;
+        listen_state->port = _libssh2_ntohu32(s);
+        s += 4;
+
+        listen_state->shost_len = _libssh2_ntohu32(s);
+        s += 4;
+        listen_state->shost = s;
+        s += listen_state->shost_len;
+        listen_state->sport = _libssh2_ntohu32(s);
+
+        _libssh2_debug(session, LIBSSH2_TRACE_CONN,
+                       "Remote received connection from %s:%ld to %s:%ld",
+                       listen_state->shost, listen_state->sport,
+                       listen_state->host, listen_state->port);
+
+        listen_state->state = libssh2_NB_state_allocated;
+    }
+
+    if(listen_state->state != libssh2_NB_state_sent) {
+        while(listn) {
+            if((listn->port == (int) listen_state->port) &&
+                (strlen(listn->host) == listen_state->host_len) &&
+                (memcmp (listn->host, listen_state->host,
+                         listen_state->host_len) == 0)) {
+                /* This is our listener */
+                LIBSSH2_CHANNEL *channel = NULL;
+                listen_state->channel = NULL;
+
+                if(listen_state->state == libssh2_NB_state_allocated) {
+                    if(listn->queue_maxsize &&
+                        (listn->queue_maxsize <= listn->queue_size)) {
+                        /* Queue is full */
+                        failure_code = SSH_OPEN_RESOURCE_SHORTAGE;
+                        _libssh2_debug(session, LIBSSH2_TRACE_CONN,
+                                       "Listener queue full, ignoring");
+                        listen_state->state = libssh2_NB_state_sent;
+                        break;
+                    }
+
+                    channel = LIBSSH2_CALLOC(session, sizeof(LIBSSH2_CHANNEL));
+                    if(!channel) {
+                        _libssh2_error(session, LIBSSH2_ERROR_ALLOC,
+                                       "Unable to allocate a channel for "
+                                       "new connection");
+                        failure_code = SSH_OPEN_RESOURCE_SHORTAGE;
+                        listen_state->state = libssh2_NB_state_sent;
+                        break;
+                    }
+                    listen_state->channel = channel;
+
+                    channel->session = session;
+                    channel->channel_type_len = sizeof("forwarded-tcpip") - 1;
+                    channel->channel_type = LIBSSH2_ALLOC(session,
+                                                          channel->
+                                                          channel_type_len +
+                                                          1);
+                    if(!channel->channel_type) {
+                        _libssh2_error(session, LIBSSH2_ERROR_ALLOC,
+                                       "Unable to allocate a channel for new"
+                                       " connection");
+                        LIBSSH2_FREE(session, channel);
+                        failure_code = SSH_OPEN_RESOURCE_SHORTAGE;
+                        listen_state->state = libssh2_NB_state_sent;
+                        break;
+                    }
+                    memcpy(channel->channel_type, "forwarded-tcpip",
+                           channel->channel_type_len + 1);
+
+                    channel->remote.id = listen_state->sender_channel;
+                    channel->remote.window_size_initial =
+                        LIBSSH2_CHANNEL_WINDOW_DEFAULT;
+                    channel->remote.window_size =
+                        LIBSSH2_CHANNEL_WINDOW_DEFAULT;
+                    channel->remote.packet_size =
+                        LIBSSH2_CHANNEL_PACKET_DEFAULT;
+
+                    channel->local.id = _libssh2_channel_nextid(session);
+                    channel->local.window_size_initial =
+                        listen_state->initial_window_size;
+                    channel->local.window_size =
+                        listen_state->initial_window_size;
+                    channel->local.packet_size = listen_state->packet_size;
+
+                    _libssh2_debug(session, LIBSSH2_TRACE_CONN,
+                                   "Connection queued: channel %lu/%lu "
+                                   "win %lu/%lu packet %lu/%lu",
+                                   channel->local.id, channel->remote.id,
+                                   channel->local.window_size,
+                                   channel->remote.window_size,
+                                   channel->local.packet_size,
+                                   channel->remote.packet_size);
+
+                    p = listen_state->packet;
+                    *(p++) = SSH_MSG_CHANNEL_OPEN_CONFIRMATION;
+                    _libssh2_store_u32(&p, channel->remote.id);
+                    _libssh2_store_u32(&p, channel->local.id);
+                    _libssh2_store_u32(&p,
+                                       channel->remote.window_size_initial);
+                    _libssh2_store_u32(&p, channel->remote.packet_size);
+
+                    listen_state->state = libssh2_NB_state_created;
+                }
+
+                if(listen_state->state == libssh2_NB_state_created) {
+                    rc = _libssh2_transport_send(session, listen_state->packet,
+                                                 17, NULL, 0);
+                    if(rc == LIBSSH2_ERROR_EAGAIN)
+                        return rc;
+                    else if(rc) {
+                        listen_state->state = libssh2_NB_state_idle;
+                        return _libssh2_error(session, rc,
+                                              "Unable to send channel "
+                                              "open confirmation");
+                    }
+
+                    /* Link the channel into the end of the queue list */
+                    if(listen_state->channel) {
+                        _libssh2_list_add(&listn->queue,
+                                          &listen_state->channel->node);
+                        listn->queue_size++;
+                    }
+
+                    listen_state->state = libssh2_NB_state_idle;
+                    return 0;
+                }
+            }
+
+            listn = _libssh2_list_next(&listn->node);
+        }
+
+        listen_state->state = libssh2_NB_state_sent;
+    }
+
+    /* We're not listening to you */
+    p = listen_state->packet;
+    *(p++) = SSH_MSG_CHANNEL_OPEN_FAILURE;
+    _libssh2_store_u32(&p, listen_state->sender_channel);
+    _libssh2_store_u32(&p, failure_code);
+    _libssh2_store_str(&p, FwdNotReq, sizeof(FwdNotReq) - 1);
+    _libssh2_htonu32(p, 0);
+
+    rc = _libssh2_transport_send(session, listen_state->packet,
+                                 packet_len, NULL, 0);
+    if(rc == LIBSSH2_ERROR_EAGAIN) {
+        return rc;
+    }
+    else if(rc) {
+        listen_state->state = libssh2_NB_state_idle;
+        return _libssh2_error(session, rc, "Unable to send open failure");
+
+    }
+    listen_state->state = libssh2_NB_state_idle;
+    return 0;
+}
+
+/*
+ * packet_x11_open
+ *
+ * Accept a forwarded X11 connection
+ */
+static inline int
+packet_x11_open(LIBSSH2_SESSION * session, unsigned char *data,
+                unsigned long datalen,
+                packet_x11_open_state_t *x11open_state)
+{
+    int failure_code = SSH_OPEN_CONNECT_FAILED;
+    /* 17 = packet_type(1) + channel(4) + reason(4) + descr(4) + lang(4) */
+    unsigned long packet_len = 17 + (sizeof(X11FwdUnAvil) - 1);
+    unsigned char *p;
+    LIBSSH2_CHANNEL *channel = x11open_state->channel;
+    int rc;
+
+    (void) datalen;
+
+    if(x11open_state->state == libssh2_NB_state_idle) {
+        unsigned char *s = data + (sizeof("x11") - 1) + 5;
+        x11open_state->sender_channel = _libssh2_ntohu32(s);
+        s += 4;
+        x11open_state->initial_window_size = _libssh2_ntohu32(s);
+        s += 4;
+        x11open_state->packet_size = _libssh2_ntohu32(s);
+        s += 4;
+        x11open_state->shost_len = _libssh2_ntohu32(s);
+        s += 4;
+        x11open_state->shost = s;
+        s += x11open_state->shost_len;
+        x11open_state->sport = _libssh2_ntohu32(s);
+
+        _libssh2_debug(session, LIBSSH2_TRACE_CONN,
+                       "X11 Connection Received from %s:%ld on channel %lu",
+                       x11open_state->shost, x11open_state->sport,
+                       x11open_state->sender_channel);
+
+        x11open_state->state = libssh2_NB_state_allocated;
+    }
+
+    if(session->x11) {
+        if(x11open_state->state == libssh2_NB_state_allocated) {
+            channel = LIBSSH2_CALLOC(session, sizeof(LIBSSH2_CHANNEL));
+            if(!channel) {
+                _libssh2_error(session, LIBSSH2_ERROR_ALLOC,
+                               "allocate a channel for new connection");
+                failure_code = SSH_OPEN_RESOURCE_SHORTAGE;
+                goto x11_exit;
+            }
+
+            channel->session = session;
+            channel->channel_type_len = sizeof("x11") - 1;
+            channel->channel_type = LIBSSH2_ALLOC(session,
+                                                  channel->channel_type_len +
+                                                  1);
+            if(!channel->channel_type) {
+                _libssh2_error(session, LIBSSH2_ERROR_ALLOC,
+                               "allocate a channel for new connection");
+                LIBSSH2_FREE(session, channel);
+                failure_code = SSH_OPEN_RESOURCE_SHORTAGE;
+                goto x11_exit;
+            }
+            memcpy(channel->channel_type, "x11",
+                   channel->channel_type_len + 1);
+
+            channel->remote.id = x11open_state->sender_channel;
+            channel->remote.window_size_initial =
+                LIBSSH2_CHANNEL_WINDOW_DEFAULT;
+            channel->remote.window_size = LIBSSH2_CHANNEL_WINDOW_DEFAULT;
+            channel->remote.packet_size = LIBSSH2_CHANNEL_PACKET_DEFAULT;
+
+            channel->local.id = _libssh2_channel_nextid(session);
+            channel->local.window_size_initial =
+                x11open_state->initial_window_size;
+            channel->local.window_size = x11open_state->initial_window_size;
+            channel->local.packet_size = x11open_state->packet_size;
+
+            _libssh2_debug(session, LIBSSH2_TRACE_CONN,
+                           "X11 Connection established: channel %lu/%lu "
+                           "win %lu/%lu packet %lu/%lu",
+                           channel->local.id, channel->remote.id,
+                           channel->local.window_size,
+                           channel->remote.window_size,
+                           channel->local.packet_size,
+                           channel->remote.packet_size);
+            p = x11open_state->packet;
+            *(p++) = SSH_MSG_CHANNEL_OPEN_CONFIRMATION;
+            _libssh2_store_u32(&p, channel->remote.id);
+            _libssh2_store_u32(&p, channel->local.id);
+            _libssh2_store_u32(&p, channel->remote.window_size_initial);
+            _libssh2_store_u32(&p, channel->remote.packet_size);
+
+            x11open_state->state = libssh2_NB_state_created;
+        }
+
+        if(x11open_state->state == libssh2_NB_state_created) {
+            rc = _libssh2_transport_send(session, x11open_state->packet, 17,
+                                         NULL, 0);
+            if(rc == LIBSSH2_ERROR_EAGAIN) {
+                return rc;
+            }
+            else if(rc) {
+                x11open_state->state = libssh2_NB_state_idle;
+                return _libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND,
+                                      "Unable to send channel open "
+                                      "confirmation");
+            }
+
+            /* Link the channel into the session */
+            _libssh2_list_add(&session->channels, &channel->node);
+
+            /*
+             * Pass control to the callback, they may turn right around and
+             * free the channel, or actually use it
+             */
+            LIBSSH2_X11_OPEN(channel, (char *)x11open_state->shost,
+                             x11open_state->sport);
+
+            x11open_state->state = libssh2_NB_state_idle;
+            return 0;
+        }
+    }
+    else
+        failure_code = SSH_OPEN_RESOURCE_SHORTAGE;
+    /* fall-trough */
+  x11_exit:
+    p = x11open_state->packet;
+    *(p++) = SSH_MSG_CHANNEL_OPEN_FAILURE;
+    _libssh2_store_u32(&p, x11open_state->sender_channel);
+    _libssh2_store_u32(&p, failure_code);
+    _libssh2_store_str(&p, X11FwdUnAvil, sizeof(X11FwdUnAvil) - 1);
+    _libssh2_htonu32(p, 0);
+
+    rc = _libssh2_transport_send(session, x11open_state->packet, packet_len,
+                                 NULL, 0);
+    if(rc == LIBSSH2_ERROR_EAGAIN) {
+        return rc;
+    }
+    else if(rc) {
+        x11open_state->state = libssh2_NB_state_idle;
+        return _libssh2_error(session, rc, "Unable to send open failure");
+    }
+    x11open_state->state = libssh2_NB_state_idle;
+    return 0;
+}
+
+/*
+ * _libssh2_packet_add
+ *
+ * Create a new packet and attach it to the brigade. Called from the transport
+ * layer when it has received a packet.
+ *
+ * The input pointer 'data' is pointing to allocated data that this function
+ * is asked to deal with so on failure OR success, it must be freed fine.
+ * The only exception is when the return code is LIBSSH2_ERROR_EAGAIN.
+ *
+ * This function will always be called with 'datalen' greater than zero.
+ */
+int
+_libssh2_packet_add(LIBSSH2_SESSION * session, unsigned char *data,
+                    size_t datalen, int macstate)
+{
+    int rc = 0;
+    char *message = NULL;
+    char *language = NULL;
+    size_t message_len = 0;
+    size_t language_len = 0;
+    LIBSSH2_CHANNEL *channelp = NULL;
+    size_t data_head = 0;
+    unsigned char msg = data[0];
+
+    switch(session->packAdd_state) {
+    case libssh2_NB_state_idle:
+        _libssh2_debug(session, LIBSSH2_TRACE_TRANS,
+                       "Packet type %d received, length=%d",
+                       (int) msg, (int) datalen);
+
+        if((macstate == LIBSSH2_MAC_INVALID) &&
+            (!session->macerror ||
+             LIBSSH2_MACERROR(session, (char *) data, datalen))) {
+            /* Bad MAC input, but no callback set or non-zero return from the
+               callback */
+
+            LIBSSH2_FREE(session, data);
+            return _libssh2_error(session, LIBSSH2_ERROR_INVALID_MAC,
+                                  "Invalid MAC received");
+        }
+        session->packAdd_state = libssh2_NB_state_allocated;
+        break;
+    case libssh2_NB_state_jump1:
+        goto libssh2_packet_add_jump_point1;
+    case libssh2_NB_state_jump2:
+        goto libssh2_packet_add_jump_point2;
+    case libssh2_NB_state_jump3:
+        goto libssh2_packet_add_jump_point3;
+    case libssh2_NB_state_jump4:
+        goto libssh2_packet_add_jump_point4;
+    case libssh2_NB_state_jump5:
+        goto libssh2_packet_add_jump_point5;
+    default: /* nothing to do */
+        break;
+    }
+
+    if(session->packAdd_state == libssh2_NB_state_allocated) {
+        /* A couple exceptions to the packet adding rule: */
+        switch(msg) {
+
+            /*
+              byte      SSH_MSG_DISCONNECT
+              uint32    reason code
+              string    description in ISO-10646 UTF-8 encoding [RFC3629]
+              string    language tag [RFC3066]
+            */
+
+        case SSH_MSG_DISCONNECT:
+            if(datalen >= 5) {
+                size_t reason = _libssh2_ntohu32(data + 1);
+
+                if(datalen >= 9) {
+                    message_len = _libssh2_ntohu32(data + 5);
+
+                    if(message_len < datalen-13) {
+                        /* 9 = packet_type(1) + reason(4) + message_len(4) */
+                        message = (char *) data + 9;
+
+                        language_len =
+                            _libssh2_ntohu32(data + 9 + message_len);
+                        language = (char *) data + 9 + message_len + 4;
+
+                        if(language_len > (datalen-13-message_len)) {
+                            /* bad input, clear info */
+                            language = message = NULL;
+                            language_len = message_len = 0;
+                        }
+                    }
+                    else
+                        /* bad size, clear it */
+                        message_len = 0;
+                }
+                if(session->ssh_msg_disconnect) {
+                    LIBSSH2_DISCONNECT(session, reason, message,
+                                       message_len, language, language_len);
+                }
+                _libssh2_debug(session, LIBSSH2_TRACE_TRANS,
+                               "Disconnect(%d): %s(%s)", reason,
+                               message, language);
+            }
+
+            LIBSSH2_FREE(session, data);
+            session->socket_state = LIBSSH2_SOCKET_DISCONNECTED;
+            session->packAdd_state = libssh2_NB_state_idle;
+            return _libssh2_error(session, LIBSSH2_ERROR_SOCKET_DISCONNECT,
+                                  "socket disconnect");
+            /*
+              byte      SSH_MSG_IGNORE
+              string    data
+            */
+
+        case SSH_MSG_IGNORE:
+            if(datalen >= 2) {
+                if(session->ssh_msg_ignore) {
+                    LIBSSH2_IGNORE(session, (char *) data + 1, datalen - 1);
+                }
+            }
+            else if(session->ssh_msg_ignore) {
+                LIBSSH2_IGNORE(session, "", 0);
+            }
+            LIBSSH2_FREE(session, data);
+            session->packAdd_state = libssh2_NB_state_idle;
+            return 0;
+
+            /*
+              byte      SSH_MSG_DEBUG
+              boolean   always_display
+              string    message in ISO-10646 UTF-8 encoding [RFC3629]
+              string    language tag [RFC3066]
+            */
+
+        case SSH_MSG_DEBUG:
+            if(datalen >= 2) {
+                int always_display = data[1];
+
+                if(datalen >= 6) {
+                    message_len = _libssh2_ntohu32(data + 2);
+
+                    if(message_len <= (datalen - 10)) {
+                        /* 6 = packet_type(1) + display(1) + message_len(4) */
+                        message = (char *) data + 6;
+                        language_len = _libssh2_ntohu32(data + 6 +
+                                                        message_len);
+
+                        if(language_len <= (datalen - 10 - message_len))
+                            language = (char *) data + 10 + message_len;
+                    }
+                }
+
+                if(session->ssh_msg_debug) {
+                    LIBSSH2_DEBUG(session, always_display, message,
+                                  message_len, language, language_len);
+                }
+            }
+            /*
+             * _libssh2_debug will actually truncate this for us so
+             * that it's not an inordinate about of data
+             */
+            _libssh2_debug(session, LIBSSH2_TRACE_TRANS,
+                           "Debug Packet: %s", message);
+            LIBSSH2_FREE(session, data);
+            session->packAdd_state = libssh2_NB_state_idle;
+            return 0;
+
+            /*
+              byte      SSH_MSG_GLOBAL_REQUEST
+              string    request name in US-ASCII only
+              boolean   want reply
+              ....      request-specific data follows
+            */
+
+        case SSH_MSG_GLOBAL_REQUEST:
+            if(datalen >= 5) {
+                uint32_t len = 0;
+                unsigned char want_reply = 0;
+                len = _libssh2_ntohu32(data + 1);
+                if(datalen >= (6 + len)) {
+                    want_reply = data[5 + len];
+                    _libssh2_debug(session,
+                                   LIBSSH2_TRACE_CONN,
+                                   "Received global request type %.*s (wr %X)",
+                                   len, data + 5, want_reply);
+                }
+
+
+                if(want_reply) {
+                    static const unsigned char packet =
+                        SSH_MSG_REQUEST_FAILURE;
+                  libssh2_packet_add_jump_point5:
+                    session->packAdd_state = libssh2_NB_state_jump5;
+                    rc = _libssh2_transport_send(session, &packet, 1, NULL, 0);
+                    if(rc == LIBSSH2_ERROR_EAGAIN)
+                        return rc;
+                }
+            }
+            LIBSSH2_FREE(session, data);
+            session->packAdd_state = libssh2_NB_state_idle;
+            return 0;
+
+            /*
+              byte      SSH_MSG_CHANNEL_EXTENDED_DATA
+              uint32    recipient channel
+              uint32    data_type_code
+              string    data
+            */
+
+        case SSH_MSG_CHANNEL_EXTENDED_DATA:
+            /* streamid(4) */
+            data_head += 4;
+
+            /* fall-through */
+
+            /*
+              byte      SSH_MSG_CHANNEL_DATA
+              uint32    recipient channel
+              string    data
+            */
+
+        case SSH_MSG_CHANNEL_DATA:
+            /* packet_type(1) + channelno(4) + datalen(4) */
+            data_head += 9;
+
+            if(datalen >= data_head)
+                channelp =
+                    _libssh2_channel_locate(session,
+                                            _libssh2_ntohu32(data + 1));
+
+            if(!channelp) {
+                _libssh2_error(session, LIBSSH2_ERROR_CHANNEL_UNKNOWN,
+                               "Packet received for unknown channel");
+                LIBSSH2_FREE(session, data);
+                session->packAdd_state = libssh2_NB_state_idle;
+                return 0;
+            }
+#ifdef LIBSSH2DEBUG
+            {
+                uint32_t stream_id = 0;
+                if(msg == SSH_MSG_CHANNEL_EXTENDED_DATA)
+                    stream_id = _libssh2_ntohu32(data + 5);
+
+                _libssh2_debug(session, LIBSSH2_TRACE_CONN,
+                               "%d bytes packet_add() for %lu/%lu/%lu",
+                               (int) (datalen - data_head),
+                               channelp->local.id,
+                               channelp->remote.id,
+                               stream_id);
+            }
+#endif
+            if((channelp->remote.extended_data_ignore_mode ==
+                 LIBSSH2_CHANNEL_EXTENDED_DATA_IGNORE) &&
+                (msg == SSH_MSG_CHANNEL_EXTENDED_DATA)) {
+                /* Pretend we didn't receive this */
+                LIBSSH2_FREE(session, data);
+
+                _libssh2_debug(session, LIBSSH2_TRACE_CONN,
+                               "Ignoring extended data and refunding %d bytes",
+                               (int) (datalen - 13));
+                if(channelp->read_avail + datalen - data_head >=
+                    channelp->remote.window_size)
+                    datalen = channelp->remote.window_size -
+                        channelp->read_avail + data_head;
+
+                channelp->remote.window_size -= datalen - data_head;
+                _libssh2_debug(session, LIBSSH2_TRACE_CONN,
+                               "shrinking window size by %lu bytes to %lu, "
+                               "read_avail %lu",
+                               datalen - data_head,
+                               channelp->remote.window_size,
+                               channelp->read_avail);
+
+                session->packAdd_channelp = channelp;
+
+                /* Adjust the window based on the block we just freed */
+              libssh2_packet_add_jump_point1:
+                session->packAdd_state = libssh2_NB_state_jump1;
+                rc = _libssh2_channel_receive_window_adjust(session->
+                                                            packAdd_channelp,
+                                                            datalen - 13,
+                                                            1, NULL);
+                if(rc == LIBSSH2_ERROR_EAGAIN)
+                    return rc;
+
+                session->packAdd_state = libssh2_NB_state_idle;
+                return 0;
+            }
+
+            /*
+             * REMEMBER! remote means remote as source of data,
+             * NOT remote window!
+             */
+            if(channelp->remote.packet_size < (datalen - data_head)) {
+                /*
+                 * Spec says we MAY ignore bytes sent beyond
+                 * packet_size
+                 */
+                _libssh2_error(session,
+                               LIBSSH2_ERROR_CHANNEL_PACKET_EXCEEDED,
+                               "Packet contains more data than we offered"
+                               " to receive, truncating");
+                datalen = channelp->remote.packet_size + data_head;
+            }
+            if(channelp->remote.window_size <= channelp->read_avail) {
+                /*
+                 * Spec says we MAY ignore bytes sent beyond
+                 * window_size
+                 */
+                _libssh2_error(session,
+                               LIBSSH2_ERROR_CHANNEL_WINDOW_EXCEEDED,
+                               "The current receive window is full,"
+                               " data ignored");
+                LIBSSH2_FREE(session, data);
+                session->packAdd_state = libssh2_NB_state_idle;
+                return 0;
+            }
+            /* Reset EOF status */
+            channelp->remote.eof = 0;
+
+            if(channelp->read_avail + datalen - data_head >
+                channelp->remote.window_size) {
+                _libssh2_error(session,
+                               LIBSSH2_ERROR_CHANNEL_WINDOW_EXCEEDED,
+                               "Remote sent more data than current "
+                               "window allows, truncating");
+                datalen = channelp->remote.window_size -
+                    channelp->read_avail + data_head;
+            }
+
+            /* Update the read_avail counter. The window size will be
+             * updated once the data is actually read from the queue
+             * from an upper layer */
+            channelp->read_avail += datalen - data_head;
+
+            _libssh2_debug(session, LIBSSH2_TRACE_CONN,
+                           "increasing read_avail by %lu bytes to %lu/%lu",
+                           (long)(datalen - data_head),
+                           (long)channelp->read_avail,
+                           (long)channelp->remote.window_size);
+
+            break;
+
+            /*
+              byte      SSH_MSG_CHANNEL_EOF
+              uint32    recipient channel
+            */
+
+        case SSH_MSG_CHANNEL_EOF:
+            if(datalen >= 5)
+                channelp =
+                    _libssh2_channel_locate(session,
+                                            _libssh2_ntohu32(data + 1));
+            if(!channelp)
+                /* We may have freed already, just quietly ignore this... */
+                ;
+            else {
+                _libssh2_debug(session,
+                               LIBSSH2_TRACE_CONN,
+                               "EOF received for channel %lu/%lu",
+                               channelp->local.id,
+                               channelp->remote.id);
+                channelp->remote.eof = 1;
+            }
+            LIBSSH2_FREE(session, data);
+            session->packAdd_state = libssh2_NB_state_idle;
+            return 0;
+
+            /*
+              byte      SSH_MSG_CHANNEL_REQUEST
+              uint32    recipient channel
+              string    request type in US-ASCII characters only
+              boolean   want reply
+              ....      type-specific data follows
+            */
+
+        case SSH_MSG_CHANNEL_REQUEST:
+            if(datalen >= 9) {
+                uint32_t channel = _libssh2_ntohu32(data + 1);
+                uint32_t len = _libssh2_ntohu32(data + 5);
+                unsigned char want_reply = 1;
+
+                if((len + 9) < datalen)
+                    want_reply = data[len + 9];
+
+                _libssh2_debug(session,
+                               LIBSSH2_TRACE_CONN,
+                               "Channel %d received request type %.*s (wr %X)",
+                               channel, len, data + 9, want_reply);
+
+                if(len == sizeof("exit-status") - 1
+                    && (sizeof("exit-status") - 1 + 9) <= datalen
+                    && !memcmp("exit-status", data + 9,
+                               sizeof("exit-status") - 1)) {
+
+                    /* we've got "exit-status" packet. Set the session value */
+                    if(datalen >= 20)
+                        channelp =
+                            _libssh2_channel_locate(session, channel);
+
+                    if(channelp && (sizeof("exit-status") + 13) <= datalen) {
+                        channelp->exit_status =
+                            _libssh2_ntohu32(data + 9 + sizeof("exit-status"));
+                        _libssh2_debug(session, LIBSSH2_TRACE_CONN,
+                                       "Exit status %lu received for "
+                                       "channel %lu/%lu",
+                                       channelp->exit_status,
+                                       channelp->local.id,
+                                       channelp->remote.id);
+                    }
+
+                }
+                else if(len == sizeof("exit-signal") - 1
+                         && (sizeof("exit-signal") - 1 + 9) <= datalen
+                         && !memcmp("exit-signal", data + 9,
+                                    sizeof("exit-signal") - 1)) {
+                    /* command terminated due to signal */
+                    if(datalen >= 20)
+                        channelp = _libssh2_channel_locate(session, channel);
+
+                    if(channelp && (sizeof("exit-signal") + 13) <= datalen) {
+                        /* set signal name (without SIG prefix) */
+                        uint32_t namelen =
+                            _libssh2_ntohu32(data + 9 + sizeof("exit-signal"));
+
+                        if(namelen <= UINT_MAX - 1) {
+                            channelp->exit_signal =
+                                LIBSSH2_ALLOC(session, namelen + 1);
+                        }
+                        else {
+                            channelp->exit_signal = NULL;
+                        }
+
+                        if(!channelp->exit_signal)
+                            rc = _libssh2_error(session, LIBSSH2_ERROR_ALLOC,
+                                                "memory for signal name");
+                        else if((sizeof("exit-signal") + 13 + namelen <=
+                                 datalen)) {
+                            memcpy(channelp->exit_signal,
+                                   data + 13 + sizeof("exit-signal"), namelen);
+                            channelp->exit_signal[namelen] = '\0';
+                            /* TODO: save error message and language tag */
+                            _libssh2_debug(session, LIBSSH2_TRACE_CONN,
+                                           "Exit signal %s received for "
+                                           "channel %lu/%lu",
+                                           channelp->exit_signal,
+                                           channelp->local.id,
+                                           channelp->remote.id);
+                        }
+                    }
+                }
+
+
+                if(want_reply) {
+                    unsigned char packet[5];
+                  libssh2_packet_add_jump_point4:
+                    session->packAdd_state = libssh2_NB_state_jump4;
+                    packet[0] = SSH_MSG_CHANNEL_FAILURE;
+                    memcpy(&packet[1], data + 1, 4);
+                    rc = _libssh2_transport_send(session, packet, 5, NULL, 0);
+                    if(rc == LIBSSH2_ERROR_EAGAIN)
+                        return rc;
+                }
+            }
+            LIBSSH2_FREE(session, data);
+            session->packAdd_state = libssh2_NB_state_idle;
+            return rc;
+
+            /*
+              byte      SSH_MSG_CHANNEL_CLOSE
+              uint32    recipient channel
+            */
+
+        case SSH_MSG_CHANNEL_CLOSE:
+            if(datalen >= 5)
+                channelp =
+                    _libssh2_channel_locate(session,
+                                            _libssh2_ntohu32(data + 1));
+            if(!channelp) {
+                /* We may have freed already, just quietly ignore this... */
+                LIBSSH2_FREE(session, data);
+                session->packAdd_state = libssh2_NB_state_idle;
+                return 0;
+            }
+            _libssh2_debug(session, LIBSSH2_TRACE_CONN,
+                           "Close received for channel %lu/%lu",
+                           channelp->local.id,
+                           channelp->remote.id);
+
+            channelp->remote.close = 1;
+            channelp->remote.eof = 1;
+
+            LIBSSH2_FREE(session, data);
+            session->packAdd_state = libssh2_NB_state_idle;
+            return 0;
+
+            /*
+              byte      SSH_MSG_CHANNEL_OPEN
+              string    "session"
+              uint32    sender channel
+              uint32    initial window size
+              uint32    maximum packet size
+            */
+
+        case SSH_MSG_CHANNEL_OPEN:
+            if(datalen < 17)
+                ;
+            else if((datalen >= (sizeof("forwarded-tcpip") + 4)) &&
+                     ((sizeof("forwarded-tcpip") - 1) ==
+                      _libssh2_ntohu32(data + 1))
+                     &&
+                     (memcmp(data + 5, "forwarded-tcpip",
+                             sizeof("forwarded-tcpip") - 1) == 0)) {
+
+                /* init the state struct */
+                memset(&session->packAdd_Qlstn_state, 0,
+                       sizeof(session->packAdd_Qlstn_state));
+
+              libssh2_packet_add_jump_point2:
+                session->packAdd_state = libssh2_NB_state_jump2;
+                rc = packet_queue_listener(session, data, datalen,
+                                           &session->packAdd_Qlstn_state);
+            }
+            else if((datalen >= (sizeof("x11") + 4)) &&
+                     ((sizeof("x11") - 1) == _libssh2_ntohu32(data + 1)) &&
+                     (memcmp(data + 5, "x11", sizeof("x11") - 1) == 0)) {
+
+                /* init the state struct */
+                memset(&session->packAdd_x11open_state, 0,
+                       sizeof(session->packAdd_x11open_state));
+
+              libssh2_packet_add_jump_point3:
+                session->packAdd_state = libssh2_NB_state_jump3;
+                rc = packet_x11_open(session, data, datalen,
+                                     &session->packAdd_x11open_state);
+            }
+            if(rc == LIBSSH2_ERROR_EAGAIN)
+                return rc;
+
+            LIBSSH2_FREE(session, data);
+            session->packAdd_state = libssh2_NB_state_idle;
+            return rc;
+
+            /*
+              byte      SSH_MSG_CHANNEL_WINDOW_ADJUST
+              uint32    recipient channel
+              uint32    bytes to add
+            */
+        case SSH_MSG_CHANNEL_WINDOW_ADJUST:
+            if(datalen < 9)
+                ;
+            else {
+                uint32_t bytestoadd = _libssh2_ntohu32(data + 5);
+                channelp =
+                    _libssh2_channel_locate(session,
+                                            _libssh2_ntohu32(data + 1));
+                if(channelp) {
+                    channelp->local.window_size += bytestoadd;
+
+                    _libssh2_debug(session, LIBSSH2_TRACE_CONN,
+                                   "Window adjust for channel %lu/%lu, "
+                                   "adding %lu bytes, new window_size=%lu",
+                                   channelp->local.id,
+                                   channelp->remote.id,
+                                   bytestoadd,
+                                   channelp->local.window_size);
+                }
+            }
+            LIBSSH2_FREE(session, data);
+            session->packAdd_state = libssh2_NB_state_idle;
+            return 0;
+        default:
+            break;
+        }
+
+        session->packAdd_state = libssh2_NB_state_sent;
+    }
+
+    if(session->packAdd_state == libssh2_NB_state_sent) {
+        LIBSSH2_PACKET *packetp =
+            LIBSSH2_ALLOC(session, sizeof(LIBSSH2_PACKET));
+        if(!packetp) {
+            _libssh2_debug(session, LIBSSH2_ERROR_ALLOC,
+                           "memory for packet");
+            LIBSSH2_FREE(session, data);
+            session->packAdd_state = libssh2_NB_state_idle;
+            return LIBSSH2_ERROR_ALLOC;
+        }
+        packetp->data = data;
+        packetp->data_len = datalen;
+        packetp->data_head = data_head;
+
+        _libssh2_list_add(&session->packets, &packetp->node);
+
+        session->packAdd_state = libssh2_NB_state_sent1;
+    }
+
+    if((msg == SSH_MSG_KEXINIT &&
+         !(session->state & LIBSSH2_STATE_EXCHANGING_KEYS)) ||
+        (session->packAdd_state == libssh2_NB_state_sent2)) {
+        if(session->packAdd_state == libssh2_NB_state_sent1) {
+            /*
+             * Remote wants new keys
+             * Well, it's already in the brigade,
+             * let's just call back into ourselves
+             */
+            _libssh2_debug(session, LIBSSH2_TRACE_TRANS, "Renegotiating Keys");
+
+            session->packAdd_state = libssh2_NB_state_sent2;
+        }
+
+        /*
+         * The KEXINIT message has been added to the queue.  The packAdd and
+         * readPack states need to be reset because _libssh2_kex_exchange
+         * (eventually) calls upon _libssh2_transport_read to read the rest of
+         * the key exchange conversation.
+         */
+        session->readPack_state = libssh2_NB_state_idle;
+        session->packet.total_num = 0;
+        session->packAdd_state = libssh2_NB_state_idle;
+        session->fullpacket_state = libssh2_NB_state_idle;
+
+        memset(&session->startup_key_state, 0, sizeof(key_exchange_state_t));
+
+        /*
+         * If there was a key reexchange failure, let's just hope we didn't
+         * send NEWKEYS yet, otherwise remote will drop us like a rock
+         */
+        rc = _libssh2_kex_exchange(session, 1, &session->startup_key_state);
+        if(rc == LIBSSH2_ERROR_EAGAIN)
+            return rc;
+    }
+
+    session->packAdd_state = libssh2_NB_state_idle;
+    return 0;
+}
+
+/*
+ * _libssh2_packet_ask
+ *
+ * Scan the brigade for a matching packet type, optionally poll the socket for
+ * a packet first
+ */
+int
+_libssh2_packet_ask(LIBSSH2_SESSION * session, unsigned char packet_type,
+                    unsigned char **data, size_t *data_len,
+                    int match_ofs, const unsigned char *match_buf,
+                    size_t match_len)
+{
+    LIBSSH2_PACKET *packet = _libssh2_list_first(&session->packets);
+
+    _libssh2_debug(session, LIBSSH2_TRACE_TRANS,
+                   "Looking for packet of type: %d", (int) packet_type);
+
+    while(packet) {
+        if(packet->data[0] == packet_type
+            && (packet->data_len >= (match_ofs + match_len))
+            && (!match_buf ||
+                (memcmp(packet->data + match_ofs, match_buf,
+                        match_len) == 0))) {
+            *data = packet->data;
+            *data_len = packet->data_len;
+
+            /* unlink struct from session->packets */
+            _libssh2_list_remove(&packet->node);
+
+            LIBSSH2_FREE(session, packet);
+
+            return 0;
+        }
+        packet = _libssh2_list_next(&packet->node);
+    }
+    return -1;
+}
+
+/*
+ * libssh2_packet_askv
+ *
+ * Scan for any of a list of packet types in the brigade, optionally poll the
+ * socket for a packet first
+ */
+int
+_libssh2_packet_askv(LIBSSH2_SESSION * session,
+                     const unsigned char *packet_types,
+                     unsigned char **data, size_t *data_len,
+                     int match_ofs,
+                     const unsigned char *match_buf,
+                     size_t match_len)
+{
+    int i, packet_types_len = strlen((char *) packet_types);
+
+    for(i = 0; i < packet_types_len; i++) {
+        if(0 == _libssh2_packet_ask(session, packet_types[i], data,
+                                     data_len, match_ofs,
+                                     match_buf, match_len)) {
+            return 0;
+        }
+    }
+
+    return -1;
+}
+
+/*
+ * _libssh2_packet_require
+ *
+ * Loops _libssh2_transport_read() until the packet requested is available
+ * SSH_DISCONNECT or a SOCKET_DISCONNECTED will cause a bailout
+ *
+ * Returns negative on error
+ * Returns 0 when it has taken care of the requested packet.
+ */
+int
+_libssh2_packet_require(LIBSSH2_SESSION * session, unsigned char packet_type,
+                        unsigned char **data, size_t *data_len,
+                        int match_ofs,
+                        const unsigned char *match_buf,
+                        size_t match_len,
+                        packet_require_state_t *state)
+{
+    if(state->start == 0) {
+        if(_libssh2_packet_ask(session, packet_type, data, data_len,
+                                match_ofs, match_buf,
+                                match_len) == 0) {
+            /* A packet was available in the packet brigade */
+            return 0;
+        }
+
+        state->start = time(NULL);
+    }
+
+    while(session->socket_state == LIBSSH2_SOCKET_CONNECTED) {
+        int ret = _libssh2_transport_read(session);
+        if(ret == LIBSSH2_ERROR_EAGAIN)
+            return ret;
+        else if(ret < 0) {
+            state->start = 0;
+            /* an error which is not just because of blocking */
+            return ret;
+        }
+        else if(ret == packet_type) {
+            /* Be lazy, let packet_ask pull it out of the brigade */
+            ret = _libssh2_packet_ask(session, packet_type, data, data_len,
+                                      match_ofs, match_buf, match_len);
+            state->start = 0;
+            return ret;
+        }
+        else if(ret == 0) {
+            /* nothing available, wait until data arrives or we time out */
+            long left = LIBSSH2_READ_TIMEOUT - (long)(time(NULL) -
+                                                      state->start);
+
+            if(left <= 0) {
+                state->start = 0;
+                return LIBSSH2_ERROR_TIMEOUT;
+            }
+            return -1; /* no packet available yet */
+        }
+    }
+
+    /* Only reached if the socket died */
+    return LIBSSH2_ERROR_SOCKET_DISCONNECT;
+}
+
+/*
+ * _libssh2_packet_burn
+ *
+ * Loops _libssh2_transport_read() until any packet is available and promptly
+ * discards it.
+ * Used during KEX exchange to discard badly guessed KEX_INIT packets
+ */
+int
+_libssh2_packet_burn(LIBSSH2_SESSION * session,
+                     libssh2_nonblocking_states * state)
+{
+    unsigned char *data;
+    size_t data_len;
+    unsigned char i, all_packets[255];
+    int ret;
+
+    if(*state == libssh2_NB_state_idle) {
+        for(i = 1; i < 255; i++) {
+            all_packets[i - 1] = i;
+        }
+        all_packets[254] = 0;
+
+        if(_libssh2_packet_askv(session, all_packets, &data, &data_len, 0,
+                                 NULL, 0) == 0) {
+            i = data[0];
+            /* A packet was available in the packet brigade, burn it */
+            LIBSSH2_FREE(session, data);
+            return i;
+        }
+
+        _libssh2_debug(session, LIBSSH2_TRACE_TRANS,
+                       "Blocking until packet becomes available to burn");
+        *state = libssh2_NB_state_created;
+    }
+
+    while(session->socket_state == LIBSSH2_SOCKET_CONNECTED) {
+        ret = _libssh2_transport_read(session);
+        if(ret == LIBSSH2_ERROR_EAGAIN) {
+            return ret;
+        }
+        else if(ret < 0) {
+            *state = libssh2_NB_state_idle;
+            return ret;
+        }
+        else if(ret == 0) {
+            /* FIXME: this might busyloop */
+            continue;
+        }
+
+        /* Be lazy, let packet_ask pull it out of the brigade */
+        if(0 ==
+            _libssh2_packet_ask(session, (unsigned char)ret,
+                                         &data, &data_len, 0, NULL, 0)) {
+            /* Smoke 'em if you got 'em */
+            LIBSSH2_FREE(session, data);
+            *state = libssh2_NB_state_idle;
+            return ret;
+        }
+    }
+
+    /* Only reached if the socket died */
+    return LIBSSH2_ERROR_SOCKET_DISCONNECT;
+}
+
+/*
+ * _libssh2_packet_requirev
+ *
+ * Loops _libssh2_transport_read() until one of a list of packet types
+ * requested is available. SSH_DISCONNECT or a SOCKET_DISCONNECTED will cause
+ * a bailout. packet_types is a null terminated list of packet_type numbers
+ */
+
+int
+_libssh2_packet_requirev(LIBSSH2_SESSION *session,
+                         const unsigned char *packet_types,
+                         unsigned char **data, size_t *data_len,
+                         int match_ofs,
+                         const unsigned char *match_buf, size_t match_len,
+                         packet_requirev_state_t * state)
+{
+    if(_libssh2_packet_askv(session, packet_types, data, data_len, match_ofs,
+                             match_buf, match_len) == 0) {
+        /* One of the packets listed was available in the packet brigade */
+        state->start = 0;
+        return 0;
+    }
+
+    if(state->start == 0) {
+        state->start = time(NULL);
+    }
+
+    while(session->socket_state != LIBSSH2_SOCKET_DISCONNECTED) {
+        int ret = _libssh2_transport_read(session);
+        if((ret < 0) && (ret != LIBSSH2_ERROR_EAGAIN)) {
+            state->start = 0;
+            return ret;
+        }
+        if(ret <= 0) {
+            long left = LIBSSH2_READ_TIMEOUT -
+                (long)(time(NULL) - state->start);
+
+            if(left <= 0) {
+                state->start = 0;
+                return LIBSSH2_ERROR_TIMEOUT;
+            }
+            else if(ret == LIBSSH2_ERROR_EAGAIN) {
+                return ret;
+            }
+        }
+
+        if(strchr((char *) packet_types, ret)) {
+            /* Be lazy, let packet_ask pull it out of the brigade */
+            return _libssh2_packet_askv(session, packet_types, data,
+                                        data_len, match_ofs, match_buf,
+                                        match_len);
+        }
+    }
+
+    /* Only reached if the socket died */
+    state->start = 0;
+    return LIBSSH2_ERROR_SOCKET_DISCONNECT;
+}
+

+ 76 - 0
libssh2/libssh2/src/packet.h

@@ -0,0 +1,76 @@
+#ifndef LIBSSH2_PACKET_H
+#define LIBSSH2_PACKET_H
+/*
+ * Copyright (C) 2010 by Daniel Stenberg
+ * Author: Daniel Stenberg <daniel@haxx.se>
+ *
+ * Redistribution and use in source and binary forms,
+ * with or without modification, are permitted provided
+ * that the following conditions are met:
+ *
+ *   Redistributions of source code must retain the above
+ *   copyright notice, this list of conditions and the
+ *   following disclaimer.
+ *
+ *   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.
+ *
+ *   Neither the name of the copyright holder nor the names
+ *   of any other contributors may be used to endorse or
+ *   promote products derived from this software without
+ *   specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+ * CONTRIBUTORS "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 COPYRIGHT OWNER OR
+ * CONTRIBUTORS 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.
+ *
+ */
+
+int _libssh2_packet_read(LIBSSH2_SESSION * session);
+
+int _libssh2_packet_ask(LIBSSH2_SESSION * session, unsigned char packet_type,
+                        unsigned char **data, size_t *data_len,
+                        int match_ofs,
+                        const unsigned char *match_buf,
+                        size_t match_len);
+
+int _libssh2_packet_askv(LIBSSH2_SESSION * session,
+                         const unsigned char *packet_types,
+                         unsigned char **data, size_t *data_len,
+                         int match_ofs,
+                         const unsigned char *match_buf,
+                         size_t match_len);
+int _libssh2_packet_require(LIBSSH2_SESSION * session,
+                            unsigned char packet_type, unsigned char **data,
+                            size_t *data_len, int match_ofs,
+                            const unsigned char *match_buf,
+                            size_t match_len,
+                            packet_require_state_t * state);
+int _libssh2_packet_requirev(LIBSSH2_SESSION *session,
+                             const unsigned char *packet_types,
+                             unsigned char **data, size_t *data_len,
+                             int match_ofs,
+                             const unsigned char *match_buf,
+                             size_t match_len,
+                             packet_requirev_state_t * state);
+int _libssh2_packet_burn(LIBSSH2_SESSION * session,
+                         libssh2_nonblocking_states * state);
+int _libssh2_packet_write(LIBSSH2_SESSION * session, unsigned char *data,
+                          unsigned long data_len);
+int _libssh2_packet_add(LIBSSH2_SESSION * session, unsigned char *data,
+                        size_t datalen, int macstate);
+
+#endif /* LIBSSH2_PACKET_H */

+ 902 - 0
libssh2/libssh2/src/pem.c

@@ -0,0 +1,902 @@
+/* Copyright (C) 2007 The Written Word, Inc.
+ * Copyright (C) 2008, Simon Josefsson
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms,
+ * with or without modification, are permitted provided
+ * that the following conditions are met:
+ *
+ *   Redistributions of source code must retain the above
+ *   copyright notice, this list of conditions and the
+ *   following disclaimer.
+ *
+ *   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.
+ *
+ *   Neither the name of the copyright holder nor the names
+ *   of any other contributors may be used to endorse or
+ *   promote products derived from this software without
+ *   specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+ * CONTRIBUTORS "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 COPYRIGHT OWNER OR
+ * CONTRIBUTORS 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 "libssh2_priv.h"
+
+static int
+readline(char *line, int line_size, FILE * fp)
+{
+    size_t len;
+
+    if(!line) {
+        return -1;
+    }
+    if(!fgets(line, line_size, fp)) {
+        return -1;
+    }
+
+    if(*line) {
+        len = strlen(line);
+        if(len > 0 && line[len - 1] == '\n') {
+            line[len - 1] = '\0';
+        }
+    }
+
+    if(*line) {
+        len = strlen(line);
+        if(len > 0 && line[len - 1] == '\r') {
+            line[len - 1] = '\0';
+        }
+    }
+
+    return 0;
+}
+
+static int
+readline_memory(char *line, size_t line_size,
+                const char *filedata, size_t filedata_len,
+                size_t *filedata_offset)
+{
+    size_t off, len;
+
+    off = *filedata_offset;
+
+    for(len = 0; off + len < filedata_len && len < line_size - 1; len++) {
+        if(filedata[off + len] == '\n' ||
+            filedata[off + len] == '\r') {
+                break;
+        }
+    }
+
+    if(len) {
+        memcpy(line, filedata + off, len);
+        *filedata_offset += len;
+    }
+
+    line[len] = '\0';
+    *filedata_offset += 1;
+
+    return 0;
+}
+
+#define LINE_SIZE 128
+
+static const char *crypt_annotation = "Proc-Type: 4,ENCRYPTED";
+
+static unsigned char hex_decode(char digit)
+{
+    return (digit >= 'A') ? 0xA + (digit - 'A') : (digit - '0');
+}
+
+int
+_libssh2_pem_parse(LIBSSH2_SESSION * session,
+                   const char *headerbegin,
+                   const char *headerend,
+                   const unsigned char *passphrase,
+                   FILE * fp, unsigned char **data, unsigned int *datalen)
+{
+    char line[LINE_SIZE];
+    unsigned char iv[LINE_SIZE];
+    char *b64data = NULL;
+    unsigned int b64datalen = 0;
+    int ret;
+    const LIBSSH2_CRYPT_METHOD *method = NULL;
+
+    do {
+        *line = '\0';
+
+        if(readline(line, LINE_SIZE, fp)) {
+            return -1;
+        }
+    }
+    while(strcmp(line, headerbegin) != 0);
+
+    if(readline(line, LINE_SIZE, fp)) {
+        return -1;
+    }
+
+    if(passphrase &&
+            memcmp(line, crypt_annotation, strlen(crypt_annotation)) == 0) {
+        const LIBSSH2_CRYPT_METHOD **all_methods, *cur_method;
+        int i;
+
+        if(readline(line, LINE_SIZE, fp)) {
+            ret = -1;
+            goto out;
+        }
+
+        all_methods = libssh2_crypt_methods();
+        while((cur_method = *all_methods++)) {
+            if(*cur_method->pem_annotation &&
+                    memcmp(line, cur_method->pem_annotation,
+                           strlen(cur_method->pem_annotation)) == 0) {
+                method = cur_method;
+                memcpy(iv, line + strlen(method->pem_annotation) + 1,
+                       2*method->iv_len);
+            }
+        }
+
+        /* None of the available crypt methods were able to decrypt the key */
+        if(method == NULL)
+            return -1;
+
+        /* Decode IV from hex */
+        for(i = 0; i < method->iv_len; ++i) {
+            iv[i]  = hex_decode(iv[2*i]) << 4;
+            iv[i] |= hex_decode(iv[2*i + 1]);
+        }
+
+        /* skip to the next line */
+        if(readline(line, LINE_SIZE, fp)) {
+            ret = -1;
+            goto out;
+        }
+    }
+
+    do {
+        if(*line) {
+            char *tmp;
+            size_t linelen;
+
+            linelen = strlen(line);
+            tmp = LIBSSH2_REALLOC(session, b64data, b64datalen + linelen);
+            if(!tmp) {
+                ret = -1;
+                goto out;
+            }
+            memcpy(tmp + b64datalen, line, linelen);
+            b64data = tmp;
+            b64datalen += linelen;
+        }
+
+        *line = '\0';
+
+        if(readline(line, LINE_SIZE, fp)) {
+            ret = -1;
+            goto out;
+        }
+    } while(strcmp(line, headerend) != 0);
+
+    if(!b64data) {
+        return -1;
+    }
+
+    if(libssh2_base64_decode(session, (char **) data, datalen,
+                              b64data, b64datalen)) {
+        ret = -1;
+        goto out;
+    }
+
+    if(method) {
+        /* Set up decryption */
+        int free_iv = 0, free_secret = 0, len_decrypted = 0, padding = 0;
+        int blocksize = method->blocksize;
+        void *abstract;
+        unsigned char secret[2*MD5_DIGEST_LENGTH];
+        libssh2_md5_ctx fingerprint_ctx;
+
+        /* Perform key derivation (PBKDF1/MD5) */
+        if(!libssh2_md5_init(&fingerprint_ctx)) {
+            ret = -1;
+            goto out;
+        }
+        libssh2_md5_update(fingerprint_ctx, passphrase,
+                           strlen((char *)passphrase));
+        libssh2_md5_update(fingerprint_ctx, iv, 8);
+        libssh2_md5_final(fingerprint_ctx, secret);
+        if(method->secret_len > MD5_DIGEST_LENGTH) {
+            if(!libssh2_md5_init(&fingerprint_ctx)) {
+                ret = -1;
+                goto out;
+            }
+            libssh2_md5_update(fingerprint_ctx, secret, MD5_DIGEST_LENGTH);
+            libssh2_md5_update(fingerprint_ctx, passphrase,
+                               strlen((char *)passphrase));
+            libssh2_md5_update(fingerprint_ctx, iv, 8);
+            libssh2_md5_final(fingerprint_ctx, secret + MD5_DIGEST_LENGTH);
+        }
+
+        /* Initialize the decryption */
+        if(method->init(session, method, iv, &free_iv, secret,
+                         &free_secret, 0, &abstract)) {
+            _libssh2_explicit_zero((char *)secret, sizeof(secret));
+            LIBSSH2_FREE(session, data);
+            ret = -1;
+            goto out;
+        }
+
+        if(free_secret) {
+            _libssh2_explicit_zero((char *)secret, sizeof(secret));
+        }
+
+        /* Do the actual decryption */
+        if((*datalen % blocksize) != 0) {
+            _libssh2_explicit_zero((char *)secret, sizeof(secret));
+            method->dtor(session, &abstract);
+            _libssh2_explicit_zero(*data, *datalen);
+            LIBSSH2_FREE(session, *data);
+            ret = -1;
+            goto out;
+        }
+
+        while(len_decrypted <= (int)*datalen - blocksize) {
+            if(method->crypt(session, *data + len_decrypted, blocksize,
+                              &abstract)) {
+                ret = LIBSSH2_ERROR_DECRYPT;
+                _libssh2_explicit_zero((char *)secret, sizeof(secret));
+                method->dtor(session, &abstract);
+                _libssh2_explicit_zero(*data, *datalen);
+                LIBSSH2_FREE(session, *data);
+                goto out;
+            }
+
+            len_decrypted += blocksize;
+        }
+
+        /* Account for padding */
+        padding = (*data)[*datalen - 1];
+        memset(&(*data)[*datalen-padding], 0, padding);
+        *datalen -= padding;
+
+        /* Clean up */
+        _libssh2_explicit_zero((char *)secret, sizeof(secret));
+        method->dtor(session, &abstract);
+    }
+
+    ret = 0;
+  out:
+    if(b64data) {
+        _libssh2_explicit_zero(b64data, b64datalen);
+        LIBSSH2_FREE(session, b64data);
+    }
+    return ret;
+}
+
+int
+_libssh2_pem_parse_memory(LIBSSH2_SESSION * session,
+                          const char *headerbegin,
+                          const char *headerend,
+                          const char *filedata, size_t filedata_len,
+                          unsigned char **data, unsigned int *datalen)
+{
+    char line[LINE_SIZE];
+    char *b64data = NULL;
+    unsigned int b64datalen = 0;
+    size_t off = 0;
+    int ret;
+
+    do {
+        *line = '\0';
+
+        if(readline_memory(line, LINE_SIZE, filedata, filedata_len, &off)) {
+            return -1;
+        }
+    }
+    while(strcmp(line, headerbegin) != 0);
+
+    *line = '\0';
+
+    do {
+        if(*line) {
+            char *tmp;
+            size_t linelen;
+
+            linelen = strlen(line);
+            tmp = LIBSSH2_REALLOC(session, b64data, b64datalen + linelen);
+            if(!tmp) {
+                ret = -1;
+                goto out;
+            }
+            memcpy(tmp + b64datalen, line, linelen);
+            b64data = tmp;
+            b64datalen += linelen;
+        }
+
+        *line = '\0';
+
+        if(readline_memory(line, LINE_SIZE, filedata, filedata_len, &off)) {
+            ret = -1;
+            goto out;
+        }
+    } while(strcmp(line, headerend) != 0);
+
+    if(!b64data) {
+        return -1;
+    }
+
+    if(libssh2_base64_decode(session, (char **) data, datalen,
+                              b64data, b64datalen)) {
+        ret = -1;
+        goto out;
+    }
+
+    ret = 0;
+  out:
+    if(b64data) {
+        _libssh2_explicit_zero(b64data, b64datalen);
+        LIBSSH2_FREE(session, b64data);
+    }
+    return ret;
+}
+
+/* OpenSSH formatted keys */
+#define AUTH_MAGIC "openssh-key-v1"
+#define OPENSSH_HEADER_BEGIN "-----BEGIN OPENSSH PRIVATE KEY-----"
+#define OPENSSH_HEADER_END "-----END OPENSSH PRIVATE KEY-----"
+
+static int
+_libssh2_openssh_pem_parse_data(LIBSSH2_SESSION * session,
+                                const unsigned char *passphrase,
+                                const char *b64data, size_t b64datalen,
+                                struct string_buf **decrypted_buf)
+{
+    const LIBSSH2_CRYPT_METHOD *method = NULL;
+    struct string_buf decoded, decrypted, kdf_buf;
+    unsigned char *ciphername = NULL;
+    unsigned char *kdfname = NULL;
+    unsigned char *kdf = NULL;
+    unsigned char *buf = NULL;
+    unsigned char *salt = NULL;
+    uint32_t nkeys, check1, check2;
+    uint32_t rounds = 0;
+    unsigned char *key = NULL;
+    unsigned char *key_part = NULL;
+    unsigned char *iv_part = NULL;
+    unsigned char *f = NULL;
+    unsigned int f_len = 0;
+    int ret = 0, keylen = 0, ivlen = 0, total_len = 0;
+    size_t kdf_len = 0, tmp_len = 0, salt_len = 0;
+
+    if(decrypted_buf)
+        *decrypted_buf = NULL;
+
+    /* decode file */
+    if(libssh2_base64_decode(session, (char **)&f, &f_len,
+                             b64data, b64datalen)) {
+       ret = -1;
+       goto out;
+    }
+
+    /* Parse the file */
+    decoded.data = (unsigned char *)f;
+    decoded.dataptr = (unsigned char *)f;
+    decoded.len = f_len;
+
+    if(decoded.len < strlen(AUTH_MAGIC)) {
+        ret = _libssh2_error(session, LIBSSH2_ERROR_PROTO, "key too short");
+        goto out;
+    }
+
+    if(strncmp((char *) decoded.dataptr, AUTH_MAGIC,
+               strlen(AUTH_MAGIC)) != 0) {
+        ret = _libssh2_error(session, LIBSSH2_ERROR_PROTO,
+                             "key auth magic mismatch");
+        goto out;
+    }
+
+    decoded.dataptr += strlen(AUTH_MAGIC) + 1;
+
+    if(_libssh2_get_string(&decoded, &ciphername, &tmp_len) ||
+       tmp_len == 0) {
+        ret = _libssh2_error(session, LIBSSH2_ERROR_PROTO,
+                             "ciphername is missing");
+        goto out;
+    }
+
+    if(_libssh2_get_string(&decoded, &kdfname, &tmp_len) ||
+       tmp_len == 0) {
+        ret = _libssh2_error(session, LIBSSH2_ERROR_PROTO,
+                       "kdfname is missing");
+        goto out;
+    }
+
+    if(_libssh2_get_string(&decoded, &kdf, &kdf_len)) {
+        ret = _libssh2_error(session, LIBSSH2_ERROR_PROTO,
+                             "kdf is missing");
+        goto out;
+    }
+    else {
+        kdf_buf.data = kdf;
+        kdf_buf.dataptr = kdf;
+        kdf_buf.len = kdf_len;
+    }
+
+    if((passphrase == NULL || strlen((const char *)passphrase) == 0) &&
+        strcmp((const char *)ciphername, "none") != 0) {
+        /* passphrase required */
+        ret = LIBSSH2_ERROR_KEYFILE_AUTH_FAILED;
+        goto out;
+    }
+
+    if(strcmp((const char *)kdfname, "none") != 0 &&
+       strcmp((const char *)kdfname, "bcrypt") != 0) {
+        ret = _libssh2_error(session, LIBSSH2_ERROR_PROTO,
+                             "unknown cipher");
+        goto out;
+    }
+
+    if(!strcmp((const char *)kdfname, "none") &&
+       strcmp((const char *)ciphername, "none") != 0) {
+        ret =_libssh2_error(session, LIBSSH2_ERROR_PROTO,
+                            "invalid format");
+        goto out;
+    }
+
+    if(_libssh2_get_u32(&decoded, &nkeys) != 0 || nkeys != 1) {
+        ret = _libssh2_error(session, LIBSSH2_ERROR_PROTO,
+                             "Multiple keys are unsupported");
+        goto out;
+    }
+
+    /* unencrypted public key */
+
+    if(_libssh2_get_string(&decoded, &buf, &tmp_len) || tmp_len == 0) {
+        ret = _libssh2_error(session, LIBSSH2_ERROR_PROTO,
+                             "Invalid private key; "
+                             "expect embedded public key");
+        goto out;
+    }
+
+    if(_libssh2_get_string(&decoded, &buf, &tmp_len) || tmp_len == 0) {
+        ret = _libssh2_error(session, LIBSSH2_ERROR_PROTO,
+                       "Private key data not found");
+        goto out;
+    }
+
+    /* decode encrypted private key */
+    decrypted.data = decrypted.dataptr = buf;
+    decrypted.len = tmp_len;
+
+    if(ciphername && strcmp((const char *)ciphername, "none") != 0) {
+        const LIBSSH2_CRYPT_METHOD **all_methods, *cur_method;
+
+        all_methods = libssh2_crypt_methods();
+        while((cur_method = *all_methods++)) {
+            if(*cur_method->name &&
+                memcmp(ciphername, cur_method->name,
+                       strlen(cur_method->name)) == 0) {
+                    method = cur_method;
+                }
+        }
+
+        /* None of the available crypt methods were able to decrypt the key */
+
+        if(method == NULL) {
+            ret = _libssh2_error(session, LIBSSH2_ERROR_PROTO,
+                                "No supported cipher found");
+            goto out;
+        }
+    }
+
+    if(method) {
+        int free_iv = 0, free_secret = 0, len_decrypted = 0;
+        int blocksize;
+        void *abstract = NULL;
+
+        keylen = method->secret_len;
+        ivlen = method->iv_len;
+        total_len = keylen + ivlen;
+
+        key = LIBSSH2_CALLOC(session, total_len);
+        if(key == NULL) {
+            ret = _libssh2_error(session, LIBSSH2_ERROR_PROTO,
+                           "Could not alloc key");
+            goto out;
+        }
+
+        if(strcmp((const char *)kdfname, "bcrypt") == 0 &&
+           passphrase != NULL) {
+            if((_libssh2_get_string(&kdf_buf, &salt, &salt_len)) ||
+                (_libssh2_get_u32(&kdf_buf, &rounds) != 0) ) {
+                ret = _libssh2_error(session, LIBSSH2_ERROR_PROTO,
+                                     "kdf contains unexpected values");
+                LIBSSH2_FREE(session, key);
+                goto out;
+            }
+
+            if(_libssh2_bcrypt_pbkdf((const char *)passphrase,
+                                     strlen((const char *)passphrase),
+                                     salt, salt_len, key,
+                                     keylen + ivlen, rounds) < 0) {
+                ret = _libssh2_error(session, LIBSSH2_ERROR_DECRYPT,
+                                     "invalid format");
+                LIBSSH2_FREE(session, key);
+                goto out;
+            }
+        }
+        else {
+            ret = _libssh2_error(session, LIBSSH2_ERROR_KEYFILE_AUTH_FAILED,
+                                            "bcrypted without passphrase");
+            LIBSSH2_FREE(session, key);
+            goto out;
+        }
+
+        /* Set up decryption */
+        blocksize = method->blocksize;
+
+        key_part = LIBSSH2_CALLOC(session, keylen);
+        if(key_part == NULL) {
+            ret = _libssh2_error(session, LIBSSH2_ERROR_PROTO,
+                                 "Could not alloc key part");
+            goto out;
+        }
+
+        iv_part = LIBSSH2_CALLOC(session, ivlen);
+        if(iv_part == NULL) {
+            ret = _libssh2_error(session, LIBSSH2_ERROR_PROTO,
+                                 "Could not alloc iv part");
+            goto out;
+        }
+
+        memcpy(key_part, key, keylen);
+        memcpy(iv_part, key + keylen, ivlen);
+
+        /* Initialize the decryption */
+        if(method->init(session, method, iv_part, &free_iv, key_part,
+                         &free_secret, 0, &abstract)) {
+            ret = LIBSSH2_ERROR_DECRYPT;
+            goto out;
+        }
+
+        /* Do the actual decryption */
+        if((decrypted.len % blocksize) != 0) {
+            method->dtor(session, &abstract);
+            ret = LIBSSH2_ERROR_DECRYPT;
+            goto out;
+        }
+
+        while((size_t)len_decrypted <= decrypted.len - blocksize) {
+            if(method->crypt(session, decrypted.data + len_decrypted,
+                             blocksize,
+                             &abstract)) {
+                ret = LIBSSH2_ERROR_DECRYPT;
+                method->dtor(session, &abstract);
+                goto out;
+            }
+
+            len_decrypted += blocksize;
+        }
+
+        /* No padding */
+
+        method->dtor(session, &abstract);
+    }
+
+    /* Check random bytes match */
+
+    if(_libssh2_get_u32(&decrypted, &check1) != 0 ||
+       _libssh2_get_u32(&decrypted, &check2) != 0 ||
+       check1 != check2) {
+       _libssh2_error(session, LIBSSH2_ERROR_PROTO,
+                      "Private key unpack failed (correct password?)");
+       ret = LIBSSH2_ERROR_KEYFILE_AUTH_FAILED;
+       goto out;
+    }
+
+    if(decrypted_buf != NULL) {
+        /* copy data to out-going buffer */
+        struct string_buf *out_buf = _libssh2_string_buf_new(session);
+        if(!out_buf) {
+            ret = _libssh2_error(session, LIBSSH2_ERROR_ALLOC,
+                                 "Unable to allocate memory for "
+                                 "decrypted struct");
+            goto out;
+        }
+
+        out_buf->data = LIBSSH2_CALLOC(session, decrypted.len);
+        if(out_buf->data == NULL) {
+            ret = _libssh2_error(session, LIBSSH2_ERROR_ALLOC,
+                                 "Unable to allocate memory for "
+                                 "decrypted struct");
+            _libssh2_string_buf_free(session, out_buf);
+            goto out;
+        }
+        memcpy(out_buf->data, decrypted.data, decrypted.len);
+        out_buf->dataptr = out_buf->data +
+            (decrypted.dataptr - decrypted.data);
+        out_buf->len = decrypted.len;
+
+        *decrypted_buf = out_buf;
+    }
+
+out:
+
+    /* Clean up */
+    if(key) {
+        _libssh2_explicit_zero(key, total_len);
+        LIBSSH2_FREE(session, key);
+    }
+    if(key_part) {
+        _libssh2_explicit_zero(key_part, keylen);
+        LIBSSH2_FREE(session, key_part);
+    }
+    if(iv_part) {
+        _libssh2_explicit_zero(iv_part, ivlen);
+        LIBSSH2_FREE(session, iv_part);
+    }
+    if(f) {
+        _libssh2_explicit_zero(f, f_len);
+        LIBSSH2_FREE(session, f);
+    }
+
+    return ret;
+}
+
+int
+_libssh2_openssh_pem_parse(LIBSSH2_SESSION * session,
+                           const unsigned char *passphrase,
+                           FILE * fp, struct string_buf **decrypted_buf)
+{
+    char line[LINE_SIZE];
+    char *b64data = NULL;
+    unsigned int b64datalen = 0;
+    int ret = 0;
+
+    /* read file */
+
+    do {
+        *line = '\0';
+
+        if(readline(line, LINE_SIZE, fp)) {
+            return -1;
+        }
+    }
+    while(strcmp(line, OPENSSH_HEADER_BEGIN) != 0);
+
+    if(readline(line, LINE_SIZE, fp)) {
+        return -1;
+    }
+
+    do {
+        if(*line) {
+            char *tmp;
+            size_t linelen;
+
+            linelen = strlen(line);
+            tmp = LIBSSH2_REALLOC(session, b64data, b64datalen + linelen);
+            if(!tmp) {
+                ret = -1;
+                goto out;
+            }
+            memcpy(tmp + b64datalen, line, linelen);
+            b64data = tmp;
+            b64datalen += linelen;
+        }
+
+        *line = '\0';
+
+        if(readline(line, LINE_SIZE, fp)) {
+            ret = -1;
+            goto out;
+        }
+    } while(strcmp(line, OPENSSH_HEADER_END) != 0);
+
+    if(!b64data) {
+        return -1;
+    }
+
+    ret = _libssh2_openssh_pem_parse_data(session,
+                                          passphrase,
+                                          (const char *)b64data,
+                                          (size_t)b64datalen,
+                                          decrypted_buf);
+
+    if(b64data) {
+        _libssh2_explicit_zero(b64data, b64datalen);
+        LIBSSH2_FREE(session, b64data);
+    }
+
+out:
+
+    return ret;
+}
+
+int
+_libssh2_openssh_pem_parse_memory(LIBSSH2_SESSION * session,
+                                  const unsigned char *passphrase,
+                                  const char *filedata, size_t filedata_len,
+                                  struct string_buf **decrypted_buf)
+{
+    char line[LINE_SIZE];
+    char *b64data = NULL;
+    unsigned int b64datalen = 0;
+    size_t off = 0;
+    int ret;
+
+    if(filedata == NULL || filedata_len <= 0) {
+        return -1;
+    }
+
+    do {
+
+        *line = '\0';
+
+        if(off >= filedata_len) {
+            return -1;
+        }
+
+        if(readline_memory(line, LINE_SIZE, filedata, filedata_len, &off)) {
+            return -1;
+        }
+    }
+    while(strcmp(line, OPENSSH_HEADER_BEGIN) != 0);
+
+    *line = '\0';
+
+    do {
+        if (*line) {
+            char *tmp;
+            size_t linelen;
+
+            linelen = strlen(line);
+            tmp = LIBSSH2_REALLOC(session, b64data, b64datalen + linelen);
+            if(!tmp) {
+                ret = -1;
+                goto out;
+            }
+            memcpy(tmp + b64datalen, line, linelen);
+            b64data = tmp;
+            b64datalen += linelen;
+        }
+
+        *line = '\0';
+
+        if(off >= filedata_len) {
+            ret = -1;
+            goto out;
+        }
+
+        if(readline_memory(line, LINE_SIZE, filedata, filedata_len, &off)) {
+            ret = -1;
+            goto out;
+        }
+    } while(strcmp(line, OPENSSH_HEADER_END) != 0);
+
+    if(!b64data) {
+        return -1;
+    }
+
+    ret = _libssh2_openssh_pem_parse_data(session, passphrase, b64data,
+                                          b64datalen, decrypted_buf);
+
+out:
+    if(b64data) {
+        _libssh2_explicit_zero(b64data, b64datalen);
+        LIBSSH2_FREE(session, b64data);
+    }
+    return ret;
+
+}
+
+static int
+read_asn1_length(const unsigned char *data,
+                 unsigned int datalen, unsigned int *len)
+{
+    unsigned int lenlen;
+    int nextpos;
+
+    if(datalen < 1) {
+        return -1;
+    }
+    *len = data[0];
+
+    if(*len >= 0x80) {
+        lenlen = *len & 0x7F;
+        *len = data[1];
+        if(1 + lenlen > datalen) {
+            return -1;
+        }
+        if(lenlen > 1) {
+            *len <<= 8;
+            *len |= data[2];
+        }
+    }
+    else {
+        lenlen = 0;
+    }
+
+    nextpos = 1 + lenlen;
+    if(lenlen > 2 || 1 + lenlen + *len > datalen) {
+        return -1;
+    }
+
+    return nextpos;
+}
+
+int
+_libssh2_pem_decode_sequence(unsigned char **data, unsigned int *datalen)
+{
+    unsigned int len;
+    int lenlen;
+
+    if(*datalen < 1) {
+        return -1;
+    }
+
+    if((*data)[0] != '\x30') {
+        return -1;
+    }
+
+    (*data)++;
+    (*datalen)--;
+
+    lenlen = read_asn1_length(*data, *datalen, &len);
+    if(lenlen < 0 || lenlen + len != *datalen) {
+        return -1;
+    }
+
+    *data += lenlen;
+    *datalen -= lenlen;
+
+    return 0;
+}
+
+int
+_libssh2_pem_decode_integer(unsigned char **data, unsigned int *datalen,
+                            unsigned char **i, unsigned int *ilen)
+{
+    unsigned int len;
+    int lenlen;
+
+    if(*datalen < 1) {
+        return -1;
+    }
+
+    if((*data)[0] != '\x02') {
+        return -1;
+    }
+
+    (*data)++;
+    (*datalen)--;
+
+    lenlen = read_asn1_length(*data, *datalen, &len);
+    if(lenlen < 0 || lenlen + len > *datalen) {
+        return -1;
+    }
+
+    *data += lenlen;
+    *datalen -= lenlen;
+
+    *i = *data;
+    *ilen = len;
+
+    *data += len;
+    *datalen -= len;
+
+    return 0;
+}

+ 1278 - 0
libssh2/libssh2/src/publickey.c

@@ -0,0 +1,1278 @@
+/* Copyright (c) 2004-2007, Sara Golemon <sarag@libssh2.org>
+ * Copyright (c) 2010-2014 by Daniel Stenberg
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms,
+ * with or without modification, are permitted provided
+ * that the following conditions are met:
+ *
+ *   Redistributions of source code must retain the above
+ *   copyright notice, this list of conditions and the
+ *   following disclaimer.
+ *
+ *   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.
+ *
+ *   Neither the name of the copyright holder nor the names
+ *   of any other contributors may be used to endorse or
+ *   promote products derived from this software without
+ *   specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+ * CONTRIBUTORS "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 COPYRIGHT OWNER OR
+ * CONTRIBUTORS 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 "libssh2_priv.h"
+#include "libssh2_publickey.h"
+#include "channel.h"
+#include "session.h"
+
+#define LIBSSH2_PUBLICKEY_VERSION               2
+
+/* Numericised response codes -- Not IETF, just local representation */
+#define LIBSSH2_PUBLICKEY_RESPONSE_STATUS       0
+#define LIBSSH2_PUBLICKEY_RESPONSE_VERSION      1
+#define LIBSSH2_PUBLICKEY_RESPONSE_PUBLICKEY    2
+
+typedef struct _LIBSSH2_PUBLICKEY_CODE_LIST
+{
+    int code;
+    const char *name;
+    int name_len;
+} LIBSSH2_PUBLICKEY_CODE_LIST;
+
+static const LIBSSH2_PUBLICKEY_CODE_LIST publickey_response_codes[] =
+{
+    {LIBSSH2_PUBLICKEY_RESPONSE_STATUS, "status", sizeof("status") - 1},
+    {LIBSSH2_PUBLICKEY_RESPONSE_VERSION, "version", sizeof("version") - 1},
+    {LIBSSH2_PUBLICKEY_RESPONSE_PUBLICKEY, "publickey",
+     sizeof("publickey") - 1},
+    {0, NULL, 0}
+};
+
+/* PUBLICKEY status codes -- IETF defined */
+#define LIBSSH2_PUBLICKEY_SUCCESS               0
+#define LIBSSH2_PUBLICKEY_ACCESS_DENIED         1
+#define LIBSSH2_PUBLICKEY_STORAGE_EXCEEDED      2
+#define LIBSSH2_PUBLICKEY_VERSION_NOT_SUPPORTED 3
+#define LIBSSH2_PUBLICKEY_KEY_NOT_FOUND         4
+#define LIBSSH2_PUBLICKEY_KEY_NOT_SUPPORTED     5
+#define LIBSSH2_PUBLICKEY_KEY_ALREADY_PRESENT   6
+#define LIBSSH2_PUBLICKEY_GENERAL_FAILURE       7
+#define LIBSSH2_PUBLICKEY_REQUEST_NOT_SUPPORTED 8
+
+#define LIBSSH2_PUBLICKEY_STATUS_CODE_MAX       8
+
+static const LIBSSH2_PUBLICKEY_CODE_LIST publickey_status_codes[] = {
+    {LIBSSH2_PUBLICKEY_SUCCESS, "success", sizeof("success") - 1},
+    {LIBSSH2_PUBLICKEY_ACCESS_DENIED, "access denied",
+     sizeof("access denied") - 1},
+    {LIBSSH2_PUBLICKEY_STORAGE_EXCEEDED, "storage exceeded",
+     sizeof("storage exceeded") - 1},
+    {LIBSSH2_PUBLICKEY_VERSION_NOT_SUPPORTED, "version not supported",
+     sizeof("version not supported") - 1},
+    {LIBSSH2_PUBLICKEY_KEY_NOT_FOUND, "key not found",
+     sizeof("key not found") - 1},
+    {LIBSSH2_PUBLICKEY_KEY_NOT_SUPPORTED, "key not supported",
+     sizeof("key not supported") - 1},
+    {LIBSSH2_PUBLICKEY_KEY_ALREADY_PRESENT, "key already present",
+     sizeof("key already present") - 1},
+    {LIBSSH2_PUBLICKEY_GENERAL_FAILURE, "general failure",
+     sizeof("general failure") - 1},
+    {LIBSSH2_PUBLICKEY_REQUEST_NOT_SUPPORTED, "request not supported",
+     sizeof("request not supported") - 1},
+    {0, NULL, 0}
+};
+
+/*
+ * publickey_status_error
+ *
+ * Format an error message from a status code
+ */
+static void
+publickey_status_error(const LIBSSH2_PUBLICKEY *pkey,
+                       LIBSSH2_SESSION *session, int status)
+{
+    const char *msg;
+
+    /* GENERAL_FAILURE got remapped between version 1 and 2 */
+    if(status == 6 && pkey && pkey->version == 1) {
+        status = 7;
+    }
+
+    if(status < 0 || status > LIBSSH2_PUBLICKEY_STATUS_CODE_MAX) {
+        msg = "unknown";
+    }
+    else {
+        msg = publickey_status_codes[status].name;
+    }
+
+    _libssh2_error(session, LIBSSH2_ERROR_PUBLICKEY_PROTOCOL, msg);
+}
+
+/*
+ * publickey_packet_receive
+ *
+ * Read a packet from the subsystem
+ */
+static int
+publickey_packet_receive(LIBSSH2_PUBLICKEY * pkey,
+                         unsigned char **data, size_t *data_len)
+{
+    LIBSSH2_CHANNEL *channel = pkey->channel;
+    LIBSSH2_SESSION *session = channel->session;
+    unsigned char buffer[4];
+    int rc;
+    *data = NULL; /* default to nothing returned */
+    *data_len = 0;
+
+    if(pkey->receive_state == libssh2_NB_state_idle) {
+        rc = _libssh2_channel_read(channel, 0, (char *) buffer, 4);
+        if(rc == LIBSSH2_ERROR_EAGAIN) {
+            return rc;
+        }
+        else if(rc != 4) {
+            return _libssh2_error(session, LIBSSH2_ERROR_PUBLICKEY_PROTOCOL,
+                                  "Invalid response from publickey subsystem");
+        }
+
+        pkey->receive_packet_len = _libssh2_ntohu32(buffer);
+        pkey->receive_packet =
+            LIBSSH2_ALLOC(session, pkey->receive_packet_len);
+        if(!pkey->receive_packet) {
+            return _libssh2_error(session, LIBSSH2_ERROR_ALLOC,
+                                  "Unable to allocate publickey response "
+                                  "buffer");
+        }
+
+        pkey->receive_state = libssh2_NB_state_sent;
+    }
+
+    if(pkey->receive_state == libssh2_NB_state_sent) {
+        rc = _libssh2_channel_read(channel, 0, (char *) pkey->receive_packet,
+                                   pkey->receive_packet_len);
+        if(rc == LIBSSH2_ERROR_EAGAIN) {
+            return rc;
+        }
+        else if(rc != (int)pkey->receive_packet_len) {
+            LIBSSH2_FREE(session, pkey->receive_packet);
+            pkey->receive_packet = NULL;
+            pkey->receive_state = libssh2_NB_state_idle;
+            return _libssh2_error(session, LIBSSH2_ERROR_SOCKET_TIMEOUT,
+                                  "Timeout waiting for publickey subsystem "
+                                  "response packet");
+        }
+
+        *data = pkey->receive_packet;
+        *data_len = pkey->receive_packet_len;
+    }
+
+    pkey->receive_state = libssh2_NB_state_idle;
+
+    return 0;
+}
+
+/* publickey_response_id
+ *
+ * Translate a string response name to a numeric code
+ * Data will be incremented by 4 + response_len on success only
+ */
+static int
+publickey_response_id(unsigned char **pdata, size_t data_len)
+{
+    size_t response_len;
+    unsigned char *data = *pdata;
+    const LIBSSH2_PUBLICKEY_CODE_LIST *codes = publickey_response_codes;
+
+    if(data_len < 4) {
+        /* Malformed response */
+        return -1;
+    }
+    response_len = _libssh2_ntohu32(data);
+    data += 4;
+    data_len -= 4;
+    if(data_len < response_len) {
+        /* Malformed response */
+        return -1;
+    }
+
+    while(codes->name) {
+        if((unsigned long)codes->name_len == response_len &&
+            strncmp(codes->name, (char *) data, response_len) == 0) {
+            *pdata = data + response_len;
+            return codes->code;
+        }
+        codes++;
+    }
+
+    return -1;
+}
+
+/* publickey_response_success
+ *
+ * Generic helper routine to wait for success response and nothing else
+ */
+static int
+publickey_response_success(LIBSSH2_PUBLICKEY * pkey)
+{
+    LIBSSH2_SESSION *session = pkey->channel->session;
+    unsigned char *data, *s;
+    size_t data_len;
+    int response;
+
+    while(1) {
+        int rc = publickey_packet_receive(pkey, &data, &data_len);
+        if(rc == LIBSSH2_ERROR_EAGAIN) {
+            return rc;
+        }
+        else if(rc) {
+            return _libssh2_error(session, LIBSSH2_ERROR_SOCKET_TIMEOUT,
+                                  "Timeout waiting for response from "
+                                  "publickey subsystem");
+        }
+
+        if(data_len < 4) {
+            return _libssh2_error(session, LIBSSH2_ERROR_BUFFER_TOO_SMALL,
+                                  "Publickey response too small");
+        }
+
+        s = data;
+        response = publickey_response_id(&s, data_len);
+
+        switch(response) {
+        case LIBSSH2_PUBLICKEY_RESPONSE_STATUS:
+            /* Error, or processing complete */
+        {
+            unsigned long status = 0;
+
+            if(data_len < 8) {
+                return _libssh2_error(session, LIBSSH2_ERROR_BUFFER_TOO_SMALL,
+                                      "Publickey response too small");
+            }
+
+            status = _libssh2_ntohu32(s);
+
+            LIBSSH2_FREE(session, data);
+
+            if(status == LIBSSH2_PUBLICKEY_SUCCESS)
+                return 0;
+
+            publickey_status_error(pkey, session, status);
+            return -1;
+        }
+        default:
+            LIBSSH2_FREE(session, data);
+            if(response < 0) {
+                return _libssh2_error(session,
+                                      LIBSSH2_ERROR_PUBLICKEY_PROTOCOL,
+                                      "Invalid publickey subsystem response");
+            }
+            /* Unknown/Unexpected */
+            _libssh2_error(session, LIBSSH2_ERROR_PUBLICKEY_PROTOCOL,
+                           "Unexpected publickey subsystem response");
+            data = NULL;
+        }
+    }
+    /* never reached, but include `return` to silence compiler warnings */
+    return -1;
+}
+
+/* *****************
+ * Publickey API *
+ ***************** */
+
+/*
+ * publickey_init
+ *
+ * Startup the publickey subsystem
+ */
+static LIBSSH2_PUBLICKEY *publickey_init(LIBSSH2_SESSION *session)
+{
+    int response;
+    int rc;
+
+    if(session->pkeyInit_state == libssh2_NB_state_idle) {
+        session->pkeyInit_data = NULL;
+        session->pkeyInit_pkey = NULL;
+        session->pkeyInit_channel = NULL;
+
+        _libssh2_debug(session, LIBSSH2_TRACE_PUBLICKEY,
+                       "Initializing publickey subsystem");
+
+        session->pkeyInit_state = libssh2_NB_state_allocated;
+    }
+
+    if(session->pkeyInit_state == libssh2_NB_state_allocated) {
+
+        session->pkeyInit_channel =
+            _libssh2_channel_open(session, "session",
+                                  sizeof("session") - 1,
+                                  LIBSSH2_CHANNEL_WINDOW_DEFAULT,
+                                  LIBSSH2_CHANNEL_PACKET_DEFAULT, NULL,
+                                  0);
+        if(!session->pkeyInit_channel) {
+            if(libssh2_session_last_errno(session) == LIBSSH2_ERROR_EAGAIN)
+                /* The error state is already set, so leave it */
+                return NULL;
+            _libssh2_error(session, LIBSSH2_ERROR_CHANNEL_FAILURE,
+                           "Unable to startup channel");
+            goto err_exit;
+        }
+
+        session->pkeyInit_state = libssh2_NB_state_sent;
+    }
+
+    if(session->pkeyInit_state == libssh2_NB_state_sent) {
+        rc = _libssh2_channel_process_startup(session->pkeyInit_channel,
+                                              "subsystem",
+                                              sizeof("subsystem") - 1,
+                                              "publickey",
+                                              sizeof("publickey") - 1);
+        if(rc == LIBSSH2_ERROR_EAGAIN) {
+            _libssh2_error(session, LIBSSH2_ERROR_EAGAIN,
+                           "Would block starting publickey subsystem");
+            return NULL;
+        }
+        else if(rc) {
+            _libssh2_error(session, LIBSSH2_ERROR_CHANNEL_FAILURE,
+                           "Unable to request publickey subsystem");
+            goto err_exit;
+        }
+
+        session->pkeyInit_state = libssh2_NB_state_sent1;
+    }
+
+    if(session->pkeyInit_state == libssh2_NB_state_sent1) {
+        unsigned char *s;
+        rc = _libssh2_channel_extended_data(session->pkeyInit_channel,
+                                         LIBSSH2_CHANNEL_EXTENDED_DATA_IGNORE);
+        if(rc == LIBSSH2_ERROR_EAGAIN) {
+            _libssh2_error(session, LIBSSH2_ERROR_EAGAIN,
+                           "Would block starting publickey subsystem");
+            return NULL;
+        }
+
+        session->pkeyInit_pkey =
+            LIBSSH2_CALLOC(session, sizeof(LIBSSH2_PUBLICKEY));
+        if(!session->pkeyInit_pkey) {
+            _libssh2_error(session, LIBSSH2_ERROR_ALLOC,
+                           "Unable to allocate a new publickey structure");
+            goto err_exit;
+        }
+        session->pkeyInit_pkey->channel = session->pkeyInit_channel;
+        session->pkeyInit_pkey->version = 0;
+
+        s = session->pkeyInit_buffer;
+        _libssh2_htonu32(s, 4 + (sizeof("version") - 1) + 4);
+        s += 4;
+        _libssh2_htonu32(s, sizeof("version") - 1);
+        s += 4;
+        memcpy(s, "version", sizeof("version") - 1);
+        s += sizeof("version") - 1;
+        _libssh2_htonu32(s, LIBSSH2_PUBLICKEY_VERSION);
+
+        session->pkeyInit_buffer_sent = 0;
+
+        _libssh2_debug(session, LIBSSH2_TRACE_PUBLICKEY,
+                       "Sending publickey advertising version %d support",
+                       (int) LIBSSH2_PUBLICKEY_VERSION);
+
+        session->pkeyInit_state = libssh2_NB_state_sent2;
+    }
+
+    if(session->pkeyInit_state == libssh2_NB_state_sent2) {
+        rc = _libssh2_channel_write(session->pkeyInit_channel, 0,
+                                    session->pkeyInit_buffer,
+                                    19 - session->pkeyInit_buffer_sent);
+        if(rc == LIBSSH2_ERROR_EAGAIN) {
+            _libssh2_error(session, LIBSSH2_ERROR_EAGAIN,
+                           "Would block sending publickey version packet");
+            return NULL;
+        }
+        else if(rc < 0) {
+            _libssh2_error(session, rc,
+                           "Unable to send publickey version packet");
+            goto err_exit;
+        }
+        session->pkeyInit_buffer_sent += rc;
+        if(session->pkeyInit_buffer_sent < 19) {
+            _libssh2_error(session, LIBSSH2_ERROR_EAGAIN,
+                           "Need to be called again to complete this");
+            return NULL;
+        }
+
+        session->pkeyInit_state = libssh2_NB_state_sent3;
+    }
+
+    if(session->pkeyInit_state == libssh2_NB_state_sent3) {
+        while(1) {
+            unsigned char *s;
+            rc = publickey_packet_receive(session->pkeyInit_pkey,
+                                          &session->pkeyInit_data,
+                                          &session->pkeyInit_data_len);
+            if(rc == LIBSSH2_ERROR_EAGAIN) {
+                _libssh2_error(session, LIBSSH2_ERROR_EAGAIN,
+                               "Would block waiting for response from "
+                               "publickey subsystem");
+                return NULL;
+            }
+            else if(rc) {
+                _libssh2_error(session, LIBSSH2_ERROR_SOCKET_TIMEOUT,
+                               "Timeout waiting for response from "
+                               "publickey subsystem");
+                goto err_exit;
+            }
+
+            s = session->pkeyInit_data;
+            if((response =
+                 publickey_response_id(&s, session->pkeyInit_data_len)) < 0) {
+                _libssh2_error(session, LIBSSH2_ERROR_PUBLICKEY_PROTOCOL,
+                               "Invalid publickey subsystem response code");
+                goto err_exit;
+            }
+
+            if(session->pkeyInit_data_len < 4) {
+                _libssh2_error(session, LIBSSH2_ERROR_BUFFER_TOO_SMALL,
+                               "Public key init data too small");
+                goto err_exit;
+            }
+
+            switch(response) {
+            case LIBSSH2_PUBLICKEY_RESPONSE_STATUS:
+                /* Error */
+            {
+                unsigned long status, descr_len, lang_len;
+
+                if(session->pkeyInit_data_len >= 8) {
+                    status = _libssh2_ntohu32(s);
+                    s += 4;
+                    descr_len = _libssh2_ntohu32(s);
+                    s += 4;
+                }
+                else {
+                    _libssh2_error(session, LIBSSH2_ERROR_BUFFER_TOO_SMALL,
+                                   "Public key init data too small");
+                    goto err_exit;
+                }
+
+                if(s + descr_len + 4 <=
+                   session->pkeyInit_data + session->pkeyInit_data_len) {
+                    /* description starts here */
+                    s += descr_len;
+                    lang_len = _libssh2_ntohu32(s);
+                    s += 4;
+                }
+                else {
+                    _libssh2_error(session, LIBSSH2_ERROR_BUFFER_TOO_SMALL,
+                                   "Public key init data too small");
+                    goto err_exit;
+                }
+
+                if(s + lang_len <=
+                   session->pkeyInit_data + session->pkeyInit_data_len) {
+                    /* lang starts here */
+                    s += lang_len;
+                }
+                else {
+                    _libssh2_error(session, LIBSSH2_ERROR_BUFFER_TOO_SMALL,
+                                   "Public key init data too small");
+                    goto err_exit;
+                }
+
+                if(s >
+                    session->pkeyInit_data + session->pkeyInit_data_len) {
+                    _libssh2_error(session,
+                                   LIBSSH2_ERROR_PUBLICKEY_PROTOCOL,
+                                   "Malformed publickey subsystem packet");
+                    goto err_exit;
+                }
+
+                publickey_status_error(NULL, session, status);
+
+                goto err_exit;
+            }
+
+            case LIBSSH2_PUBLICKEY_RESPONSE_VERSION:
+                /* What we want */
+                session->pkeyInit_pkey->version = _libssh2_ntohu32(s);
+                if(session->pkeyInit_pkey->version >
+                    LIBSSH2_PUBLICKEY_VERSION) {
+                    _libssh2_debug(session, LIBSSH2_TRACE_PUBLICKEY,
+                                   "Truncate remote publickey version "
+                                   "from %lu",
+                                   session->pkeyInit_pkey->version);
+                    session->pkeyInit_pkey->version =
+                        LIBSSH2_PUBLICKEY_VERSION;
+                }
+                _libssh2_debug(session, LIBSSH2_TRACE_PUBLICKEY,
+                               "Enabling publickey subsystem version %lu",
+                               session->pkeyInit_pkey->version);
+                LIBSSH2_FREE(session, session->pkeyInit_data);
+                session->pkeyInit_data = NULL;
+                session->pkeyInit_state = libssh2_NB_state_idle;
+                return session->pkeyInit_pkey;
+
+            default:
+                /* Unknown/Unexpected */
+                _libssh2_error(session, LIBSSH2_ERROR_PUBLICKEY_PROTOCOL,
+                               "Unexpected publickey subsystem response, "
+                               "ignoring");
+                LIBSSH2_FREE(session, session->pkeyInit_data);
+                session->pkeyInit_data = NULL;
+            }
+        }
+    }
+
+    /* Never reached except by direct goto */
+  err_exit:
+    session->pkeyInit_state = libssh2_NB_state_sent4;
+    if(session->pkeyInit_channel) {
+        rc = _libssh2_channel_close(session->pkeyInit_channel);
+        if(rc == LIBSSH2_ERROR_EAGAIN) {
+            _libssh2_error(session, LIBSSH2_ERROR_EAGAIN,
+                           "Would block closing channel");
+            return NULL;
+        }
+    }
+    if(session->pkeyInit_pkey) {
+        LIBSSH2_FREE(session, session->pkeyInit_pkey);
+        session->pkeyInit_pkey = NULL;
+    }
+    if(session->pkeyInit_data) {
+        LIBSSH2_FREE(session, session->pkeyInit_data);
+        session->pkeyInit_data = NULL;
+    }
+    session->pkeyInit_state = libssh2_NB_state_idle;
+    return NULL;
+}
+
+/*
+ * libssh2_publickey_init
+ *
+ * Startup the publickey subsystem
+ */
+LIBSSH2_API LIBSSH2_PUBLICKEY *
+libssh2_publickey_init(LIBSSH2_SESSION *session)
+{
+    LIBSSH2_PUBLICKEY *ptr;
+
+    BLOCK_ADJUST_ERRNO(ptr, session,
+                       publickey_init(session));
+    return ptr;
+}
+
+
+
+/*
+ * libssh2_publickey_add_ex
+ *
+ * Add a new public key entry
+ */
+LIBSSH2_API int
+libssh2_publickey_add_ex(LIBSSH2_PUBLICKEY *pkey, const unsigned char *name,
+                         unsigned long name_len, const unsigned char *blob,
+                         unsigned long blob_len, char overwrite,
+                         unsigned long num_attrs,
+                         const libssh2_publickey_attribute attrs[])
+{
+    LIBSSH2_CHANNEL *channel;
+    LIBSSH2_SESSION *session;
+    /*  19 = packet_len(4) + add_len(4) + "add"(3) + name_len(4) + {name}
+        blob_len(4) + {blob} */
+    unsigned long i, packet_len = 19 + name_len + blob_len;
+    unsigned char *comment = NULL;
+    unsigned long comment_len = 0;
+    int rc;
+
+    if(!pkey)
+        return LIBSSH2_ERROR_BAD_USE;
+
+    channel = pkey->channel;
+    session = channel->session;
+
+    if(pkey->add_state == libssh2_NB_state_idle) {
+        pkey->add_packet = NULL;
+
+        _libssh2_debug(session, LIBSSH2_TRACE_PUBLICKEY, "Adding %s publickey",
+                       name);
+
+        if(pkey->version == 1) {
+            for(i = 0; i < num_attrs; i++) {
+                /* Search for a comment attribute */
+                if(attrs[i].name_len == (sizeof("comment") - 1) &&
+                    strncmp(attrs[i].name, "comment",
+                            sizeof("comment") - 1) == 0) {
+                    comment = (unsigned char *) attrs[i].value;
+                    comment_len = attrs[i].value_len;
+                    break;
+                }
+            }
+            packet_len += 4 + comment_len;
+        }
+        else {
+            packet_len += 5;    /* overwrite(1) + attribute_count(4) */
+            for(i = 0; i < num_attrs; i++) {
+                packet_len += 9 + attrs[i].name_len + attrs[i].value_len;
+                /* name_len(4) + value_len(4) + mandatory(1) */
+            }
+        }
+
+        pkey->add_packet = LIBSSH2_ALLOC(session, packet_len);
+        if(!pkey->add_packet) {
+            return _libssh2_error(session, LIBSSH2_ERROR_ALLOC,
+                                  "Unable to allocate memory for "
+                                  "publickey \"add\" packet");
+        }
+
+        pkey->add_s = pkey->add_packet;
+        _libssh2_htonu32(pkey->add_s, packet_len - 4);
+        pkey->add_s += 4;
+        _libssh2_htonu32(pkey->add_s, sizeof("add") - 1);
+        pkey->add_s += 4;
+        memcpy(pkey->add_s, "add", sizeof("add") - 1);
+        pkey->add_s += sizeof("add") - 1;
+        if(pkey->version == 1) {
+            _libssh2_htonu32(pkey->add_s, comment_len);
+            pkey->add_s += 4;
+            if(comment) {
+                memcpy(pkey->add_s, comment, comment_len);
+                pkey->add_s += comment_len;
+            }
+
+            _libssh2_htonu32(pkey->add_s, name_len);
+            pkey->add_s += 4;
+            memcpy(pkey->add_s, name, name_len);
+            pkey->add_s += name_len;
+            _libssh2_htonu32(pkey->add_s, blob_len);
+            pkey->add_s += 4;
+            memcpy(pkey->add_s, blob, blob_len);
+            pkey->add_s += blob_len;
+        }
+        else {
+            /* Version == 2 */
+
+            _libssh2_htonu32(pkey->add_s, name_len);
+            pkey->add_s += 4;
+            memcpy(pkey->add_s, name, name_len);
+            pkey->add_s += name_len;
+            _libssh2_htonu32(pkey->add_s, blob_len);
+            pkey->add_s += 4;
+            memcpy(pkey->add_s, blob, blob_len);
+            pkey->add_s += blob_len;
+            *(pkey->add_s++) = overwrite ? 0x01 : 0;
+            _libssh2_htonu32(pkey->add_s, num_attrs);
+            pkey->add_s += 4;
+            for(i = 0; i < num_attrs; i++) {
+                _libssh2_htonu32(pkey->add_s, attrs[i].name_len);
+                pkey->add_s += 4;
+                memcpy(pkey->add_s, attrs[i].name, attrs[i].name_len);
+                pkey->add_s += attrs[i].name_len;
+                _libssh2_htonu32(pkey->add_s, attrs[i].value_len);
+                pkey->add_s += 4;
+                memcpy(pkey->add_s, attrs[i].value, attrs[i].value_len);
+                pkey->add_s += attrs[i].value_len;
+                *(pkey->add_s++) = attrs[i].mandatory ? 0x01 : 0;
+            }
+        }
+
+        _libssh2_debug(session, LIBSSH2_TRACE_PUBLICKEY,
+                       "Sending publickey \"add\" packet: "
+                       "type=%s blob_len=%ld num_attrs=%ld",
+                       name, blob_len, num_attrs);
+
+        pkey->add_state = libssh2_NB_state_created;
+    }
+
+    if(pkey->add_state == libssh2_NB_state_created) {
+        rc = _libssh2_channel_write(channel, 0, pkey->add_packet,
+                                    (pkey->add_s - pkey->add_packet));
+        if(rc == LIBSSH2_ERROR_EAGAIN) {
+            return rc;
+        }
+        else if((pkey->add_s - pkey->add_packet) != rc) {
+            LIBSSH2_FREE(session, pkey->add_packet);
+            pkey->add_packet = NULL;
+            return _libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND,
+                                  "Unable to send publickey add packet");
+        }
+        LIBSSH2_FREE(session, pkey->add_packet);
+        pkey->add_packet = NULL;
+
+        pkey->add_state = libssh2_NB_state_sent;
+    }
+
+    rc = publickey_response_success(pkey);
+    if(rc == LIBSSH2_ERROR_EAGAIN) {
+        return rc;
+    }
+
+    pkey->add_state = libssh2_NB_state_idle;
+
+    return rc;
+}
+
+/* libssh2_publickey_remove_ex
+ * Remove an existing publickey so that authentication can no longer be
+ * performed using it
+ */
+LIBSSH2_API int
+libssh2_publickey_remove_ex(LIBSSH2_PUBLICKEY * pkey,
+                            const unsigned char *name, unsigned long name_len,
+                            const unsigned char *blob, unsigned long blob_len)
+{
+    LIBSSH2_CHANNEL *channel;
+    LIBSSH2_SESSION *session;
+    /* 22 = packet_len(4) + remove_len(4) + "remove"(6) + name_len(4) + {name}
+       + blob_len(4) + {blob} */
+    unsigned long packet_len = 22 + name_len + blob_len;
+    int rc;
+
+    if(!pkey)
+        return LIBSSH2_ERROR_BAD_USE;
+
+    channel = pkey->channel;
+    session = channel->session;
+
+    if(pkey->remove_state == libssh2_NB_state_idle) {
+        pkey->remove_packet = NULL;
+
+        pkey->remove_packet = LIBSSH2_ALLOC(session, packet_len);
+        if(!pkey->remove_packet) {
+            return _libssh2_error(session, LIBSSH2_ERROR_ALLOC,
+                                  "Unable to allocate memory for "
+                                  "publickey \"remove\" packet");
+        }
+
+        pkey->remove_s = pkey->remove_packet;
+        _libssh2_htonu32(pkey->remove_s, packet_len - 4);
+        pkey->remove_s += 4;
+        _libssh2_htonu32(pkey->remove_s, sizeof("remove") - 1);
+        pkey->remove_s += 4;
+        memcpy(pkey->remove_s, "remove", sizeof("remove") - 1);
+        pkey->remove_s += sizeof("remove") - 1;
+        _libssh2_htonu32(pkey->remove_s, name_len);
+        pkey->remove_s += 4;
+        memcpy(pkey->remove_s, name, name_len);
+        pkey->remove_s += name_len;
+        _libssh2_htonu32(pkey->remove_s, blob_len);
+        pkey->remove_s += 4;
+        memcpy(pkey->remove_s, blob, blob_len);
+        pkey->remove_s += blob_len;
+
+        _libssh2_debug(session, LIBSSH2_TRACE_PUBLICKEY,
+                       "Sending publickey \"remove\" packet: "
+                       "type=%s blob_len=%ld",
+                       name, blob_len);
+
+        pkey->remove_state = libssh2_NB_state_created;
+    }
+
+    if(pkey->remove_state == libssh2_NB_state_created) {
+        rc = _libssh2_channel_write(channel, 0, pkey->remove_packet,
+                                    (pkey->remove_s - pkey->remove_packet));
+        if(rc == LIBSSH2_ERROR_EAGAIN) {
+            return rc;
+        }
+        else if((pkey->remove_s - pkey->remove_packet) != rc) {
+            LIBSSH2_FREE(session, pkey->remove_packet);
+            pkey->remove_packet = NULL;
+            pkey->remove_state = libssh2_NB_state_idle;
+            return _libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND,
+                                  "Unable to send publickey remove packet");
+        }
+        LIBSSH2_FREE(session, pkey->remove_packet);
+        pkey->remove_packet = NULL;
+
+        pkey->remove_state = libssh2_NB_state_sent;
+    }
+
+    rc = publickey_response_success(pkey);
+    if(rc == LIBSSH2_ERROR_EAGAIN) {
+        return rc;
+    }
+
+    pkey->remove_state = libssh2_NB_state_idle;
+
+    return rc;
+}
+
+/* libssh2_publickey_list_fetch
+ * Fetch a list of supported public key from a server
+ */
+LIBSSH2_API int
+libssh2_publickey_list_fetch(LIBSSH2_PUBLICKEY * pkey, unsigned long *num_keys,
+                             libssh2_publickey_list ** pkey_list)
+{
+    LIBSSH2_CHANNEL *channel;
+    LIBSSH2_SESSION *session;
+    libssh2_publickey_list *list = NULL;
+    unsigned long buffer_len = 12, keys = 0, max_keys = 0, i;
+    /* 12 = packet_len(4) + list_len(4) + "list"(4) */
+    int response;
+    int rc;
+
+    if(!pkey)
+        return LIBSSH2_ERROR_BAD_USE;
+
+    channel = pkey->channel;
+    session = channel->session;
+
+    if(pkey->listFetch_state == libssh2_NB_state_idle) {
+        pkey->listFetch_data = NULL;
+
+        pkey->listFetch_s = pkey->listFetch_buffer;
+        _libssh2_htonu32(pkey->listFetch_s, buffer_len - 4);
+        pkey->listFetch_s += 4;
+        _libssh2_htonu32(pkey->listFetch_s, sizeof("list") - 1);
+        pkey->listFetch_s += 4;
+        memcpy(pkey->listFetch_s, "list", sizeof("list") - 1);
+        pkey->listFetch_s += sizeof("list") - 1;
+
+        _libssh2_debug(session, LIBSSH2_TRACE_PUBLICKEY,
+                       "Sending publickey \"list\" packet");
+
+        pkey->listFetch_state = libssh2_NB_state_created;
+    }
+
+    if(pkey->listFetch_state == libssh2_NB_state_created) {
+        rc = _libssh2_channel_write(channel, 0,
+                                    pkey->listFetch_buffer,
+                                    (pkey->listFetch_s -
+                                     pkey->listFetch_buffer));
+        if(rc == LIBSSH2_ERROR_EAGAIN) {
+            return rc;
+        }
+        else if((pkey->listFetch_s - pkey->listFetch_buffer) != rc) {
+            pkey->listFetch_state = libssh2_NB_state_idle;
+            return _libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND,
+                                  "Unable to send publickey list packet");
+        }
+
+        pkey->listFetch_state = libssh2_NB_state_sent;
+    }
+
+    while(1) {
+        rc = publickey_packet_receive(pkey, &pkey->listFetch_data,
+                                      &pkey->listFetch_data_len);
+        if(rc == LIBSSH2_ERROR_EAGAIN) {
+            return rc;
+        }
+        else if(rc) {
+            _libssh2_error(session, LIBSSH2_ERROR_SOCKET_TIMEOUT,
+                           "Timeout waiting for response from "
+                           "publickey subsystem");
+            goto err_exit;
+        }
+
+        pkey->listFetch_s = pkey->listFetch_data;
+        if((response =
+             publickey_response_id(&pkey->listFetch_s,
+                                   pkey->listFetch_data_len)) < 0) {
+            _libssh2_error(session, LIBSSH2_ERROR_PUBLICKEY_PROTOCOL,
+                           "Invalid publickey subsystem response code");
+            goto err_exit;
+        }
+
+        switch(response) {
+        case LIBSSH2_PUBLICKEY_RESPONSE_STATUS:
+            /* Error, or processing complete */
+        {
+            unsigned long status, descr_len, lang_len;
+
+            if(pkey->listFetch_s + 8 <=
+               pkey->listFetch_data + pkey->listFetch_data_len) {
+                status = _libssh2_ntohu32(pkey->listFetch_s);
+                pkey->listFetch_s += 4;
+                descr_len = _libssh2_ntohu32(pkey->listFetch_s);
+                pkey->listFetch_s += 4;
+            }
+            else {
+                _libssh2_error(session, LIBSSH2_ERROR_BUFFER_TOO_SMALL,
+                               "ListFetch data too short");
+                goto err_exit;
+            }
+
+            if(pkey->listFetch_s + descr_len + 4 <=
+               pkey->listFetch_data + pkey->listFetch_data_len) {
+                /* description starts at pkey->listFetch_s */
+                pkey->listFetch_s += descr_len;
+                lang_len = _libssh2_ntohu32(pkey->listFetch_s);
+                pkey->listFetch_s += 4;
+            }
+            else {
+                _libssh2_error(session, LIBSSH2_ERROR_BUFFER_TOO_SMALL,
+                               "ListFetch data too short");
+                goto err_exit;
+            }
+
+            if(pkey->listFetch_s + lang_len <=
+               pkey->listFetch_data + pkey->listFetch_data_len) {
+                /* lang starts at pkey->listFetch_s */
+                pkey->listFetch_s += lang_len;
+            }
+            else {
+                _libssh2_error(session, LIBSSH2_ERROR_BUFFER_TOO_SMALL,
+                               "ListFetch data too short");
+                goto err_exit;
+            }
+
+            if(pkey->listFetch_s >
+                pkey->listFetch_data + pkey->listFetch_data_len) {
+                _libssh2_error(session, LIBSSH2_ERROR_PUBLICKEY_PROTOCOL,
+                               "Malformed publickey subsystem packet");
+                goto err_exit;
+            }
+
+            if(status == LIBSSH2_PUBLICKEY_SUCCESS) {
+                LIBSSH2_FREE(session, pkey->listFetch_data);
+                pkey->listFetch_data = NULL;
+                *pkey_list = list;
+                *num_keys = keys;
+                pkey->listFetch_state = libssh2_NB_state_idle;
+                return 0;
+            }
+
+            publickey_status_error(pkey, session, status);
+            goto err_exit;
+        }
+        case LIBSSH2_PUBLICKEY_RESPONSE_PUBLICKEY:
+            /* What we want */
+            if(keys >= max_keys) {
+                libssh2_publickey_list *newlist;
+                /* Grow the key list if necessary */
+                max_keys += 8;
+                newlist =
+                    LIBSSH2_REALLOC(session, list,
+                                    (max_keys +
+                                     1) * sizeof(libssh2_publickey_list));
+                if(!newlist) {
+                    _libssh2_error(session, LIBSSH2_ERROR_ALLOC,
+                                   "Unable to allocate memory for "
+                                   "publickey list");
+                    goto err_exit;
+                }
+                list = newlist;
+            }
+            if(pkey->version == 1) {
+                unsigned long comment_len;
+
+                if(pkey->listFetch_s + 4 <=
+                   pkey->listFetch_data + pkey->listFetch_data_len) {
+                    comment_len = _libssh2_ntohu32(pkey->listFetch_s);
+                    pkey->listFetch_s += 4;
+                }
+                else {
+                    _libssh2_error(session, LIBSSH2_ERROR_BUFFER_TOO_SMALL,
+                                   "ListFetch data too short");
+                    goto err_exit;
+                }
+
+                if(comment_len) {
+                    list[keys].num_attrs = 1;
+                    list[keys].attrs =
+                        LIBSSH2_ALLOC(session,
+                                      sizeof(libssh2_publickey_attribute));
+                    if(!list[keys].attrs) {
+                        _libssh2_error(session, LIBSSH2_ERROR_ALLOC,
+                                       "Unable to allocate memory for "
+                                       "publickey attributes");
+                        goto err_exit;
+                    }
+                    list[keys].attrs[0].name = "comment";
+                    list[keys].attrs[0].name_len = sizeof("comment") - 1;
+                    list[keys].attrs[0].value = (char *) pkey->listFetch_s;
+                    list[keys].attrs[0].value_len = comment_len;
+                    list[keys].attrs[0].mandatory = 0;
+
+                    pkey->listFetch_s += comment_len;
+                }
+                else {
+                    list[keys].num_attrs = 0;
+                    list[keys].attrs = NULL;
+                }
+
+                if(pkey->listFetch_s + 4 <=
+                    pkey->listFetch_data + pkey->listFetch_data_len) {
+                    list[keys].name_len = _libssh2_ntohu32(pkey->listFetch_s);
+                    pkey->listFetch_s += 4;
+                }
+                else {
+                    _libssh2_error(session, LIBSSH2_ERROR_BUFFER_TOO_SMALL,
+                                   "ListFetch data too short");
+                    goto err_exit;
+                }
+
+                if(pkey->listFetch_s + list[keys].name_len <=
+                   pkey->listFetch_data + pkey->listFetch_data_len) {
+                    list[keys].name = pkey->listFetch_s;
+                    pkey->listFetch_s += list[keys].name_len;
+                }
+                else {
+                    _libssh2_error(session, LIBSSH2_ERROR_BUFFER_TOO_SMALL,
+                                   "ListFetch data too short");
+                    goto err_exit;
+                }
+
+                if(pkey->listFetch_s + 4 <=
+                   pkey->listFetch_data + pkey->listFetch_data_len) {
+                    list[keys].blob_len = _libssh2_ntohu32(pkey->listFetch_s);
+                    pkey->listFetch_s += 4;
+                }
+                else {
+                    _libssh2_error(session, LIBSSH2_ERROR_BUFFER_TOO_SMALL,
+                                   "ListFetch data too short");
+                    goto err_exit;
+                }
+
+                if(pkey->listFetch_s + list[keys].blob_len <=
+                   pkey->listFetch_data + pkey->listFetch_data_len) {
+                    list[keys].blob = pkey->listFetch_s;
+                    pkey->listFetch_s += list[keys].blob_len;
+                }
+                else {
+                    _libssh2_error(session, LIBSSH2_ERROR_BUFFER_TOO_SMALL,
+                                   "ListFetch data too short");
+                    goto err_exit;
+                }
+            }
+            else {
+                /* Version == 2 */
+
+                if(pkey->listFetch_s + 4 <=
+                   pkey->listFetch_data + pkey->listFetch_data_len) {
+                    list[keys].name_len = _libssh2_ntohu32(pkey->listFetch_s);
+                    pkey->listFetch_s += 4;
+                }
+                else {
+                    _libssh2_error(session, LIBSSH2_ERROR_BUFFER_TOO_SMALL,
+                                   "ListFetch data too short");
+                    goto err_exit;
+                }
+
+                if(pkey->listFetch_s + list[keys].name_len <=
+                   pkey->listFetch_data + pkey->listFetch_data_len) {
+                    list[keys].name = pkey->listFetch_s;
+                    pkey->listFetch_s += list[keys].name_len;
+                }
+                else {
+                    _libssh2_error(session, LIBSSH2_ERROR_BUFFER_TOO_SMALL,
+                                   "ListFetch data too short");
+                    goto err_exit;
+                }
+
+                if(pkey->listFetch_s + 4 <=
+                   pkey->listFetch_data + pkey->listFetch_data_len) {
+                    list[keys].blob_len = _libssh2_ntohu32(pkey->listFetch_s);
+                    pkey->listFetch_s += 4;
+                }
+                else {
+                    _libssh2_error(session, LIBSSH2_ERROR_BUFFER_TOO_SMALL,
+                                   "ListFetch data too short");
+                    goto err_exit;
+                }
+
+                if(pkey->listFetch_s + list[keys].blob_len <=
+                   pkey->listFetch_data + pkey->listFetch_data_len) {
+                    list[keys].blob = pkey->listFetch_s;
+                    pkey->listFetch_s += list[keys].blob_len;
+                }
+                else {
+                    _libssh2_error(session, LIBSSH2_ERROR_BUFFER_TOO_SMALL,
+                                   "ListFetch data too short");
+                    goto err_exit;
+                }
+
+                if(pkey->listFetch_s + 4 <=
+                   pkey->listFetch_data + pkey->listFetch_data_len) {
+                    list[keys].num_attrs = _libssh2_ntohu32(pkey->listFetch_s);
+                    pkey->listFetch_s += 4;
+                }
+                else {
+                    _libssh2_error(session, LIBSSH2_ERROR_BUFFER_TOO_SMALL,
+                                   "ListFetch data too short");
+                    goto err_exit;
+                }
+
+                if(list[keys].num_attrs) {
+                    list[keys].attrs =
+                        LIBSSH2_ALLOC(session,
+                                      list[keys].num_attrs *
+                                      sizeof(libssh2_publickey_attribute));
+                    if(!list[keys].attrs) {
+                        _libssh2_error(session, LIBSSH2_ERROR_ALLOC,
+                                       "Unable to allocate memory for "
+                                       "publickey attributes");
+                        goto err_exit;
+                    }
+                    for(i = 0; i < list[keys].num_attrs; i++) {
+                        if(pkey->listFetch_s + 4 <=
+                           pkey->listFetch_data + pkey->listFetch_data_len) {
+                            list[keys].attrs[i].name_len =
+                                _libssh2_ntohu32(pkey->listFetch_s);
+                            pkey->listFetch_s += 4;
+                        }
+                        else {
+                            _libssh2_error(session,
+                                           LIBSSH2_ERROR_BUFFER_TOO_SMALL,
+                                           "ListFetch data too short");
+                            goto err_exit;
+                        }
+
+                        if(pkey->listFetch_s + list[keys].attrs[i].name_len <=
+                           pkey->listFetch_data + pkey->listFetch_data_len) {
+                            list[keys].attrs[i].name =
+                                (char *) pkey->listFetch_s;
+                            pkey->listFetch_s += list[keys].attrs[i].name_len;
+                        }
+                        else {
+                            _libssh2_error(session,
+                                           LIBSSH2_ERROR_BUFFER_TOO_SMALL,
+                                           "ListFetch data too short");
+                            goto err_exit;
+                        }
+
+                        if(pkey->listFetch_s + 4 <=
+                           pkey->listFetch_data + pkey->listFetch_data_len) {
+                            list[keys].attrs[i].value_len =
+                                _libssh2_ntohu32(pkey->listFetch_s);
+                            pkey->listFetch_s += 4;
+                        }
+                        else {
+                            _libssh2_error(session,
+                                           LIBSSH2_ERROR_BUFFER_TOO_SMALL,
+                                           "ListFetch data too short");
+                            goto err_exit;
+                        }
+
+                        if(pkey->listFetch_s +
+                           list[keys].attrs[i].value_len <=
+                           pkey->listFetch_data + pkey->listFetch_data_len) {
+                            list[keys].attrs[i].value =
+                                (char *) pkey->listFetch_s;
+                            pkey->listFetch_s += list[keys].attrs[i].value_len;
+                        }
+                        else {
+                            _libssh2_error(session,
+                                           LIBSSH2_ERROR_BUFFER_TOO_SMALL,
+                                           "ListFetch data too short");
+                            goto err_exit;
+                        }
+
+                        /* actually an ignored value */
+                        list[keys].attrs[i].mandatory = 0;
+                    }
+                }
+                else {
+                    list[keys].attrs = NULL;
+                }
+            }
+            /* To be FREEd in libssh2_publickey_list_free() */
+            list[keys].packet = pkey->listFetch_data;
+            keys++;
+
+            list[keys].packet = NULL;   /* Terminate the list */
+            pkey->listFetch_data = NULL;
+            break;
+        default:
+            /* Unknown/Unexpected */
+            _libssh2_error(session, LIBSSH2_ERROR_PUBLICKEY_PROTOCOL,
+                           "Unexpected publickey subsystem response");
+            LIBSSH2_FREE(session, pkey->listFetch_data);
+            pkey->listFetch_data = NULL;
+        }
+    }
+
+    /* Only reached via explicit goto */
+  err_exit:
+    if(pkey->listFetch_data) {
+        LIBSSH2_FREE(session, pkey->listFetch_data);
+        pkey->listFetch_data = NULL;
+    }
+    if(list) {
+        libssh2_publickey_list_free(pkey, list);
+    }
+    pkey->listFetch_state = libssh2_NB_state_idle;
+    return -1;
+}
+
+/* libssh2_publickey_list_free
+ * Free a previously fetched list of public keys
+ */
+LIBSSH2_API void
+libssh2_publickey_list_free(LIBSSH2_PUBLICKEY * pkey,
+                            libssh2_publickey_list * pkey_list)
+{
+    LIBSSH2_SESSION *session;
+    libssh2_publickey_list *p = pkey_list;
+
+    if(!pkey || !p)
+        return;
+
+    session = pkey->channel->session;
+
+    while(p->packet) {
+        if(p->attrs) {
+            LIBSSH2_FREE(session, p->attrs);
+        }
+        LIBSSH2_FREE(session, p->packet);
+        p++;
+    }
+
+    LIBSSH2_FREE(session, pkey_list);
+}
+
+/* libssh2_publickey_shutdown
+ * Shutdown the publickey subsystem
+ */
+LIBSSH2_API int
+libssh2_publickey_shutdown(LIBSSH2_PUBLICKEY *pkey)
+{
+    LIBSSH2_SESSION *session;
+    int rc;
+
+    if(!pkey)
+        return LIBSSH2_ERROR_BAD_USE;
+
+    session = pkey->channel->session;
+
+    /*
+     * Make sure all memory used in the state variables are free
+     */
+    if(pkey->receive_packet) {
+        LIBSSH2_FREE(session, pkey->receive_packet);
+        pkey->receive_packet = NULL;
+    }
+    if(pkey->add_packet) {
+        LIBSSH2_FREE(session, pkey->add_packet);
+        pkey->add_packet = NULL;
+    }
+    if(pkey->remove_packet) {
+        LIBSSH2_FREE(session, pkey->remove_packet);
+        pkey->remove_packet = NULL;
+    }
+    if(pkey->listFetch_data) {
+        LIBSSH2_FREE(session, pkey->listFetch_data);
+        pkey->listFetch_data = NULL;
+    }
+
+    rc = _libssh2_channel_free(pkey->channel);
+    if(rc == LIBSSH2_ERROR_EAGAIN)
+        return rc;
+
+    LIBSSH2_FREE(session, pkey);
+    return 0;
+}

+ 1145 - 0
libssh2/libssh2/src/scp.c

@@ -0,0 +1,1145 @@
+/* Copyright (c) 2009-2019 by Daniel Stenberg
+ * Copyright (c) 2004-2008, Sara Golemon <sarag@libssh2.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms,
+ * with or without modification, are permitted provided
+ * that the following conditions are met:
+ *
+ *   Redistributions of source code must retain the above
+ *   copyright notice, this list of conditions and the
+ *   following disclaimer.
+ *
+ *   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.
+ *
+ *   Neither the name of the copyright holder nor the names
+ *   of any other contributors may be used to endorse or
+ *   promote products derived from this software without
+ *   specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+ * CONTRIBUTORS "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 COPYRIGHT OWNER OR
+ * CONTRIBUTORS 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 "libssh2_priv.h"
+#include <errno.h>
+#include <stdlib.h>
+
+#include "channel.h"
+#include "session.h"
+
+
+/* Max. length of a quoted string after libssh2_shell_quotearg() processing */
+#define _libssh2_shell_quotedsize(s)     (3 * strlen(s) + 2)
+
+/*
+  This function quotes a string in a way suitable to be used with a
+  shell, e.g. the file name
+  one two
+  becomes
+  'one two'
+
+  The resulting output string is crafted in a way that makes it usable
+  with the two most common shell types: Bourne Shell derived shells
+  (sh, ksh, ksh93, bash, zsh) and C-Shell derivates (csh, tcsh).
+
+  The following special cases are handled:
+  o  If the string contains an apostrophy itself, the apostrophy
+  character is written in quotation marks, e.g. "'".
+  The shell cannot handle the syntax 'doesn\'t', so we close the
+  current argument word, add the apostrophe in quotation marks "",
+  and open a new argument word instead (_ indicate the input
+  string characters):
+  _____   _   _
+  'doesn' "'" 't'
+
+  Sequences of apostrophes are combined in one pair of quotation marks:
+  a'''b
+  becomes
+  _  ___  _
+  'a'"'''"'b'
+
+  o  If the string contains an exclamation mark (!), the C-Shell
+  interprets it as an event number. Using \! (not within quotation
+  marks or single quotation marks) is a mechanism understood by
+  both Bourne Shell and C-Shell.
+
+  If a quotation was already started, the argument word is closed
+  first:
+  a!b
+
+  become
+  _  _ _
+  'a'\!'b'
+
+  The result buffer must be large enough for the expanded result. A
+  bad case regarding expansion is alternating characters and
+  apostrophes:
+
+  a'b'c'd'                   (length 8) gets converted to
+  'a'"'"'b'"'"'c'"'"'d'"'"   (length 24)
+
+  This is the worst case.
+
+  Maximum length of the result:
+  1 + 6 * (length(input) + 1) / 2) + 1
+
+  => 3 * length(input) + 2
+
+  Explanation:
+  o  leading apostrophe
+  o  one character / apostrophe pair (two characters) can get
+  represented as 6 characters: a' -> a'"'"'
+  o  String terminator (+1)
+
+  A result buffer three times the size of the input buffer + 2
+  characters should be safe.
+
+  References:
+  o  csh-compatible quotation (special handling for '!' etc.), see
+  http://www.grymoire.com/Unix/Csh.html#toc-uh-10
+
+  Return value:
+  Length of the resulting string (not counting the terminating '\0'),
+  or 0 in case of errors, e.g. result buffer too small
+
+  Note: this function could possible be used elsewhere within libssh2, but
+  until then it is kept static and in this source file.
+*/
+
+static unsigned
+shell_quotearg(const char *path, unsigned char *buf,
+               unsigned bufsize)
+{
+    const char *src;
+    unsigned char *dst, *endp;
+
+    /*
+     * Processing States:
+     *  UQSTRING:       unquoted string: ... -- used for quoting exclamation
+     *                  marks. This is the initial state
+     *  SQSTRING:       single-quoted-string: '... -- any character may follow
+     *  QSTRING:        quoted string: "... -- only apostrophes may follow
+     */
+    enum { UQSTRING, SQSTRING, QSTRING } state = UQSTRING;
+
+    endp = &buf[bufsize];
+    src = path;
+    dst = buf;
+    while(*src && dst < endp - 1) {
+
+        switch(*src) {
+            /*
+             * Special handling for apostrophe.
+             * An apostrophe is always written in quotation marks, e.g.
+             * ' -> "'".
+             */
+
+        case '\'':
+            switch(state) {
+            case UQSTRING:      /* Unquoted string */
+                if(dst + 1 >= endp)
+                    return 0;
+                *dst++ = '"';
+                break;
+            case QSTRING:       /* Continue quoted string */
+                break;
+            case SQSTRING:      /* Close single quoted string */
+                if(dst + 2 >= endp)
+                    return 0;
+                *dst++ = '\'';
+                *dst++ = '"';
+                break;
+            default:
+                break;
+            }
+            state = QSTRING;
+            break;
+
+            /*
+             * Special handling for exclamation marks. CSH interprets
+             * exclamation marks even when quoted with apostrophes. We convert
+             * it to the plain string \!, because both Bourne Shell and CSH
+             * interpret that as a verbatim exclamation mark.
+             */
+
+        case '!':
+            switch(state) {
+            case UQSTRING:
+                if(dst + 1 >= endp)
+                    return 0;
+                *dst++ = '\\';
+                break;
+            case QSTRING:
+                if(dst + 2 >= endp)
+                    return 0;
+                *dst++ = '"';           /* Closing quotation mark */
+                *dst++ = '\\';
+                break;
+            case SQSTRING:              /* Close single quoted string */
+                if(dst + 2 >= endp)
+                    return 0;
+                *dst++ = '\'';
+                *dst++ = '\\';
+                break;
+            default:
+                break;
+            }
+            state = UQSTRING;
+            break;
+
+            /*
+             * Ordinary character: prefer single-quoted string
+             */
+
+        default:
+            switch(state) {
+            case UQSTRING:
+                if(dst + 1 >= endp)
+                    return 0;
+                *dst++ = '\'';
+                break;
+            case QSTRING:
+                if(dst + 2 >= endp)
+                    return 0;
+                *dst++ = '"';           /* Closing quotation mark */
+                *dst++ = '\'';
+                break;
+            case SQSTRING:      /* Continue single quoted string */
+                break;
+            default:
+                break;
+            }
+            state = SQSTRING;   /* Start single-quoted string */
+            break;
+        }
+
+        if(dst + 1 >= endp)
+            return 0;
+        *dst++ = *src++;
+    }
+
+    switch(state) {
+    case UQSTRING:
+        break;
+    case QSTRING:           /* Close quoted string */
+        if(dst + 1 >= endp)
+            return 0;
+        *dst++ = '"';
+        break;
+    case SQSTRING:          /* Close single quoted string */
+        if(dst + 1 >= endp)
+            return 0;
+        *dst++ = '\'';
+        break;
+    default:
+        break;
+    }
+
+    if(dst + 1 >= endp)
+        return 0;
+    *dst = '\0';
+
+    /* The result cannot be larger than 3 * strlen(path) + 2 */
+    /* assert((dst - buf) <= (3 * (src - path) + 2)); */
+
+    return dst - buf;
+}
+
+/*
+ * scp_recv
+ *
+ * Open a channel and request a remote file via SCP
+ *
+ */
+static LIBSSH2_CHANNEL *
+scp_recv(LIBSSH2_SESSION * session, const char *path, libssh2_struct_stat * sb)
+{
+    int cmd_len;
+    int rc;
+    int tmp_err_code;
+    const char *tmp_err_msg;
+
+    if(session->scpRecv_state == libssh2_NB_state_idle) {
+        session->scpRecv_mode = 0;
+        session->scpRecv_size = 0;
+        session->scpRecv_mtime = 0;
+        session->scpRecv_atime = 0;
+
+        session->scpRecv_command_len =
+            _libssh2_shell_quotedsize(path) + sizeof("scp -f ") + (sb?1:0);
+
+        session->scpRecv_command =
+            LIBSSH2_ALLOC(session, session->scpRecv_command_len);
+
+        if(!session->scpRecv_command) {
+            _libssh2_error(session, LIBSSH2_ERROR_ALLOC,
+                           "Unable to allocate a command buffer for "
+                           "SCP session");
+            return NULL;
+        }
+
+        snprintf((char *)session->scpRecv_command,
+                 session->scpRecv_command_len,
+                 "scp -%sf ", sb?"p":"");
+
+        cmd_len = strlen((char *)session->scpRecv_command);
+        cmd_len += shell_quotearg(path,
+                                  &session->scpRecv_command[cmd_len],
+                                  session->scpRecv_command_len - cmd_len);
+
+        /* the command to exec should _not_ be NUL-terminated */
+        session->scpRecv_command_len = cmd_len;
+
+        _libssh2_debug(session, LIBSSH2_TRACE_SCP,
+                       "Opening channel for SCP receive");
+
+        session->scpRecv_state = libssh2_NB_state_created;
+    }
+
+    if(session->scpRecv_state == libssh2_NB_state_created) {
+        /* Allocate a channel */
+        session->scpRecv_channel =
+            _libssh2_channel_open(session, "session",
+                                  sizeof("session") - 1,
+                                  LIBSSH2_CHANNEL_WINDOW_DEFAULT,
+                                  LIBSSH2_CHANNEL_PACKET_DEFAULT, NULL,
+                                  0);
+        if(!session->scpRecv_channel) {
+            if(libssh2_session_last_errno(session) !=
+                LIBSSH2_ERROR_EAGAIN) {
+                LIBSSH2_FREE(session, session->scpRecv_command);
+                session->scpRecv_command = NULL;
+                session->scpRecv_state = libssh2_NB_state_idle;
+            }
+            else {
+                _libssh2_error(session, LIBSSH2_ERROR_EAGAIN,
+                               "Would block starting up channel");
+            }
+            return NULL;
+        }
+
+        session->scpRecv_state = libssh2_NB_state_sent;
+    }
+
+    if(session->scpRecv_state == libssh2_NB_state_sent) {
+        /* Request SCP for the desired file */
+        rc = _libssh2_channel_process_startup(session->scpRecv_channel, "exec",
+                                              sizeof("exec") - 1,
+                                              (char *)session->scpRecv_command,
+                                              session->scpRecv_command_len);
+        if(rc == LIBSSH2_ERROR_EAGAIN) {
+            _libssh2_error(session, LIBSSH2_ERROR_EAGAIN,
+                           "Would block requesting SCP startup");
+            return NULL;
+        }
+        else if(rc) {
+            LIBSSH2_FREE(session, session->scpRecv_command);
+            session->scpRecv_command = NULL;
+            goto scp_recv_error;
+        }
+        LIBSSH2_FREE(session, session->scpRecv_command);
+        session->scpRecv_command = NULL;
+
+        _libssh2_debug(session, LIBSSH2_TRACE_SCP, "Sending initial wakeup");
+        /* SCP ACK */
+        session->scpRecv_response[0] = '\0';
+
+        session->scpRecv_state = libssh2_NB_state_sent1;
+    }
+
+    if(session->scpRecv_state == libssh2_NB_state_sent1) {
+        rc = _libssh2_channel_write(session->scpRecv_channel, 0,
+                                    session->scpRecv_response, 1);
+        if(rc == LIBSSH2_ERROR_EAGAIN) {
+            _libssh2_error(session, LIBSSH2_ERROR_EAGAIN,
+                           "Would block sending initial wakeup");
+            return NULL;
+        }
+        else if(rc != 1) {
+            goto scp_recv_error;
+        }
+
+        /* Parse SCP response */
+        session->scpRecv_response_len = 0;
+
+        session->scpRecv_state = libssh2_NB_state_sent2;
+    }
+
+    if((session->scpRecv_state == libssh2_NB_state_sent2)
+        || (session->scpRecv_state == libssh2_NB_state_sent3)) {
+        while(sb && (session->scpRecv_response_len <
+                      LIBSSH2_SCP_RESPONSE_BUFLEN)) {
+            unsigned char *s, *p;
+
+            if(session->scpRecv_state == libssh2_NB_state_sent2) {
+                rc = _libssh2_channel_read(session->scpRecv_channel, 0,
+                                           (char *) session->
+                                           scpRecv_response +
+                                           session->scpRecv_response_len, 1);
+                if(rc == LIBSSH2_ERROR_EAGAIN) {
+                    _libssh2_error(session, LIBSSH2_ERROR_EAGAIN,
+                                   "Would block waiting for SCP response");
+                    return NULL;
+                }
+                else if(rc < 0) {
+                    /* error, give up */
+                    _libssh2_error(session, rc, "Failed reading SCP response");
+                    goto scp_recv_error;
+                }
+                else if(rc == 0)
+                    goto scp_recv_empty_channel;
+
+                session->scpRecv_response_len++;
+
+                if(session->scpRecv_response[0] != 'T') {
+                    size_t err_len;
+                    char *err_msg;
+
+                    /* there can be
+                       01 for warnings
+                       02 for errors
+
+                       The following string MUST be newline terminated
+                    */
+                    err_len =
+                        _libssh2_channel_packet_data_len(session->
+                                                         scpRecv_channel, 0);
+                    err_msg = LIBSSH2_ALLOC(session, err_len + 1);
+                    if(!err_msg) {
+                        _libssh2_error(session, LIBSSH2_ERROR_ALLOC,
+                                       "Failed to get memory ");
+                        goto scp_recv_error;
+                    }
+
+                    /* Read the remote error message */
+                    (void)_libssh2_channel_read(session->scpRecv_channel, 0,
+                                                err_msg, err_len);
+                    /* If it failed for any reason, we ignore it anyway. */
+
+                    /* zero terminate the error */
+                    err_msg[err_len] = 0;
+
+                    _libssh2_debug(session, LIBSSH2_TRACE_SCP,
+                                   "got %02x %s", session->scpRecv_response[0],
+                                   err_msg);
+
+                    _libssh2_error(session, LIBSSH2_ERROR_SCP_PROTOCOL,
+                                   "Failed to recv file");
+
+                    LIBSSH2_FREE(session, err_msg);
+                    goto scp_recv_error;
+                }
+
+                if((session->scpRecv_response_len > 1) &&
+                    ((session->
+                      scpRecv_response[session->scpRecv_response_len - 1] <
+                      '0')
+                     || (session->
+                         scpRecv_response[session->scpRecv_response_len - 1] >
+                         '9'))
+                    && (session->
+                        scpRecv_response[session->scpRecv_response_len - 1] !=
+                        ' ')
+                    && (session->
+                        scpRecv_response[session->scpRecv_response_len - 1] !=
+                        '\r')
+                    && (session->
+                        scpRecv_response[session->scpRecv_response_len - 1] !=
+                        '\n')) {
+                    _libssh2_error(session, LIBSSH2_ERROR_SCP_PROTOCOL,
+                                   "Invalid data in SCP response");
+                    goto scp_recv_error;
+                }
+
+                if((session->scpRecv_response_len < 9)
+                    || (session->
+                        scpRecv_response[session->scpRecv_response_len - 1] !=
+                        '\n')) {
+                    if(session->scpRecv_response_len ==
+                        LIBSSH2_SCP_RESPONSE_BUFLEN) {
+                        /* You had your chance */
+                        _libssh2_error(session, LIBSSH2_ERROR_SCP_PROTOCOL,
+                                       "Unterminated response from "
+                                       "SCP server");
+                        goto scp_recv_error;
+                    }
+                    /* Way too short to be an SCP response, or not done yet,
+                       short circuit */
+                    continue;
+                }
+
+                /* We're guaranteed not to go under response_len == 0 by the
+                   logic above */
+                while((session->
+                        scpRecv_response[session->scpRecv_response_len - 1] ==
+                        '\r')
+                       || (session->
+                           scpRecv_response[session->scpRecv_response_len -
+                                            1] == '\n'))
+                    session->scpRecv_response_len--;
+                session->scpRecv_response[session->scpRecv_response_len] =
+                    '\0';
+
+                if(session->scpRecv_response_len < 8) {
+                    /* EOL came too soon */
+                    _libssh2_error(session, LIBSSH2_ERROR_SCP_PROTOCOL,
+                                   "Invalid response from SCP server, "
+                                   "too short");
+                    goto scp_recv_error;
+                }
+
+                s = session->scpRecv_response + 1;
+
+                p = (unsigned char *) strchr((char *) s, ' ');
+                if(!p || ((p - s) <= 0)) {
+                    /* No spaces or space in the wrong spot */
+                    _libssh2_error(session, LIBSSH2_ERROR_SCP_PROTOCOL,
+                                   "Invalid response from SCP server, "
+                                   "malformed mtime");
+                    goto scp_recv_error;
+                }
+
+                *(p++) = '\0';
+                /* Make sure we don't get fooled by leftover values */
+                session->scpRecv_mtime = strtol((char *) s, NULL, 10);
+
+                s = (unsigned char *) strchr((char *) p, ' ');
+                if(!s || ((s - p) <= 0)) {
+                    /* No spaces or space in the wrong spot */
+                    _libssh2_error(session, LIBSSH2_ERROR_SCP_PROTOCOL,
+                                   "Invalid response from SCP server, "
+                                   "malformed mtime.usec");
+                    goto scp_recv_error;
+                }
+
+                /* Ignore mtime.usec */
+                s++;
+                p = (unsigned char *) strchr((char *) s, ' ');
+                if(!p || ((p - s) <= 0)) {
+                    /* No spaces or space in the wrong spot */
+                    _libssh2_error(session, LIBSSH2_ERROR_SCP_PROTOCOL,
+                                   "Invalid response from SCP server, "
+                                   "too short or malformed");
+                    goto scp_recv_error;
+                }
+
+                *p = '\0';
+                /* Make sure we don't get fooled by leftover values */
+                session->scpRecv_atime = strtol((char *) s, NULL, 10);
+
+                /* SCP ACK */
+                session->scpRecv_response[0] = '\0';
+
+                session->scpRecv_state = libssh2_NB_state_sent3;
+            }
+
+            if(session->scpRecv_state == libssh2_NB_state_sent3) {
+                rc = _libssh2_channel_write(session->scpRecv_channel, 0,
+                                            session->scpRecv_response, 1);
+                if(rc == LIBSSH2_ERROR_EAGAIN) {
+                    _libssh2_error(session, LIBSSH2_ERROR_EAGAIN,
+                                   "Would block waiting to send SCP ACK");
+                    return NULL;
+                }
+                else if(rc != 1) {
+                    goto scp_recv_error;
+                }
+
+                _libssh2_debug(session, LIBSSH2_TRACE_SCP,
+                               "mtime = %ld, atime = %ld",
+                               session->scpRecv_mtime, session->scpRecv_atime);
+
+                /* We *should* check that atime.usec is valid, but why let
+                   that stop use? */
+                break;
+            }
+        }
+
+        session->scpRecv_state = libssh2_NB_state_sent4;
+    }
+
+    if(session->scpRecv_state == libssh2_NB_state_sent4) {
+        session->scpRecv_response_len = 0;
+
+        session->scpRecv_state = libssh2_NB_state_sent5;
+    }
+
+    if((session->scpRecv_state == libssh2_NB_state_sent5)
+        || (session->scpRecv_state == libssh2_NB_state_sent6)) {
+        while(session->scpRecv_response_len < LIBSSH2_SCP_RESPONSE_BUFLEN) {
+            char *s, *p, *e = NULL;
+
+            if(session->scpRecv_state == libssh2_NB_state_sent5) {
+                rc = _libssh2_channel_read(session->scpRecv_channel, 0,
+                                           (char *) session->
+                                           scpRecv_response +
+                                           session->scpRecv_response_len, 1);
+                if(rc == LIBSSH2_ERROR_EAGAIN) {
+                    _libssh2_error(session, LIBSSH2_ERROR_EAGAIN,
+                                   "Would block waiting for SCP response");
+                    return NULL;
+                }
+                else if(rc < 0) {
+                    /* error, bail out*/
+                    _libssh2_error(session, rc, "Failed reading SCP response");
+                    goto scp_recv_error;
+                }
+                else if(rc == 0)
+                    goto scp_recv_empty_channel;
+
+                session->scpRecv_response_len++;
+
+                if(session->scpRecv_response[0] != 'C') {
+                    _libssh2_error(session, LIBSSH2_ERROR_SCP_PROTOCOL,
+                                   "Invalid response from SCP server");
+                    goto scp_recv_error;
+                }
+
+                if((session->scpRecv_response_len > 1) &&
+                    (session->
+                     scpRecv_response[session->scpRecv_response_len - 1] !=
+                     '\r')
+                    && (session->
+                        scpRecv_response[session->scpRecv_response_len - 1] !=
+                        '\n')
+                    &&
+                    (session->
+                     scpRecv_response[session->scpRecv_response_len - 1]
+                     < 32)) {
+                    _libssh2_error(session, LIBSSH2_ERROR_SCP_PROTOCOL,
+                                   "Invalid data in SCP response");
+                    goto scp_recv_error;
+                }
+
+                if((session->scpRecv_response_len < 7)
+                    || (session->
+                        scpRecv_response[session->scpRecv_response_len - 1] !=
+                        '\n')) {
+                    if(session->scpRecv_response_len ==
+                        LIBSSH2_SCP_RESPONSE_BUFLEN) {
+                        /* You had your chance */
+                        _libssh2_error(session, LIBSSH2_ERROR_SCP_PROTOCOL,
+                                       "Unterminated response "
+                                       "from SCP server");
+                        goto scp_recv_error;
+                    }
+                    /* Way too short to be an SCP response, or not done yet,
+                       short circuit */
+                    continue;
+                }
+
+                /* We're guaranteed not to go under response_len == 0 by the
+                   logic above */
+                while((session->
+                        scpRecv_response[session->scpRecv_response_len - 1] ==
+                        '\r')
+                       || (session->
+                           scpRecv_response[session->scpRecv_response_len -
+                                            1] == '\n')) {
+                    session->scpRecv_response_len--;
+                }
+                session->scpRecv_response[session->scpRecv_response_len] =
+                    '\0';
+
+                if(session->scpRecv_response_len < 6) {
+                    /* EOL came too soon */
+                    _libssh2_error(session, LIBSSH2_ERROR_SCP_PROTOCOL,
+                                   "Invalid response from SCP server, "
+                                   "too short");
+                    goto scp_recv_error;
+                }
+
+                s = (char *) session->scpRecv_response + 1;
+
+                p = strchr(s, ' ');
+                if(!p || ((p - s) <= 0)) {
+                    /* No spaces or space in the wrong spot */
+                    _libssh2_error(session, LIBSSH2_ERROR_SCP_PROTOCOL,
+                                   "Invalid response from SCP server, "
+                                   "malformed mode");
+                    goto scp_recv_error;
+                }
+
+                *(p++) = '\0';
+                /* Make sure we don't get fooled by leftover values */
+
+                session->scpRecv_mode = strtol(s, &e, 8);
+                if(e && *e) {
+                    _libssh2_error(session, LIBSSH2_ERROR_SCP_PROTOCOL,
+                                   "Invalid response from SCP server, "
+                                   "invalid mode");
+                    goto scp_recv_error;
+                }
+
+                s = strchr(p, ' ');
+                if(!s || ((s - p) <= 0)) {
+                    /* No spaces or space in the wrong spot */
+                    _libssh2_error(session, LIBSSH2_ERROR_SCP_PROTOCOL,
+                                   "Invalid response from SCP server, "
+                                   "too short or malformed");
+                    goto scp_recv_error;
+                }
+
+                *s = '\0';
+                /* Make sure we don't get fooled by leftover values */
+                session->scpRecv_size = scpsize_strtol(p, &e, 10);
+                if(e && *e) {
+                    _libssh2_error(session, LIBSSH2_ERROR_SCP_PROTOCOL,
+                                   "Invalid response from SCP server, "
+                                   "invalid size");
+                    goto scp_recv_error;
+                }
+
+                /* SCP ACK */
+                session->scpRecv_response[0] = '\0';
+
+                session->scpRecv_state = libssh2_NB_state_sent6;
+            }
+
+            if(session->scpRecv_state == libssh2_NB_state_sent6) {
+                rc = _libssh2_channel_write(session->scpRecv_channel, 0,
+                                            session->scpRecv_response, 1);
+                if(rc == LIBSSH2_ERROR_EAGAIN) {
+                    _libssh2_error(session, LIBSSH2_ERROR_EAGAIN,
+                                   "Would block sending SCP ACK");
+                    return NULL;
+                }
+                else if(rc != 1) {
+                    goto scp_recv_error;
+                }
+                _libssh2_debug(session, LIBSSH2_TRACE_SCP,
+                               "mode = 0%lo size = %ld", session->scpRecv_mode,
+                               session->scpRecv_size);
+
+                /* We *should* check that basename is valid, but why let that
+                   stop us? */
+                break;
+            }
+        }
+
+        session->scpRecv_state = libssh2_NB_state_sent7;
+    }
+
+    if(sb) {
+        memset(sb, 0, sizeof(libssh2_struct_stat));
+
+        sb->st_mtime = session->scpRecv_mtime;
+        sb->st_atime = session->scpRecv_atime;
+        sb->st_size = session->scpRecv_size;
+        sb->st_mode = (unsigned short)session->scpRecv_mode;
+    }
+
+    session->scpRecv_state = libssh2_NB_state_idle;
+    return session->scpRecv_channel;
+
+  scp_recv_empty_channel:
+    /* the code only jumps here as a result of a zero read from channel_read()
+       so we check EOF status to avoid getting stuck in a loop */
+    if(libssh2_channel_eof(session->scpRecv_channel))
+        _libssh2_error(session, LIBSSH2_ERROR_SCP_PROTOCOL,
+                       "Unexpected channel close");
+    else
+        return session->scpRecv_channel;
+    /* fall-through */
+  scp_recv_error:
+    tmp_err_code = session->err_code;
+    tmp_err_msg = session->err_msg;
+    while(libssh2_channel_free(session->scpRecv_channel) ==
+           LIBSSH2_ERROR_EAGAIN);
+    session->err_code = tmp_err_code;
+    session->err_msg = tmp_err_msg;
+    session->scpRecv_channel = NULL;
+    session->scpRecv_state = libssh2_NB_state_idle;
+    return NULL;
+}
+
+/*
+ * libssh2_scp_recv
+ *
+ * DEPRECATED
+ *
+ * Open a channel and request a remote file via SCP.  This receives files
+ * larger than 2 GB, but is unable to report the proper size on platforms
+ * where the st_size member of struct stat is limited to 2 GB (e.g. windows).
+ *
+ */
+LIBSSH2_API LIBSSH2_CHANNEL *
+libssh2_scp_recv(LIBSSH2_SESSION *session, const char *path, struct stat * sb)
+{
+    LIBSSH2_CHANNEL *ptr;
+
+    /* scp_recv uses libssh2_struct_stat, so pass one if the caller gave us a
+       struct to populate... */
+    libssh2_struct_stat sb_intl;
+    libssh2_struct_stat *sb_ptr;
+    memset(&sb_intl, 0, sizeof(sb_intl));
+    sb_ptr = sb ? &sb_intl : NULL;
+
+    BLOCK_ADJUST_ERRNO(ptr, session, scp_recv(session, path, sb_ptr));
+
+    /* ...and populate the caller's with as much info as fits. */
+    if(sb) {
+        memset(sb, 0, sizeof(struct stat));
+
+        sb->st_mtime = sb_intl.st_mtime;
+        sb->st_atime = sb_intl.st_atime;
+        sb->st_size = (off_t)sb_intl.st_size;
+        sb->st_mode = sb_intl.st_mode;
+    }
+
+    return ptr;
+}
+
+/*
+ * libssh2_scp_recv2
+ *
+ * Open a channel and request a remote file via SCP.  This supports files > 2GB
+ * on platforms that support it.
+ *
+ */
+LIBSSH2_API LIBSSH2_CHANNEL *
+libssh2_scp_recv2(LIBSSH2_SESSION *session, const char *path,
+                  libssh2_struct_stat *sb)
+{
+    LIBSSH2_CHANNEL *ptr;
+    BLOCK_ADJUST_ERRNO(ptr, session, scp_recv(session, path, sb));
+    return ptr;
+}
+
+/*
+ * scp_send()
+ *
+ * Send a file using SCP
+ *
+ */
+static LIBSSH2_CHANNEL *
+scp_send(LIBSSH2_SESSION * session, const char *path, int mode,
+         libssh2_int64_t size, time_t mtime, time_t atime)
+{
+    int cmd_len;
+    int rc;
+    int tmp_err_code;
+    const char *tmp_err_msg;
+
+    if(session->scpSend_state == libssh2_NB_state_idle) {
+        session->scpSend_command_len =
+            _libssh2_shell_quotedsize(path) + sizeof("scp -t ") +
+            ((mtime || atime)?1:0);
+
+        session->scpSend_command =
+            LIBSSH2_ALLOC(session, session->scpSend_command_len);
+
+        if(!session->scpSend_command) {
+            _libssh2_error(session, LIBSSH2_ERROR_ALLOC,
+                           "Unable to allocate a command buffer for "
+                           "SCP session");
+            return NULL;
+        }
+
+        snprintf((char *)session->scpSend_command,
+                 session->scpSend_command_len,
+                 "scp -%st ", (mtime || atime)?"p":"");
+
+        cmd_len = strlen((char *)session->scpSend_command);
+        cmd_len += shell_quotearg(path,
+                                  &session->scpSend_command[cmd_len],
+                                  session->scpSend_command_len - cmd_len);
+
+        /* the command to exec should _not_ be NUL-terminated */
+        session->scpSend_command_len = cmd_len;
+
+        _libssh2_debug(session, LIBSSH2_TRACE_SCP,
+                       "Opening channel for SCP send");
+        /* Allocate a channel */
+
+        session->scpSend_state = libssh2_NB_state_created;
+    }
+
+    if(session->scpSend_state == libssh2_NB_state_created) {
+        session->scpSend_channel =
+            _libssh2_channel_open(session, "session", sizeof("session") - 1,
+                                  LIBSSH2_CHANNEL_WINDOW_DEFAULT,
+                                  LIBSSH2_CHANNEL_PACKET_DEFAULT, NULL, 0);
+        if(!session->scpSend_channel) {
+            if(libssh2_session_last_errno(session) != LIBSSH2_ERROR_EAGAIN) {
+                /* previous call set libssh2_session_last_error(), pass it
+                   through */
+                LIBSSH2_FREE(session, session->scpSend_command);
+                session->scpSend_command = NULL;
+                session->scpSend_state = libssh2_NB_state_idle;
+            }
+            else {
+                _libssh2_error(session, LIBSSH2_ERROR_EAGAIN,
+                               "Would block starting up channel");
+            }
+            return NULL;
+        }
+
+        session->scpSend_state = libssh2_NB_state_sent;
+    }
+
+    if(session->scpSend_state == libssh2_NB_state_sent) {
+        /* Request SCP for the desired file */
+        rc = _libssh2_channel_process_startup(session->scpSend_channel, "exec",
+                                              sizeof("exec") - 1,
+                                              (char *)session->scpSend_command,
+                                              session->scpSend_command_len);
+        if(rc == LIBSSH2_ERROR_EAGAIN) {
+            _libssh2_error(session, LIBSSH2_ERROR_EAGAIN,
+                           "Would block requesting SCP startup");
+            return NULL;
+        }
+        else if(rc) {
+            /* previous call set libssh2_session_last_error(), pass it
+               through */
+            LIBSSH2_FREE(session, session->scpSend_command);
+            session->scpSend_command = NULL;
+            _libssh2_error(session, LIBSSH2_ERROR_SCP_PROTOCOL,
+                           "Unknown error while getting error string");
+            goto scp_send_error;
+        }
+        LIBSSH2_FREE(session, session->scpSend_command);
+        session->scpSend_command = NULL;
+
+        session->scpSend_state = libssh2_NB_state_sent1;
+    }
+
+    if(session->scpSend_state == libssh2_NB_state_sent1) {
+        /* Wait for ACK */
+        rc = _libssh2_channel_read(session->scpSend_channel, 0,
+                                   (char *) session->scpSend_response, 1);
+        if(rc == LIBSSH2_ERROR_EAGAIN) {
+            _libssh2_error(session, LIBSSH2_ERROR_EAGAIN,
+                           "Would block waiting for response from remote");
+            return NULL;
+        }
+        else if(rc < 0) {
+            _libssh2_error(session, rc, "SCP failure");
+            goto scp_send_error;
+        }
+        else if(!rc)
+            /* remain in the same state */
+            goto scp_send_empty_channel;
+        else if(session->scpSend_response[0] != 0) {
+            _libssh2_error(session, LIBSSH2_ERROR_SCP_PROTOCOL,
+                           "Invalid ACK response from remote");
+            goto scp_send_error;
+        }
+        if(mtime || atime) {
+            /* Send mtime and atime to be used for file */
+            session->scpSend_response_len =
+                snprintf((char *) session->scpSend_response,
+                         LIBSSH2_SCP_RESPONSE_BUFLEN, "T%ld 0 %ld 0\n",
+                         (long)mtime, (long)atime);
+            _libssh2_debug(session, LIBSSH2_TRACE_SCP, "Sent %s",
+                           session->scpSend_response);
+        }
+
+        session->scpSend_state = libssh2_NB_state_sent2;
+    }
+
+    /* Send mtime and atime to be used for file */
+    if(mtime || atime) {
+        if(session->scpSend_state == libssh2_NB_state_sent2) {
+            rc = _libssh2_channel_write(session->scpSend_channel, 0,
+                                        session->scpSend_response,
+                                        session->scpSend_response_len);
+            if(rc == LIBSSH2_ERROR_EAGAIN) {
+                _libssh2_error(session, LIBSSH2_ERROR_EAGAIN,
+                               "Would block sending time data for SCP file");
+                return NULL;
+            }
+            else if(rc != (int)session->scpSend_response_len) {
+                _libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND,
+                               "Unable to send time data for SCP file");
+                goto scp_send_error;
+            }
+
+            session->scpSend_state = libssh2_NB_state_sent3;
+        }
+
+        if(session->scpSend_state == libssh2_NB_state_sent3) {
+            /* Wait for ACK */
+            rc = _libssh2_channel_read(session->scpSend_channel, 0,
+                                       (char *) session->scpSend_response, 1);
+            if(rc == LIBSSH2_ERROR_EAGAIN) {
+                _libssh2_error(session, LIBSSH2_ERROR_EAGAIN,
+                               "Would block waiting for response");
+                return NULL;
+            }
+            else if(rc < 0) {
+                _libssh2_error(session, rc, "SCP failure");
+                goto scp_send_error;
+            }
+            else if(!rc)
+                /* remain in the same state */
+                goto scp_send_empty_channel;
+            else if(session->scpSend_response[0] != 0) {
+                _libssh2_error(session, LIBSSH2_ERROR_SCP_PROTOCOL,
+                               "Invalid SCP ACK response");
+                goto scp_send_error;
+            }
+
+            session->scpSend_state = libssh2_NB_state_sent4;
+        }
+    }
+    else {
+        if(session->scpSend_state == libssh2_NB_state_sent2) {
+            session->scpSend_state = libssh2_NB_state_sent4;
+        }
+    }
+
+    if(session->scpSend_state == libssh2_NB_state_sent4) {
+        /* Send mode, size, and basename */
+        const char *base = strrchr(path, '/');
+        if(base)
+            base++;
+        else
+            base = path;
+
+        session->scpSend_response_len =
+            snprintf((char *) session->scpSend_response,
+                     LIBSSH2_SCP_RESPONSE_BUFLEN, "C0%o %"
+                     LIBSSH2_INT64_T_FORMAT " %s\n", mode,
+                     size, base);
+        _libssh2_debug(session, LIBSSH2_TRACE_SCP, "Sent %s",
+                       session->scpSend_response);
+
+        session->scpSend_state = libssh2_NB_state_sent5;
+    }
+
+    if(session->scpSend_state == libssh2_NB_state_sent5) {
+        rc = _libssh2_channel_write(session->scpSend_channel, 0,
+                                    session->scpSend_response,
+                                    session->scpSend_response_len);
+        if(rc == LIBSSH2_ERROR_EAGAIN) {
+            _libssh2_error(session, LIBSSH2_ERROR_EAGAIN,
+                           "Would block send core file data for SCP file");
+            return NULL;
+        }
+        else if(rc != (int)session->scpSend_response_len) {
+            _libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND,
+                           "Unable to send core file data for SCP file");
+            goto scp_send_error;
+        }
+
+        session->scpSend_state = libssh2_NB_state_sent6;
+    }
+
+    if(session->scpSend_state == libssh2_NB_state_sent6) {
+        /* Wait for ACK */
+        rc = _libssh2_channel_read(session->scpSend_channel, 0,
+                                   (char *) session->scpSend_response, 1);
+        if(rc == LIBSSH2_ERROR_EAGAIN) {
+            _libssh2_error(session, LIBSSH2_ERROR_EAGAIN,
+                           "Would block waiting for response");
+            return NULL;
+        }
+        else if(rc < 0) {
+            _libssh2_error(session, LIBSSH2_ERROR_SCP_PROTOCOL,
+                           "Invalid ACK response from remote");
+            goto scp_send_error;
+        }
+        else if(rc == 0)
+            goto scp_send_empty_channel;
+
+        else if(session->scpSend_response[0] != 0) {
+            size_t err_len;
+            char *err_msg;
+
+            err_len =
+                _libssh2_channel_packet_data_len(session->scpSend_channel, 0);
+            err_msg = LIBSSH2_ALLOC(session, err_len + 1);
+            if(!err_msg) {
+                _libssh2_error(session, LIBSSH2_ERROR_ALLOC,
+                               "failed to get memory");
+                goto scp_send_error;
+            }
+
+            /* Read the remote error message */
+            rc = _libssh2_channel_read(session->scpSend_channel, 0,
+                                       err_msg, err_len);
+            if(rc > 0) {
+                err_msg[err_len] = 0;
+                _libssh2_debug(session, LIBSSH2_TRACE_SCP,
+                               "got %02x %s", session->scpSend_response[0],
+                               err_msg);
+            }
+            LIBSSH2_FREE(session, err_msg);
+            _libssh2_error(session, LIBSSH2_ERROR_SCP_PROTOCOL,
+                           "failed to send file");
+            goto scp_send_error;
+        }
+    }
+
+    session->scpSend_state = libssh2_NB_state_idle;
+    return session->scpSend_channel;
+
+  scp_send_empty_channel:
+    /* the code only jumps here as a result of a zero read from channel_read()
+       so we check EOF status to avoid getting stuck in a loop */
+    if(libssh2_channel_eof(session->scpSend_channel)) {
+        _libssh2_error(session, LIBSSH2_ERROR_SCP_PROTOCOL,
+                       "Unexpected channel close");
+    }
+    else
+        return session->scpSend_channel;
+    /* fall-through */
+  scp_send_error:
+    tmp_err_code = session->err_code;
+    tmp_err_msg = session->err_msg;
+    while(libssh2_channel_free(session->scpSend_channel) ==
+          LIBSSH2_ERROR_EAGAIN);
+    session->err_code = tmp_err_code;
+    session->err_msg = tmp_err_msg;
+    session->scpSend_channel = NULL;
+    session->scpSend_state = libssh2_NB_state_idle;
+    return NULL;
+}
+
+/*
+ * libssh2_scp_send_ex
+ *
+ * Send a file using SCP. Old API.
+ */
+LIBSSH2_API LIBSSH2_CHANNEL *
+libssh2_scp_send_ex(LIBSSH2_SESSION *session, const char *path, int mode,
+                    size_t size, long mtime, long atime)
+{
+    LIBSSH2_CHANNEL *ptr;
+    BLOCK_ADJUST_ERRNO(ptr, session,
+                       scp_send(session, path, mode, size,
+                                (time_t)mtime, (time_t)atime));
+    return ptr;
+}
+
+/*
+ * libssh2_scp_send64
+ *
+ * Send a file using SCP
+ */
+LIBSSH2_API LIBSSH2_CHANNEL *
+libssh2_scp_send64(LIBSSH2_SESSION *session, const char *path, int mode,
+                   libssh2_int64_t size, time_t mtime, time_t atime)
+{
+    LIBSSH2_CHANNEL *ptr;
+    BLOCK_ADJUST_ERRNO(ptr, session,
+                       scp_send(session, path, mode, size, mtime, atime));
+    return ptr;
+}

+ 1832 - 0
libssh2/libssh2/src/session.c

@@ -0,0 +1,1832 @@
+/* Copyright (c) 2004-2007 Sara Golemon <sarag@libssh2.org>
+ * Copyright (c) 2009-2015 by Daniel Stenberg
+ * Copyright (c) 2010 Simon Josefsson <simon@josefsson.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms,
+ * with or without modification, are permitted provided
+ * that the following conditions are met:
+ *
+ *   Redistributions of source code must retain the above
+ *   copyright notice, this list of conditions and the
+ *   following disclaimer.
+ *
+ *   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.
+ *
+ *   Neither the name of the copyright holder nor the names
+ *   of any other contributors may be used to endorse or
+ *   promote products derived from this software without
+ *   specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+ * CONTRIBUTORS "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 COPYRIGHT OWNER OR
+ * CONTRIBUTORS 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 "libssh2_priv.h"
+#include <errno.h>
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#include <stdlib.h>
+#include <fcntl.h>
+
+#ifdef HAVE_GETTIMEOFDAY
+#include <sys/time.h>
+#endif
+#ifdef HAVE_ALLOCA_H
+#include <alloca.h>
+#endif
+
+#include "transport.h"
+#include "session.h"
+#include "channel.h"
+#include "mac.h"
+#include "misc.h"
+
+/* libssh2_default_alloc
+ */
+static
+LIBSSH2_ALLOC_FUNC(libssh2_default_alloc)
+{
+    (void) abstract;
+    return malloc(count);
+}
+
+/* libssh2_default_free
+ */
+static
+LIBSSH2_FREE_FUNC(libssh2_default_free)
+{
+    (void) abstract;
+    free(ptr);
+}
+
+/* libssh2_default_realloc
+ */
+static
+LIBSSH2_REALLOC_FUNC(libssh2_default_realloc)
+{
+    (void) abstract;
+    return realloc(ptr, count);
+}
+
+/*
+ * banner_receive
+ *
+ * Wait for a hello from the remote host
+ * Allocate a buffer and store the banner in session->remote.banner
+ * Returns: 0 on success, LIBSSH2_ERROR_EAGAIN if read would block, negative
+ * on failure
+ */
+static int
+banner_receive(LIBSSH2_SESSION * session)
+{
+    int ret;
+    int banner_len;
+
+    if(session->banner_TxRx_state == libssh2_NB_state_idle) {
+        banner_len = 0;
+
+        session->banner_TxRx_state = libssh2_NB_state_created;
+    }
+    else {
+        banner_len = session->banner_TxRx_total_send;
+    }
+
+    while((banner_len < (int) sizeof(session->banner_TxRx_banner)) &&
+           ((banner_len == 0)
+            || (session->banner_TxRx_banner[banner_len - 1] != '\n'))) {
+        char c = '\0';
+
+        /* no incoming block yet! */
+        session->socket_block_directions &= ~LIBSSH2_SESSION_BLOCK_INBOUND;
+
+        ret = LIBSSH2_RECV(session, &c, 1,
+                            LIBSSH2_SOCKET_RECV_FLAGS(session));
+        if(ret < 0) {
+            if(session->api_block_mode || (ret != -EAGAIN))
+                /* ignore EAGAIN when non-blocking */
+                _libssh2_debug(session, LIBSSH2_TRACE_SOCKET,
+                               "Error recving %d bytes: %d", 1, -ret);
+        }
+        else
+            _libssh2_debug(session, LIBSSH2_TRACE_SOCKET,
+                           "Recved %d bytes banner", ret);
+
+        if(ret < 0) {
+            if(ret == -EAGAIN) {
+                session->socket_block_directions =
+                    LIBSSH2_SESSION_BLOCK_INBOUND;
+                session->banner_TxRx_total_send = banner_len;
+                return LIBSSH2_ERROR_EAGAIN;
+            }
+
+            /* Some kinda error */
+            session->banner_TxRx_state = libssh2_NB_state_idle;
+            session->banner_TxRx_total_send = 0;
+            return LIBSSH2_ERROR_SOCKET_RECV;
+        }
+
+        if(ret == 0) {
+            session->socket_state = LIBSSH2_SOCKET_DISCONNECTED;
+            return LIBSSH2_ERROR_SOCKET_DISCONNECT;
+        }
+
+        if(c == '\0') {
+            /* NULLs are not allowed in SSH banners */
+            session->banner_TxRx_state = libssh2_NB_state_idle;
+            session->banner_TxRx_total_send = 0;
+            return LIBSSH2_ERROR_BANNER_RECV;
+        }
+
+        session->banner_TxRx_banner[banner_len++] = c;
+    }
+
+    while(banner_len &&
+           ((session->banner_TxRx_banner[banner_len - 1] == '\n') ||
+            (session->banner_TxRx_banner[banner_len - 1] == '\r'))) {
+        banner_len--;
+    }
+
+    /* From this point on, we are done here */
+    session->banner_TxRx_state = libssh2_NB_state_idle;
+    session->banner_TxRx_total_send = 0;
+
+    if(!banner_len)
+        return LIBSSH2_ERROR_BANNER_RECV;
+
+    if(session->remote.banner)
+        LIBSSH2_FREE(session, session->remote.banner);
+
+    session->remote.banner = LIBSSH2_ALLOC(session, banner_len + 1);
+    if(!session->remote.banner) {
+        return _libssh2_error(session, LIBSSH2_ERROR_ALLOC,
+                              "Error allocating space for remote banner");
+    }
+    memcpy(session->remote.banner, session->banner_TxRx_banner, banner_len);
+    session->remote.banner[banner_len] = '\0';
+    _libssh2_debug(session, LIBSSH2_TRACE_TRANS, "Received Banner: %s",
+                   session->remote.banner);
+    return LIBSSH2_ERROR_NONE;
+}
+
+/*
+ * banner_send
+ *
+ * Send the default banner, or the one set via libssh2_setopt_string
+ *
+ * Returns LIBSSH2_ERROR_EAGAIN if it would block - and if it does so, you
+ * should call this function again as soon as it is likely that more data can
+ * be sent, and this function should then be called with the same argument set
+ * (same data pointer and same data_len) until zero or failure is returned.
+ */
+static int
+banner_send(LIBSSH2_SESSION * session)
+{
+    char *banner = (char *) LIBSSH2_SSH_DEFAULT_BANNER_WITH_CRLF;
+    int banner_len = sizeof(LIBSSH2_SSH_DEFAULT_BANNER_WITH_CRLF) - 1;
+    ssize_t ret;
+#ifdef LIBSSH2DEBUG
+    char banner_dup[256];
+#endif
+
+    if(session->banner_TxRx_state == libssh2_NB_state_idle) {
+        if(session->local.banner) {
+            /* setopt_string will have given us our \r\n characters */
+            banner_len = strlen((char *) session->local.banner);
+            banner = (char *) session->local.banner;
+        }
+#ifdef LIBSSH2DEBUG
+        /* Hack and slash to avoid sending CRLF in debug output */
+        if(banner_len < 256) {
+            memcpy(banner_dup, banner, banner_len - 2);
+            banner_dup[banner_len - 2] = '\0';
+        }
+        else {
+            memcpy(banner_dup, banner, 255);
+            banner[255] = '\0';
+        }
+
+        _libssh2_debug(session, LIBSSH2_TRACE_TRANS, "Sending Banner: %s",
+                       banner_dup);
+#endif
+
+        session->banner_TxRx_state = libssh2_NB_state_created;
+    }
+
+    /* no outgoing block yet! */
+    session->socket_block_directions &= ~LIBSSH2_SESSION_BLOCK_OUTBOUND;
+
+    ret = LIBSSH2_SEND(session,
+                        banner + session->banner_TxRx_total_send,
+                        banner_len - session->banner_TxRx_total_send,
+                        LIBSSH2_SOCKET_SEND_FLAGS(session));
+    if(ret < 0)
+        _libssh2_debug(session, LIBSSH2_TRACE_SOCKET,
+                       "Error sending %d bytes: %d",
+                       banner_len - session->banner_TxRx_total_send, -ret);
+    else
+        _libssh2_debug(session, LIBSSH2_TRACE_SOCKET,
+                       "Sent %d/%d bytes at %p+%d", ret,
+                       banner_len - session->banner_TxRx_total_send,
+                       banner, session->banner_TxRx_total_send);
+
+    if(ret != (banner_len - session->banner_TxRx_total_send)) {
+        if(ret >= 0 || ret == -EAGAIN) {
+            /* the whole packet could not be sent, save the what was */
+            session->socket_block_directions =
+                LIBSSH2_SESSION_BLOCK_OUTBOUND;
+            if(ret > 0)
+                session->banner_TxRx_total_send += ret;
+            return LIBSSH2_ERROR_EAGAIN;
+        }
+        session->banner_TxRx_state = libssh2_NB_state_idle;
+        session->banner_TxRx_total_send = 0;
+        return LIBSSH2_ERROR_SOCKET_RECV;
+    }
+
+    /* Set the state back to idle */
+    session->banner_TxRx_state = libssh2_NB_state_idle;
+    session->banner_TxRx_total_send = 0;
+
+    return 0;
+}
+
+/*
+ * session_nonblock() sets the given socket to either blocking or
+ * non-blocking mode based on the 'nonblock' boolean argument. This function
+ * is copied from the libcurl sources with permission.
+ */
+static int
+session_nonblock(libssh2_socket_t sockfd,   /* operate on this */
+                 int nonblock /* TRUE or FALSE */ )
+{
+#undef SETBLOCK
+#define SETBLOCK 0
+#ifdef HAVE_O_NONBLOCK
+    /* most recent unix versions */
+    int flags;
+
+    flags = fcntl(sockfd, F_GETFL, 0);
+    if(nonblock)
+        return fcntl(sockfd, F_SETFL, flags | O_NONBLOCK);
+    else
+        return fcntl(sockfd, F_SETFL, flags & (~O_NONBLOCK));
+#undef SETBLOCK
+#define SETBLOCK 1
+#endif
+
+#if defined(HAVE_FIONBIO) && (SETBLOCK == 0)
+    /* older unix versions and VMS*/
+    int flags;
+
+    flags = nonblock;
+    return ioctl(sockfd, FIONBIO, &flags);
+#undef SETBLOCK
+#define SETBLOCK 2
+#endif
+
+#if defined(HAVE_IOCTLSOCKET) && (SETBLOCK == 0)
+    /* Windows? */
+    unsigned long flags;
+    flags = nonblock;
+
+    return ioctlsocket(sockfd, FIONBIO, &flags);
+#undef SETBLOCK
+#define SETBLOCK 3
+#endif
+
+#if defined(HAVE_IOCTLSOCKET_CASE) && (SETBLOCK == 0)
+    /* presumably for Amiga */
+    return IoctlSocket(sockfd, FIONBIO, (long) nonblock);
+#undef SETBLOCK
+#define SETBLOCK 4
+#endif
+
+#if defined(HAVE_SO_NONBLOCK) && (SETBLOCK == 0)
+    /* BeOS */
+    long b = nonblock ? 1 : 0;
+    return setsockopt(sockfd, SOL_SOCKET, SO_NONBLOCK, &b, sizeof(b));
+#undef SETBLOCK
+#define SETBLOCK 5
+#endif
+
+#ifdef HAVE_DISABLED_NONBLOCKING
+    return 0;                   /* returns success */
+#undef SETBLOCK
+#define SETBLOCK 6
+#endif
+
+#if(SETBLOCK == 0)
+#error "no non-blocking method was found/used/set"
+#endif
+}
+
+/*
+ * get_socket_nonblocking()
+ *
+ * gets the given blocking or non-blocking state of the socket.
+ */
+static int
+get_socket_nonblocking(int sockfd)
+{                               /* operate on this */
+#undef GETBLOCK
+#define GETBLOCK 0
+#ifdef HAVE_O_NONBLOCK
+    /* most recent unix versions */
+    int flags = fcntl(sockfd, F_GETFL, 0);
+
+    if(flags == -1) {
+        /* Assume blocking on error */
+        return 1;
+    }
+    return (flags & O_NONBLOCK);
+#undef GETBLOCK
+#define GETBLOCK 1
+#endif
+
+#if defined(WSAEWOULDBLOCK) && (GETBLOCK == 0)
+    /* Windows? */
+    unsigned int option_value;
+    socklen_t option_len = sizeof(option_value);
+
+    if(getsockopt
+        (sockfd, SOL_SOCKET, SO_ERROR, (void *) &option_value, &option_len)) {
+        /* Assume blocking on error */
+        return 1;
+    }
+    return (int) option_value;
+#undef GETBLOCK
+#define GETBLOCK 2
+#endif
+
+#if defined(HAVE_SO_NONBLOCK) && (GETBLOCK == 0)
+    /* BeOS */
+    long b;
+    if(getsockopt(sockfd, SOL_SOCKET, SO_NONBLOCK, &b, sizeof(b))) {
+        /* Assume blocking on error */
+        return 1;
+    }
+    return (int) b;
+#undef GETBLOCK
+#define GETBLOCK 5
+#endif
+
+#if defined(SO_STATE) && defined(__VMS) && (GETBLOCK == 0)
+
+    /* VMS TCP/IP Services */
+
+    size_t sockstat = 0;
+    int    callstat = 0;
+    size_t size = sizeof(int);
+
+    callstat = getsockopt(sockfd, SOL_SOCKET, SO_STATE,
+                                  (char *)&sockstat, &size);
+    if(callstat == -1) return 0;
+    if((sockstat&SS_NBIO) != 0) return 1;
+    return 0;
+
+#undef GETBLOCK
+#define GETBLOCK 6
+#endif
+
+#ifdef HAVE_DISABLED_NONBLOCKING
+    return 1;                   /* returns blocking */
+#undef GETBLOCK
+#define GETBLOCK 7
+#endif
+
+#if(GETBLOCK == 0)
+#error "no non-blocking method was found/used/get"
+#endif
+}
+
+/* libssh2_session_banner_set
+ * Set the local banner to use in the server handshake.
+ */
+LIBSSH2_API int
+libssh2_session_banner_set(LIBSSH2_SESSION * session, const char *banner)
+{
+    size_t banner_len = banner ? strlen(banner) : 0;
+
+    if(session->local.banner) {
+        LIBSSH2_FREE(session, session->local.banner);
+        session->local.banner = NULL;
+    }
+
+    if(!banner_len)
+        return 0;
+
+    session->local.banner = LIBSSH2_ALLOC(session, banner_len + 3);
+    if(!session->local.banner) {
+        return _libssh2_error(session, LIBSSH2_ERROR_ALLOC,
+                              "Unable to allocate memory for local banner");
+    }
+
+    memcpy(session->local.banner, banner, banner_len);
+
+    /* first zero terminate like this so that the debug output is nice */
+    session->local.banner[banner_len] = '\0';
+    _libssh2_debug(session, LIBSSH2_TRACE_TRANS, "Setting local Banner: %s",
+                   session->local.banner);
+    session->local.banner[banner_len++] = '\r';
+    session->local.banner[banner_len++] = '\n';
+    session->local.banner[banner_len] = '\0';
+
+    return 0;
+}
+
+/* libssh2_banner_set
+ * Set the local banner. DEPRECATED VERSION
+ */
+LIBSSH2_API int
+libssh2_banner_set(LIBSSH2_SESSION * session, const char *banner)
+{
+    return libssh2_session_banner_set(session, banner);
+}
+
+/*
+ * libssh2_session_init_ex
+ *
+ * Allocate and initialize a libssh2 session structure. Allows for malloc
+ * callbacks in case the calling program has its own memory manager It's
+ * allowable (but unadvisable) to define some but not all of the malloc
+ * callbacks An additional pointer value may be optionally passed to be sent
+ * to the callbacks (so they know who's asking)
+ */
+LIBSSH2_API LIBSSH2_SESSION *
+libssh2_session_init_ex(LIBSSH2_ALLOC_FUNC((*my_alloc)),
+                        LIBSSH2_FREE_FUNC((*my_free)),
+                        LIBSSH2_REALLOC_FUNC((*my_realloc)), void *abstract)
+{
+    LIBSSH2_ALLOC_FUNC((*local_alloc)) = libssh2_default_alloc;
+    LIBSSH2_FREE_FUNC((*local_free)) = libssh2_default_free;
+    LIBSSH2_REALLOC_FUNC((*local_realloc)) = libssh2_default_realloc;
+    LIBSSH2_SESSION *session;
+
+    if(my_alloc) {
+        local_alloc = my_alloc;
+    }
+    if(my_free) {
+        local_free = my_free;
+    }
+    if(my_realloc) {
+        local_realloc = my_realloc;
+    }
+
+    session = local_alloc(sizeof(LIBSSH2_SESSION), &abstract);
+    if(session) {
+        memset(session, 0, sizeof(LIBSSH2_SESSION));
+        session->alloc = local_alloc;
+        session->free = local_free;
+        session->realloc = local_realloc;
+        session->send = _libssh2_send;
+        session->recv = _libssh2_recv;
+        session->abstract = abstract;
+        session->api_timeout = 0; /* timeout-free API by default */
+        session->api_block_mode = 1; /* blocking API by default */
+        _libssh2_debug(session, LIBSSH2_TRACE_TRANS,
+                       "New session resource allocated");
+        _libssh2_init_if_needed();
+    }
+    return session;
+}
+
+/*
+ * libssh2_session_callback_set
+ *
+ * Set (or reset) a callback function
+ * Returns the prior address
+ *
+ * ALERT: this function relies on that we can typecast function pointers
+ * to void pointers, which isn't allowed in ISO C!
+ */
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wpedantic"
+LIBSSH2_API void *
+libssh2_session_callback_set(LIBSSH2_SESSION * session,
+                             int cbtype, void *callback)
+{
+    void *oldcb;
+
+    switch(cbtype) {
+    case LIBSSH2_CALLBACK_IGNORE:
+        oldcb = session->ssh_msg_ignore;
+        session->ssh_msg_ignore = callback;
+        return oldcb;
+
+    case LIBSSH2_CALLBACK_DEBUG:
+        oldcb = session->ssh_msg_debug;
+        session->ssh_msg_debug = callback;
+        return oldcb;
+
+    case LIBSSH2_CALLBACK_DISCONNECT:
+        oldcb = session->ssh_msg_disconnect;
+        session->ssh_msg_disconnect = callback;
+        return oldcb;
+
+    case LIBSSH2_CALLBACK_MACERROR:
+        oldcb = session->macerror;
+        session->macerror = callback;
+        return oldcb;
+
+    case LIBSSH2_CALLBACK_X11:
+        oldcb = session->x11;
+        session->x11 = callback;
+        return oldcb;
+
+    case LIBSSH2_CALLBACK_SEND:
+        oldcb = session->send;
+        session->send = callback;
+        return oldcb;
+
+    case LIBSSH2_CALLBACK_RECV:
+        oldcb = session->recv;
+        session->recv = callback;
+        return oldcb;
+    }
+    _libssh2_debug(session, LIBSSH2_TRACE_TRANS, "Setting Callback %d",
+                   cbtype);
+
+    return NULL;
+}
+#pragma GCC diagnostic pop
+
+/*
+ * _libssh2_wait_socket()
+ *
+ * Utility function that waits for action on the socket. Returns 0 when ready
+ * to run again or error on timeout.
+ */
+int _libssh2_wait_socket(LIBSSH2_SESSION *session, time_t start_time)
+{
+    int rc;
+    int seconds_to_next;
+    int dir;
+    int has_timeout;
+    long ms_to_next = 0;
+    long elapsed_ms;
+
+    /* since libssh2 often sets EAGAIN internally before this function is
+       called, we can decrease some amount of confusion in user programs by
+       resetting the error code in this function to reduce the risk of EAGAIN
+       being stored as error when a blocking function has returned */
+    session->err_code = LIBSSH2_ERROR_NONE;
+
+    rc = libssh2_keepalive_send(session, &seconds_to_next);
+    if(rc < 0)
+        return rc;
+
+    ms_to_next = seconds_to_next * 1000;
+
+    /* figure out what to wait for */
+    dir = libssh2_session_block_directions(session);
+
+    if(!dir) {
+        _libssh2_debug(session, LIBSSH2_TRACE_SOCKET,
+                       "Nothing to wait for in wait_socket");
+        /* To avoid that we hang below just because there's nothing set to
+           wait for, we timeout on 1 second to also avoid busy-looping
+           during this condition */
+        ms_to_next = 1000;
+    }
+
+    if(session->api_timeout > 0 &&
+        (seconds_to_next == 0 ||
+         ms_to_next > session->api_timeout)) {
+        time_t now = time(NULL);
+        elapsed_ms = (long)(1000*difftime(now, start_time));
+        if(elapsed_ms > session->api_timeout) {
+            return _libssh2_error(session, LIBSSH2_ERROR_TIMEOUT,
+                                  "API timeout expired");
+        }
+        ms_to_next = (session->api_timeout - elapsed_ms);
+        has_timeout = 1;
+    }
+    else if(ms_to_next > 0) {
+        has_timeout = 1;
+    }
+    else
+        has_timeout = 0;
+
+#ifdef HAVE_POLL
+    {
+        struct pollfd sockets[1];
+
+        sockets[0].fd = session->socket_fd;
+        sockets[0].events = 0;
+        sockets[0].revents = 0;
+
+        if(dir & LIBSSH2_SESSION_BLOCK_INBOUND)
+            sockets[0].events |= POLLIN;
+
+        if(dir & LIBSSH2_SESSION_BLOCK_OUTBOUND)
+            sockets[0].events |= POLLOUT;
+
+        rc = poll(sockets, 1, has_timeout?ms_to_next: -1);
+    }
+#else
+    {
+        fd_set rfd;
+        fd_set wfd;
+        fd_set *writefd = NULL;
+        fd_set *readfd = NULL;
+        struct timeval tv;
+
+        tv.tv_sec = ms_to_next / 1000;
+        tv.tv_usec = (ms_to_next - tv.tv_sec*1000) * 1000;
+
+        if(dir & LIBSSH2_SESSION_BLOCK_INBOUND) {
+            FD_ZERO(&rfd);
+            FD_SET(session->socket_fd, &rfd);
+            readfd = &rfd;
+        }
+
+        if(dir & LIBSSH2_SESSION_BLOCK_OUTBOUND) {
+            FD_ZERO(&wfd);
+            FD_SET(session->socket_fd, &wfd);
+            writefd = &wfd;
+        }
+
+        rc = select(session->socket_fd + 1, readfd, writefd, NULL,
+                    has_timeout ? &tv : NULL);
+    }
+#endif
+    if(rc == 0) {
+        return _libssh2_error(session, LIBSSH2_ERROR_TIMEOUT,
+                              "Timed out waiting on socket");
+    }
+    if(rc < 0) {
+        return _libssh2_error(session, LIBSSH2_ERROR_TIMEOUT,
+                              "Error waiting on socket");
+    }
+
+    return 0; /* ready to try again */
+}
+
+static int
+session_startup(LIBSSH2_SESSION *session, libssh2_socket_t sock)
+{
+    int rc;
+
+    if(session->startup_state == libssh2_NB_state_idle) {
+        _libssh2_debug(session, LIBSSH2_TRACE_TRANS,
+                       "session_startup for socket %d", sock);
+        if(LIBSSH2_INVALID_SOCKET == sock) {
+            /* Did we forget something? */
+            return _libssh2_error(session, LIBSSH2_ERROR_BAD_SOCKET,
+                                  "Bad socket provided");
+        }
+        session->socket_fd = sock;
+
+        session->socket_prev_blockstate =
+            !get_socket_nonblocking(session->socket_fd);
+
+        if(session->socket_prev_blockstate) {
+            /* If in blocking state change to non-blocking */
+            rc = session_nonblock(session->socket_fd, 1);
+            if(rc) {
+                return _libssh2_error(session, rc,
+                                      "Failed changing socket's "
+                                      "blocking state to non-blocking");
+            }
+        }
+
+        session->startup_state = libssh2_NB_state_created;
+    }
+
+    if(session->startup_state == libssh2_NB_state_created) {
+        rc = banner_send(session);
+        if(rc == LIBSSH2_ERROR_EAGAIN)
+            return rc;
+        else if(rc) {
+            return _libssh2_error(session, rc,
+                                  "Failed sending banner");
+        }
+        session->startup_state = libssh2_NB_state_sent;
+        session->banner_TxRx_state = libssh2_NB_state_idle;
+    }
+
+    if(session->startup_state == libssh2_NB_state_sent) {
+        do {
+            rc = banner_receive(session);
+            if(rc == LIBSSH2_ERROR_EAGAIN)
+                return rc;
+            else if(rc)
+                return _libssh2_error(session, rc,
+                                      "Failed getting banner");
+        } while(strncmp("SSH-", (char *)session->remote.banner, 4));
+
+        session->startup_state = libssh2_NB_state_sent1;
+    }
+
+    if(session->startup_state == libssh2_NB_state_sent1) {
+        rc = _libssh2_kex_exchange(session, 0, &session->startup_key_state);
+        if(rc == LIBSSH2_ERROR_EAGAIN)
+            return rc;
+        else if(rc)
+            return _libssh2_error(session, rc,
+                                  "Unable to exchange encryption keys");
+
+        session->startup_state = libssh2_NB_state_sent2;
+    }
+
+    if(session->startup_state == libssh2_NB_state_sent2) {
+        _libssh2_debug(session, LIBSSH2_TRACE_TRANS,
+                       "Requesting userauth service");
+
+        /* Request the userauth service */
+        session->startup_service[0] = SSH_MSG_SERVICE_REQUEST;
+        _libssh2_htonu32(session->startup_service + 1,
+                         sizeof("ssh-userauth") - 1);
+        memcpy(session->startup_service + 5, "ssh-userauth",
+               sizeof("ssh-userauth") - 1);
+
+        session->startup_state = libssh2_NB_state_sent3;
+    }
+
+    if(session->startup_state == libssh2_NB_state_sent3) {
+        rc = _libssh2_transport_send(session, session->startup_service,
+                                     sizeof("ssh-userauth") + 5 - 1,
+                                     NULL, 0);
+        if(rc == LIBSSH2_ERROR_EAGAIN)
+            return rc;
+        else if(rc) {
+            return _libssh2_error(session, rc,
+                                  "Unable to ask for ssh-userauth service");
+        }
+
+        session->startup_state = libssh2_NB_state_sent4;
+    }
+
+    if(session->startup_state == libssh2_NB_state_sent4) {
+        rc = _libssh2_packet_require(session, SSH_MSG_SERVICE_ACCEPT,
+                                     &session->startup_data,
+                                     &session->startup_data_len, 0, NULL, 0,
+                                     &session->startup_req_state);
+        if(rc)
+            return rc;
+
+        if(session->startup_data_len < 5) {
+            return _libssh2_error(session, LIBSSH2_ERROR_PROTO,
+                                  "Unexpected packet length");
+        }
+
+        session->startup_service_length =
+            _libssh2_ntohu32(session->startup_data + 1);
+
+
+        if((session->startup_service_length != (sizeof("ssh-userauth") - 1))
+            || strncmp("ssh-userauth", (char *) session->startup_data + 5,
+                       session->startup_service_length)) {
+            LIBSSH2_FREE(session, session->startup_data);
+            session->startup_data = NULL;
+            return _libssh2_error(session, LIBSSH2_ERROR_PROTO,
+                                  "Invalid response received from server");
+        }
+        LIBSSH2_FREE(session, session->startup_data);
+        session->startup_data = NULL;
+
+        session->startup_state = libssh2_NB_state_idle;
+
+        return 0;
+    }
+
+    /* just for safety return some error */
+    return LIBSSH2_ERROR_INVAL;
+}
+
+/*
+ * libssh2_session_handshake()
+ *
+ * session: LIBSSH2_SESSION struct allocated and owned by the calling program
+ * sock:    *must* be populated with an opened and connected socket.
+ *
+ * Returns: 0 on success, or non-zero on failure
+ */
+LIBSSH2_API int
+libssh2_session_handshake(LIBSSH2_SESSION *session, libssh2_socket_t sock)
+{
+    int rc;
+
+    BLOCK_ADJUST(rc, session, session_startup(session, sock) );
+
+    return rc;
+}
+
+/*
+ * libssh2_session_startup()
+ *
+ * DEPRECATED. Use libssh2_session_handshake() instead! This function is not
+ * portable enough.
+ *
+ * session: LIBSSH2_SESSION struct allocated and owned by the calling program
+ * sock:    *must* be populated with an opened and connected socket.
+ *
+ * Returns: 0 on success, or non-zero on failure
+ */
+LIBSSH2_API int
+libssh2_session_startup(LIBSSH2_SESSION *session, int sock)
+{
+    return libssh2_session_handshake(session, (libssh2_socket_t) sock);
+}
+
+/*
+ * libssh2_session_free
+ *
+ * Frees the memory allocated to the session
+ * Also closes and frees any channels attached to this session
+ */
+static int
+session_free(LIBSSH2_SESSION *session)
+{
+    int rc;
+    LIBSSH2_PACKET *pkg;
+    LIBSSH2_CHANNEL *ch;
+    LIBSSH2_LISTENER *l;
+    int packets_left = 0;
+
+    if(session->free_state == libssh2_NB_state_idle) {
+        _libssh2_debug(session, LIBSSH2_TRACE_TRANS,
+                       "Freeing session resource",
+                       session->remote.banner);
+
+        session->free_state = libssh2_NB_state_created;
+    }
+
+    if(session->free_state == libssh2_NB_state_created) {
+        while((ch = _libssh2_list_first(&session->channels))) {
+
+            rc = _libssh2_channel_free(ch);
+            if(rc == LIBSSH2_ERROR_EAGAIN)
+                return rc;
+        }
+
+        session->free_state = libssh2_NB_state_sent;
+    }
+
+    if(session->free_state == libssh2_NB_state_sent) {
+        while((l = _libssh2_list_first(&session->listeners))) {
+            rc = _libssh2_channel_forward_cancel(l);
+            if(rc == LIBSSH2_ERROR_EAGAIN)
+                return rc;
+        }
+
+        session->free_state = libssh2_NB_state_sent1;
+    }
+
+    if(session->state & LIBSSH2_STATE_NEWKEYS) {
+        /* hostkey */
+        if(session->hostkey && session->hostkey->dtor) {
+            session->hostkey->dtor(session, &session->server_hostkey_abstract);
+        }
+
+        /* Client to Server */
+        /* crypt */
+        if(session->local.crypt && session->local.crypt->dtor) {
+            session->local.crypt->dtor(session,
+                                       &session->local.crypt_abstract);
+        }
+        /* comp */
+        if(session->local.comp && session->local.comp->dtor) {
+            session->local.comp->dtor(session, 1,
+                                      &session->local.comp_abstract);
+        }
+        /* mac */
+        if(session->local.mac && session->local.mac->dtor) {
+            session->local.mac->dtor(session, &session->local.mac_abstract);
+        }
+
+        /* Server to Client */
+        /* crypt */
+        if(session->remote.crypt && session->remote.crypt->dtor) {
+            session->remote.crypt->dtor(session,
+                                        &session->remote.crypt_abstract);
+        }
+        /* comp */
+        if(session->remote.comp && session->remote.comp->dtor) {
+            session->remote.comp->dtor(session, 0,
+                                       &session->remote.comp_abstract);
+        }
+        /* mac */
+        if(session->remote.mac && session->remote.mac->dtor) {
+            session->remote.mac->dtor(session, &session->remote.mac_abstract);
+        }
+
+        /* session_id */
+        if(session->session_id) {
+            LIBSSH2_FREE(session, session->session_id);
+        }
+    }
+
+    /* Free banner(s) */
+    if(session->remote.banner) {
+        LIBSSH2_FREE(session, session->remote.banner);
+    }
+    if(session->local.banner) {
+        LIBSSH2_FREE(session, session->local.banner);
+    }
+
+    /* Free preference(s) */
+    if(session->kex_prefs) {
+        LIBSSH2_FREE(session, session->kex_prefs);
+    }
+    if(session->hostkey_prefs) {
+        LIBSSH2_FREE(session, session->hostkey_prefs);
+    }
+
+    if(session->local.kexinit) {
+        LIBSSH2_FREE(session, session->local.kexinit);
+    }
+    if(session->local.crypt_prefs) {
+        LIBSSH2_FREE(session, session->local.crypt_prefs);
+    }
+    if(session->local.mac_prefs) {
+        LIBSSH2_FREE(session, session->local.mac_prefs);
+    }
+    if(session->local.comp_prefs) {
+        LIBSSH2_FREE(session, session->local.comp_prefs);
+    }
+    if(session->local.lang_prefs) {
+        LIBSSH2_FREE(session, session->local.lang_prefs);
+    }
+
+    if(session->remote.kexinit) {
+        LIBSSH2_FREE(session, session->remote.kexinit);
+    }
+    if(session->remote.crypt_prefs) {
+        LIBSSH2_FREE(session, session->remote.crypt_prefs);
+    }
+    if(session->remote.mac_prefs) {
+        LIBSSH2_FREE(session, session->remote.mac_prefs);
+    }
+    if(session->remote.comp_prefs) {
+        LIBSSH2_FREE(session, session->remote.comp_prefs);
+    }
+    if(session->remote.lang_prefs) {
+        LIBSSH2_FREE(session, session->remote.lang_prefs);
+    }
+
+    /*
+     * Make sure all memory used in the state variables are free
+     */
+    if(session->kexinit_data) {
+        LIBSSH2_FREE(session, session->kexinit_data);
+    }
+    if(session->startup_data) {
+        LIBSSH2_FREE(session, session->startup_data);
+    }
+    if(session->userauth_list_data) {
+        LIBSSH2_FREE(session, session->userauth_list_data);
+    }
+    if(session->userauth_pswd_data) {
+        LIBSSH2_FREE(session, session->userauth_pswd_data);
+    }
+    if(session->userauth_pswd_newpw) {
+        LIBSSH2_FREE(session, session->userauth_pswd_newpw);
+    }
+    if(session->userauth_host_packet) {
+        LIBSSH2_FREE(session, session->userauth_host_packet);
+    }
+    if(session->userauth_host_method) {
+        LIBSSH2_FREE(session, session->userauth_host_method);
+    }
+    if(session->userauth_host_data) {
+        LIBSSH2_FREE(session, session->userauth_host_data);
+    }
+    if(session->userauth_pblc_data) {
+        LIBSSH2_FREE(session, session->userauth_pblc_data);
+    }
+    if(session->userauth_pblc_packet) {
+        LIBSSH2_FREE(session, session->userauth_pblc_packet);
+    }
+    if(session->userauth_pblc_method) {
+        LIBSSH2_FREE(session, session->userauth_pblc_method);
+    }
+    if(session->userauth_kybd_data) {
+        LIBSSH2_FREE(session, session->userauth_kybd_data);
+    }
+    if(session->userauth_kybd_packet) {
+        LIBSSH2_FREE(session, session->userauth_kybd_packet);
+    }
+    if(session->userauth_kybd_auth_instruction) {
+        LIBSSH2_FREE(session, session->userauth_kybd_auth_instruction);
+    }
+    if(session->open_packet) {
+        LIBSSH2_FREE(session, session->open_packet);
+    }
+    if(session->open_data) {
+        LIBSSH2_FREE(session, session->open_data);
+    }
+    if(session->direct_message) {
+        LIBSSH2_FREE(session, session->direct_message);
+    }
+    if(session->fwdLstn_packet) {
+        LIBSSH2_FREE(session, session->fwdLstn_packet);
+    }
+    if(session->pkeyInit_data) {
+        LIBSSH2_FREE(session, session->pkeyInit_data);
+    }
+    if(session->scpRecv_command) {
+        LIBSSH2_FREE(session, session->scpRecv_command);
+    }
+    if(session->scpSend_command) {
+        LIBSSH2_FREE(session, session->scpSend_command);
+    }
+    if(session->sftpInit_sftp) {
+        LIBSSH2_FREE(session, session->sftpInit_sftp);
+    }
+
+    /* Free payload buffer */
+    if(session->packet.total_num) {
+        LIBSSH2_FREE(session, session->packet.payload);
+    }
+
+    /* Cleanup all remaining packets */
+    while((pkg = _libssh2_list_first(&session->packets))) {
+        packets_left++;
+        _libssh2_debug(session, LIBSSH2_TRACE_TRANS,
+            "packet left with id %d", pkg->data[0]);
+        /* unlink the node */
+        _libssh2_list_remove(&pkg->node);
+
+        /* free */
+        LIBSSH2_FREE(session, pkg->data);
+        LIBSSH2_FREE(session, pkg);
+    }
+    _libssh2_debug(session, LIBSSH2_TRACE_TRANS,
+         "Extra packets left %d", packets_left);
+
+    if(session->socket_prev_blockstate) {
+        /* if the socket was previously blocking, put it back so */
+        rc = session_nonblock(session->socket_fd, 0);
+        if(rc) {
+            _libssh2_debug(session, LIBSSH2_TRACE_TRANS,
+             "unable to reset socket's blocking state");
+        }
+    }
+
+    if(session->server_hostkey) {
+        LIBSSH2_FREE(session, session->server_hostkey);
+    }
+
+    /* error string */
+    if(session->err_msg &&
+       ((session->err_flags & LIBSSH2_ERR_FLAG_DUP) != 0)) {
+        LIBSSH2_FREE(session, (char *)session->err_msg);
+    }
+
+    LIBSSH2_FREE(session, session);
+
+    return 0;
+}
+
+/*
+ * libssh2_session_free
+ *
+ * Frees the memory allocated to the session
+ * Also closes and frees any channels attached to this session
+ */
+LIBSSH2_API int
+libssh2_session_free(LIBSSH2_SESSION * session)
+{
+    int rc;
+
+    BLOCK_ADJUST(rc, session, session_free(session) );
+
+    return rc;
+}
+
+/*
+ * libssh2_session_disconnect_ex
+ */
+static int
+session_disconnect(LIBSSH2_SESSION *session, int reason,
+                   const char *description,
+                   const char *lang)
+{
+    unsigned char *s;
+    unsigned long descr_len = 0, lang_len = 0;
+    int rc;
+
+    if(session->disconnect_state == libssh2_NB_state_idle) {
+        _libssh2_debug(session, LIBSSH2_TRACE_TRANS,
+                       "Disconnecting: reason=%d, desc=%s, lang=%s", reason,
+                       description, lang);
+        if(description)
+            descr_len = strlen(description);
+
+        if(lang)
+            lang_len = strlen(lang);
+
+        if(descr_len > 256)
+            return _libssh2_error(session, LIBSSH2_ERROR_INVAL,
+                                  "too long description");
+
+        /* 13 = packet_type(1) + reason code(4) + descr_len(4) + lang_len(4) */
+        session->disconnect_data_len = descr_len + lang_len + 13;
+
+        s = session->disconnect_data;
+
+        *(s++) = SSH_MSG_DISCONNECT;
+        _libssh2_store_u32(&s, reason);
+        _libssh2_store_str(&s, description, descr_len);
+        /* store length only, lang is sent separately */
+        _libssh2_store_u32(&s, lang_len);
+
+        session->disconnect_state = libssh2_NB_state_created;
+    }
+
+    rc = _libssh2_transport_send(session, session->disconnect_data,
+                                 session->disconnect_data_len,
+                                 (unsigned char *)lang, lang_len);
+    if(rc == LIBSSH2_ERROR_EAGAIN)
+        return rc;
+
+    session->disconnect_state = libssh2_NB_state_idle;
+
+    return 0;
+}
+
+/*
+ * libssh2_session_disconnect_ex
+ */
+LIBSSH2_API int
+libssh2_session_disconnect_ex(LIBSSH2_SESSION *session, int reason,
+                              const char *desc, const char *lang)
+{
+    int rc;
+    session->state &= ~LIBSSH2_STATE_EXCHANGING_KEYS;
+    BLOCK_ADJUST(rc, session,
+                 session_disconnect(session, reason, desc, lang));
+
+    return rc;
+}
+
+/* libssh2_session_methods
+ *
+ * Return the currently active methods for method_type
+ *
+ * NOTE: Currently lang_cs and lang_sc are ALWAYS set to empty string
+ * regardless of actual negotiation Strings should NOT be freed
+ */
+LIBSSH2_API const char *
+libssh2_session_methods(LIBSSH2_SESSION * session, int method_type)
+{
+    /* All methods have char *name as their first element */
+    const LIBSSH2_KEX_METHOD *method = NULL;
+
+    switch(method_type) {
+    case LIBSSH2_METHOD_KEX:
+        method = session->kex;
+        break;
+
+    case LIBSSH2_METHOD_HOSTKEY:
+        method = (LIBSSH2_KEX_METHOD *) session->hostkey;
+        break;
+
+    case LIBSSH2_METHOD_CRYPT_CS:
+        method = (LIBSSH2_KEX_METHOD *) session->local.crypt;
+        break;
+
+    case LIBSSH2_METHOD_CRYPT_SC:
+        method = (LIBSSH2_KEX_METHOD *) session->remote.crypt;
+        break;
+
+    case LIBSSH2_METHOD_MAC_CS:
+        method = (LIBSSH2_KEX_METHOD *) session->local.mac;
+        break;
+
+    case LIBSSH2_METHOD_MAC_SC:
+        method = (LIBSSH2_KEX_METHOD *) session->remote.mac;
+        break;
+
+    case LIBSSH2_METHOD_COMP_CS:
+        method = (LIBSSH2_KEX_METHOD *) session->local.comp;
+        break;
+
+    case LIBSSH2_METHOD_COMP_SC:
+        method = (LIBSSH2_KEX_METHOD *) session->remote.comp;
+        break;
+
+    case LIBSSH2_METHOD_LANG_CS:
+        return "";
+
+    case LIBSSH2_METHOD_LANG_SC:
+        return "";
+
+    default:
+        _libssh2_error(session, LIBSSH2_ERROR_INVAL,
+                       "Invalid parameter specified for method_type");
+        return NULL;
+    }
+
+    if(!method) {
+        _libssh2_error(session, LIBSSH2_ERROR_METHOD_NONE,
+                       "No method negotiated");
+        return NULL;
+    }
+
+    return method->name;
+}
+
+/* libssh2_session_abstract
+ * Retrieve a pointer to the abstract property
+ */
+LIBSSH2_API void **
+libssh2_session_abstract(LIBSSH2_SESSION * session)
+{
+    return &session->abstract;
+}
+
+/* libssh2_session_last_error
+ *
+ * Returns error code and populates an error string into errmsg If want_buf is
+ * non-zero then the string placed into errmsg must be freed by the calling
+ * program. Otherwise it is assumed to be owned by libssh2
+ */
+LIBSSH2_API int
+libssh2_session_last_error(LIBSSH2_SESSION * session, char **errmsg,
+                           int *errmsg_len, int want_buf)
+{
+    size_t msglen = 0;
+
+    /* No error to report */
+    if(!session->err_code) {
+        if(errmsg) {
+            if(want_buf) {
+                *errmsg = LIBSSH2_ALLOC(session, 1);
+                if(*errmsg) {
+                    **errmsg = 0;
+                }
+            }
+            else {
+                *errmsg = (char *) "";
+            }
+        }
+        if(errmsg_len) {
+            *errmsg_len = 0;
+        }
+        return 0;
+    }
+
+    if(errmsg) {
+        const char *error = session->err_msg ? session->err_msg : "";
+
+        msglen = strlen(error);
+
+        if(want_buf) {
+            /* Make a copy so the calling program can own it */
+            *errmsg = LIBSSH2_ALLOC(session, msglen + 1);
+            if(*errmsg) {
+                memcpy(*errmsg, error, msglen);
+                (*errmsg)[msglen] = 0;
+            }
+        }
+        else
+            *errmsg = (char *)error;
+    }
+
+    if(errmsg_len) {
+        *errmsg_len = msglen;
+    }
+
+    return session->err_code;
+}
+
+/* libssh2_session_last_errno
+ *
+ * Returns error code
+ */
+LIBSSH2_API int
+libssh2_session_last_errno(LIBSSH2_SESSION * session)
+{
+    return session->err_code;
+}
+
+/* libssh2_session_set_last_error
+ *
+ * Sets the internal error code for the session.
+ *
+ * This function is available specifically to be used by high level
+ * language wrappers (i.e. Python or Perl) that may extend the library
+ * features while still relying on its error reporting mechanism.
+ */
+LIBSSH2_API int
+libssh2_session_set_last_error(LIBSSH2_SESSION* session,
+                               int errcode,
+                               const char *errmsg)
+{
+    return _libssh2_error_flags(session, errcode, errmsg,
+                                LIBSSH2_ERR_FLAG_DUP);
+}
+
+/* Libssh2_session_flag
+ *
+ * Set/Get session flags
+ *
+ * Return error code.
+ */
+LIBSSH2_API int
+libssh2_session_flag(LIBSSH2_SESSION * session, int flag, int value)
+{
+    switch(flag) {
+    case LIBSSH2_FLAG_SIGPIPE:
+        session->flag.sigpipe = value;
+        break;
+    case LIBSSH2_FLAG_COMPRESS:
+        session->flag.compress = value;
+        break;
+    default:
+        /* unknown flag */
+        return LIBSSH2_ERROR_INVAL;
+    }
+
+    return LIBSSH2_ERROR_NONE;
+}
+
+/* _libssh2_session_set_blocking
+ *
+ * Set a session's blocking mode on or off, return the previous status when
+ * this function is called. Note this function does not alter the state of the
+ * actual socket involved.
+ */
+int
+_libssh2_session_set_blocking(LIBSSH2_SESSION *session, int blocking)
+{
+    int bl = session->api_block_mode;
+    _libssh2_debug(session, LIBSSH2_TRACE_CONN,
+                   "Setting blocking mode %s", blocking?"ON":"OFF");
+    session->api_block_mode = blocking;
+
+    return bl;
+}
+
+/* libssh2_session_set_blocking
+ *
+ * Set a channel's blocking mode on or off, similar to a socket's
+ * fcntl(fd, F_SETFL, O_NONBLOCK); type command
+ */
+LIBSSH2_API void
+libssh2_session_set_blocking(LIBSSH2_SESSION * session, int blocking)
+{
+    (void) _libssh2_session_set_blocking(session, blocking);
+}
+
+/* libssh2_session_get_blocking
+ *
+ * Returns a session's blocking mode on or off
+ */
+LIBSSH2_API int
+libssh2_session_get_blocking(LIBSSH2_SESSION * session)
+{
+    return session->api_block_mode;
+}
+
+
+/* libssh2_session_set_timeout
+ *
+ * Set a session's timeout (in msec) for blocking mode,
+ * or 0 to disable timeouts.
+ */
+LIBSSH2_API void
+libssh2_session_set_timeout(LIBSSH2_SESSION * session, long timeout)
+{
+    session->api_timeout = timeout;
+}
+
+/* libssh2_session_get_timeout
+ *
+ * Returns a session's timeout, or 0 if disabled
+ */
+LIBSSH2_API long
+libssh2_session_get_timeout(LIBSSH2_SESSION * session)
+{
+    return session->api_timeout;
+}
+
+/*
+ * libssh2_poll_channel_read
+ *
+ * Returns 0 if no data is waiting on channel,
+ * non-0 if data is available
+ */
+LIBSSH2_API int
+libssh2_poll_channel_read(LIBSSH2_CHANNEL *channel, int extended)
+{
+    LIBSSH2_SESSION *session;
+    LIBSSH2_PACKET *packet;
+
+    if(!channel)
+        return LIBSSH2_ERROR_BAD_USE;
+
+    session = channel->session;
+    packet = _libssh2_list_first(&session->packets);
+
+    while(packet) {
+        if(packet->data_len < 5) {
+            return _libssh2_error(session, LIBSSH2_ERROR_BUFFER_TOO_SMALL,
+                                  "Packet too small");
+        }
+
+        if(channel->local.id == _libssh2_ntohu32(packet->data + 1)) {
+            if(extended == 1 &&
+                (packet->data[0] == SSH_MSG_CHANNEL_EXTENDED_DATA
+                 || packet->data[0] == SSH_MSG_CHANNEL_DATA)) {
+                return 1;
+            }
+            else if(extended == 0 &&
+                    packet->data[0] == SSH_MSG_CHANNEL_DATA) {
+                return 1;
+            }
+            /* else - no data of any type is ready to be read */
+        }
+        packet = _libssh2_list_next(&packet->node);
+    }
+
+    return 0;
+}
+
+/*
+ * poll_channel_write
+ *
+ * Returns 0 if writing to channel would block,
+ * non-0 if data can be written without blocking
+ */
+static inline int
+poll_channel_write(LIBSSH2_CHANNEL * channel)
+{
+    return channel->local.window_size ? 1 : 0;
+}
+
+/* poll_listener_queued
+ *
+ * Returns 0 if no connections are waiting to be accepted
+ * non-0 if one or more connections are available
+ */
+static inline int
+poll_listener_queued(LIBSSH2_LISTENER * listener)
+{
+    return _libssh2_list_first(&listener->queue) ? 1 : 0;
+}
+
+/*
+ * libssh2_poll
+ *
+ * Poll sockets, channels, and listeners for activity
+ */
+LIBSSH2_API int
+libssh2_poll(LIBSSH2_POLLFD * fds, unsigned int nfds, long timeout)
+{
+    long timeout_remaining;
+    unsigned int i, active_fds;
+#ifdef HAVE_POLL
+    LIBSSH2_SESSION *session = NULL;
+#ifdef HAVE_ALLOCA
+    struct pollfd *sockets = alloca(sizeof(struct pollfd) * nfds);
+#else
+    struct pollfd sockets[256];
+
+    if(nfds > 256)
+        /* systems without alloca use a fixed-size array, this can be fixed if
+           we really want to, at least if the compiler is a C99 capable one */
+        return -1;
+#endif
+    /* Setup sockets for polling */
+    for(i = 0; i < nfds; i++) {
+        fds[i].revents = 0;
+        switch(fds[i].type) {
+        case LIBSSH2_POLLFD_SOCKET:
+            sockets[i].fd = fds[i].fd.socket;
+            sockets[i].events = fds[i].events;
+            sockets[i].revents = 0;
+            break;
+
+        case LIBSSH2_POLLFD_CHANNEL:
+            sockets[i].fd = fds[i].fd.channel->session->socket_fd;
+            sockets[i].events = POLLIN;
+            sockets[i].revents = 0;
+            if(!session)
+                session = fds[i].fd.channel->session;
+            break;
+
+        case LIBSSH2_POLLFD_LISTENER:
+            sockets[i].fd = fds[i].fd.listener->session->socket_fd;
+            sockets[i].events = POLLIN;
+            sockets[i].revents = 0;
+            if(!session)
+                session = fds[i].fd.listener->session;
+            break;
+
+        default:
+            if(session)
+                _libssh2_error(session, LIBSSH2_ERROR_INVALID_POLL_TYPE,
+                               "Invalid descriptor passed to libssh2_poll()");
+            return -1;
+        }
+    }
+#elif defined(HAVE_SELECT)
+    LIBSSH2_SESSION *session = NULL;
+    libssh2_socket_t maxfd = 0;
+    fd_set rfds, wfds;
+    struct timeval tv;
+
+    FD_ZERO(&rfds);
+    FD_ZERO(&wfds);
+    for(i = 0; i < nfds; i++) {
+        fds[i].revents = 0;
+        switch(fds[i].type) {
+        case LIBSSH2_POLLFD_SOCKET:
+            if(fds[i].events & LIBSSH2_POLLFD_POLLIN) {
+                FD_SET(fds[i].fd.socket, &rfds);
+                if(fds[i].fd.socket > maxfd)
+                    maxfd = fds[i].fd.socket;
+            }
+            if(fds[i].events & LIBSSH2_POLLFD_POLLOUT) {
+                FD_SET(fds[i].fd.socket, &wfds);
+                if(fds[i].fd.socket > maxfd)
+                    maxfd = fds[i].fd.socket;
+            }
+            break;
+
+        case LIBSSH2_POLLFD_CHANNEL:
+            FD_SET(fds[i].fd.channel->session->socket_fd, &rfds);
+            if(fds[i].fd.channel->session->socket_fd > maxfd)
+                maxfd = fds[i].fd.channel->session->socket_fd;
+            if(!session)
+                session = fds[i].fd.channel->session;
+            break;
+
+        case LIBSSH2_POLLFD_LISTENER:
+            FD_SET(fds[i].fd.listener->session->socket_fd, &rfds);
+            if(fds[i].fd.listener->session->socket_fd > maxfd)
+                maxfd = fds[i].fd.listener->session->socket_fd;
+            if(!session)
+                session = fds[i].fd.listener->session;
+            break;
+
+        default:
+            if(session)
+                _libssh2_error(session, LIBSSH2_ERROR_INVALID_POLL_TYPE,
+                               "Invalid descriptor passed to libssh2_poll()");
+            return -1;
+        }
+    }
+#else
+    /* No select() or poll()
+     * no sockets structure to setup
+     */
+
+    timeout = 0;
+#endif /* HAVE_POLL or HAVE_SELECT */
+
+    timeout_remaining = timeout;
+    do {
+#if defined(HAVE_POLL) || defined(HAVE_SELECT)
+        int sysret;
+#endif
+
+        active_fds = 0;
+
+        for(i = 0; i < nfds; i++) {
+            if(fds[i].events != fds[i].revents) {
+                switch(fds[i].type) {
+                case LIBSSH2_POLLFD_CHANNEL:
+                    if((fds[i].events & LIBSSH2_POLLFD_POLLIN) &&
+                        /* Want to be ready for read */
+                        ((fds[i].revents & LIBSSH2_POLLFD_POLLIN) == 0)) {
+                        /* Not yet known to be ready for read */
+                        fds[i].revents |=
+                            libssh2_poll_channel_read(fds[i].fd.channel,
+                                                      0) ?
+                            LIBSSH2_POLLFD_POLLIN : 0;
+                    }
+                    if((fds[i].events & LIBSSH2_POLLFD_POLLEXT) &&
+                        /* Want to be ready for extended read */
+                        ((fds[i].revents & LIBSSH2_POLLFD_POLLEXT) == 0)) {
+                        /* Not yet known to be ready for extended read */
+                        fds[i].revents |=
+                            libssh2_poll_channel_read(fds[i].fd.channel,
+                                                      1) ?
+                            LIBSSH2_POLLFD_POLLEXT : 0;
+                    }
+                    if((fds[i].events & LIBSSH2_POLLFD_POLLOUT) &&
+                        /* Want to be ready for write */
+                        ((fds[i].revents & LIBSSH2_POLLFD_POLLOUT) == 0)) {
+                        /* Not yet known to be ready for write */
+                        fds[i].revents |=
+                            poll_channel_write(fds[i].fd. channel) ?
+                            LIBSSH2_POLLFD_POLLOUT : 0;
+                    }
+                    if(fds[i].fd.channel->remote.close
+                        || fds[i].fd.channel->local.close) {
+                        fds[i].revents |= LIBSSH2_POLLFD_CHANNEL_CLOSED;
+                    }
+                    if(fds[i].fd.channel->session->socket_state ==
+                        LIBSSH2_SOCKET_DISCONNECTED) {
+                        fds[i].revents |=
+                            LIBSSH2_POLLFD_CHANNEL_CLOSED |
+                            LIBSSH2_POLLFD_SESSION_CLOSED;
+                    }
+                    break;
+
+                case LIBSSH2_POLLFD_LISTENER:
+                    if((fds[i].events & LIBSSH2_POLLFD_POLLIN) &&
+                        /* Want a connection */
+                        ((fds[i].revents & LIBSSH2_POLLFD_POLLIN) == 0)) {
+                        /* No connections known of yet */
+                        fds[i].revents |=
+                            poll_listener_queued(fds[i].fd. listener) ?
+                            LIBSSH2_POLLFD_POLLIN : 0;
+                    }
+                    if(fds[i].fd.listener->session->socket_state ==
+                        LIBSSH2_SOCKET_DISCONNECTED) {
+                        fds[i].revents |=
+                            LIBSSH2_POLLFD_LISTENER_CLOSED |
+                            LIBSSH2_POLLFD_SESSION_CLOSED;
+                    }
+                    break;
+                }
+            }
+            if(fds[i].revents) {
+                active_fds++;
+            }
+        }
+
+        if(active_fds) {
+            /* Don't block on the sockets if we have channels/listeners which
+               are ready */
+            timeout_remaining = 0;
+        }
+#ifdef HAVE_POLL
+
+#ifdef HAVE_LIBSSH2_GETTIMEOFDAY
+        {
+            struct timeval tv_begin, tv_end;
+
+            _libssh2_gettimeofday((struct timeval *) &tv_begin, NULL);
+            sysret = poll(sockets, nfds, timeout_remaining);
+            _libssh2_gettimeofday((struct timeval *) &tv_end, NULL);
+            timeout_remaining -= (tv_end.tv_sec - tv_begin.tv_sec) * 1000;
+            timeout_remaining -= (tv_end.tv_usec - tv_begin.tv_usec) / 1000;
+        }
+#else
+        /* If the platform doesn't support gettimeofday,
+         * then just make the call non-blocking and walk away
+         */
+        sysret = poll(sockets, nfds, timeout_remaining);
+        timeout_remaining = 0;
+#endif /* HAVE_GETTIMEOFDAY */
+
+        if(sysret > 0) {
+            for(i = 0; i < nfds; i++) {
+                switch(fds[i].type) {
+                case LIBSSH2_POLLFD_SOCKET:
+                    fds[i].revents = sockets[i].revents;
+                    sockets[i].revents = 0; /* In case we loop again, be
+                                               nice */
+                    if(fds[i].revents) {
+                        active_fds++;
+                    }
+                    break;
+                case LIBSSH2_POLLFD_CHANNEL:
+                    if(sockets[i].events & POLLIN) {
+                        /* Spin session until no data available */
+                        while(_libssh2_transport_read(fds[i].fd.
+                                                      channel->session)
+                              > 0);
+                    }
+                    if(sockets[i].revents & POLLHUP) {
+                        fds[i].revents |=
+                            LIBSSH2_POLLFD_CHANNEL_CLOSED |
+                            LIBSSH2_POLLFD_SESSION_CLOSED;
+                    }
+                    sockets[i].revents = 0;
+                    break;
+                case LIBSSH2_POLLFD_LISTENER:
+                    if(sockets[i].events & POLLIN) {
+                        /* Spin session until no data available */
+                        while(_libssh2_transport_read(fds[i].fd.
+                                                      listener->session)
+                              > 0);
+                    }
+                    if(sockets[i].revents & POLLHUP) {
+                        fds[i].revents |=
+                            LIBSSH2_POLLFD_LISTENER_CLOSED |
+                            LIBSSH2_POLLFD_SESSION_CLOSED;
+                    }
+                    sockets[i].revents = 0;
+                    break;
+                }
+            }
+        }
+#elif defined(HAVE_SELECT)
+        tv.tv_sec = timeout_remaining / 1000;
+        tv.tv_usec = (timeout_remaining % 1000) * 1000;
+#ifdef HAVE_LIBSSH2_GETTIMEOFDAY
+        {
+            struct timeval tv_begin, tv_end;
+
+            _libssh2_gettimeofday((struct timeval *) &tv_begin, NULL);
+            sysret = select(maxfd + 1, &rfds, &wfds, NULL, &tv);
+            _libssh2_gettimeofday((struct timeval *) &tv_end, NULL);
+
+            timeout_remaining -= (tv_end.tv_sec - tv_begin.tv_sec) * 1000;
+            timeout_remaining -= (tv_end.tv_usec - tv_begin.tv_usec) / 1000;
+        }
+#else
+        /* If the platform doesn't support gettimeofday,
+         * then just make the call non-blocking and walk away
+         */
+        sysret = select(maxfd + 1, &rfds, &wfds, NULL, &tv);
+        timeout_remaining = 0;
+#endif
+
+        if(sysret > 0) {
+            for(i = 0; i < nfds; i++) {
+                switch(fds[i].type) {
+                case LIBSSH2_POLLFD_SOCKET:
+                    if(FD_ISSET(fds[i].fd.socket, &rfds)) {
+                        fds[i].revents |= LIBSSH2_POLLFD_POLLIN;
+                    }
+                    if(FD_ISSET(fds[i].fd.socket, &wfds)) {
+                        fds[i].revents |= LIBSSH2_POLLFD_POLLOUT;
+                    }
+                    if(fds[i].revents) {
+                        active_fds++;
+                    }
+                    break;
+
+                case LIBSSH2_POLLFD_CHANNEL:
+                    if(FD_ISSET(fds[i].fd.channel->session->socket_fd,
+                                &rfds)) {
+                        /* Spin session until no data available */
+                        while(_libssh2_transport_read(fds[i].fd.
+                                                      channel->session)
+                              > 0);
+                    }
+                    break;
+
+                case LIBSSH2_POLLFD_LISTENER:
+                    if(FD_ISSET
+                        (fds[i].fd.listener->session->socket_fd, &rfds)) {
+                        /* Spin session until no data available */
+                        while(_libssh2_transport_read(fds[i].fd.
+                                                      listener->session)
+                              > 0);
+                    }
+                    break;
+                }
+            }
+        }
+#endif /* else no select() or poll() -- timeout (and by extension
+        * timeout_remaining) will be equal to 0 */
+    } while((timeout_remaining > 0) && !active_fds);
+
+    return active_fds;
+}
+
+/*
+ * libssh2_session_block_directions
+ *
+ * Get blocked direction when a function returns LIBSSH2_ERROR_EAGAIN
+ * Returns LIBSSH2_SOCKET_BLOCK_INBOUND if recv() blocked
+ * or LIBSSH2_SOCKET_BLOCK_OUTBOUND if send() blocked
+ */
+LIBSSH2_API int
+libssh2_session_block_directions(LIBSSH2_SESSION *session)
+{
+    return session->socket_block_directions;
+}
+
+/* libssh2_session_banner_get
+ * Get the remote banner (server ID string)
+ */
+
+LIBSSH2_API const char *
+libssh2_session_banner_get(LIBSSH2_SESSION *session)
+{
+    /* to avoid a coredump when session is NULL */
+    if(NULL == session)
+        return NULL;
+
+    if(NULL == session->remote.banner)
+        return NULL;
+
+    return (const char *) session->remote.banner;
+}

+ 93 - 0
libssh2/libssh2/src/session.h

@@ -0,0 +1,93 @@
+#ifndef LIBSSH2_SESSION_H
+#define LIBSSH2_SESSION_H
+/* Copyright (c) 2004-2007 Sara Golemon <sarag@libssh2.org>
+ * Copyright (c) 2009-2010 by Daniel Stenberg
+ * Copyright (c) 2010 Simon Josefsson <simon@josefsson.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms,
+ * with or without modification, are permitted provided
+ * that the following conditions are met:
+ *
+ *   Redistributions of source code must retain the above
+ *   copyright notice, this list of conditions and the
+ *   following disclaimer.
+ *
+ *   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.
+ *
+ *   Neither the name of the copyright holder nor the names
+ *   of any other contributors may be used to endorse or
+ *   promote products derived from this software without
+ *   specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+ * CONTRIBUTORS "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 COPYRIGHT OWNER OR
+ * CONTRIBUTORS 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.
+ */
+
+/* Conveniance-macros to allow code like this;
+
+   int rc = BLOCK_ADJUST(rc, session, session_startup(session, sock) );
+
+   int rc = BLOCK_ADJUST_ERRNO(ptr, session, session_startup(session, sock) );
+
+   The point of course being to make sure that while in non-blocking mode
+   these always return no matter what the return code is, but in blocking mode
+   it blocks if EAGAIN is the reason for the return from the underlying
+   function.
+
+*/
+#define BLOCK_ADJUST(rc, sess, x) \
+    do { \
+       time_t entry_time = time(NULL); \
+       do { \
+          rc = x; \
+          /* the order of the check below is important to properly deal with \
+             the case when the 'sess' is freed */ \
+          if((rc != LIBSSH2_ERROR_EAGAIN) || !sess->api_block_mode) \
+              break; \
+          rc = _libssh2_wait_socket(sess, entry_time);  \
+       } while(!rc);   \
+    } while(0)
+
+/*
+ * For functions that returns a pointer, we need to check if the API is
+ * non-blocking and return immediately. If the pointer is non-NULL we return
+ * immediately. If the API is blocking and we get a NULL we check the errno
+ * and *only* if that is EAGAIN we loop and wait for socket action.
+ */
+#define BLOCK_ADJUST_ERRNO(ptr, sess, x) \
+    do { \
+       time_t entry_time = time(NULL); \
+       int rc; \
+       do { \
+           ptr = x; \
+           if(!sess->api_block_mode || \
+              (ptr != NULL) || \
+              (libssh2_session_last_errno(sess) != LIBSSH2_ERROR_EAGAIN) ) \
+               break; \
+           rc = _libssh2_wait_socket(sess, entry_time); \
+        } while(!rc); \
+    } while(0)
+
+
+int _libssh2_wait_socket(LIBSSH2_SESSION *session, time_t entry_time);
+
+/* this is the lib-internal set blocking function */
+int _libssh2_session_set_blocking(LIBSSH2_SESSION * session, int blocking);
+
+#endif /* LIBSSH2_SESSION_H */

+ 3755 - 0
libssh2/libssh2/src/sftp.c

@@ -0,0 +1,3755 @@
+/* Copyright (c) 2004-2008, Sara Golemon <sarag@libssh2.org>
+ * Copyright (c) 2007 Eli Fant <elifantu@mail.ru>
+ * Copyright (c) 2009-2019 by Daniel Stenberg
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms,
+ * with or without modification, are permitted provided
+ * that the following conditions are met:
+ *
+ *   Redistributions of source code must retain the above
+ *   copyright notice, this list of conditions and the
+ *   following disclaimer.
+ *
+ *   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.
+ *
+ *   Neither the name of the copyright holder nor the names
+ *   of any other contributors may be used to endorse or
+ *   promote products derived from this software without
+ *   specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+ * CONTRIBUTORS "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 COPYRIGHT OWNER OR
+ * CONTRIBUTORS 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 <assert.h>
+
+#include "libssh2_priv.h"
+#include "libssh2_sftp.h"
+#include "channel.h"
+#include "session.h"
+#include "sftp.h"
+
+/* Note: Version 6 was documented at the time of writing
+ * However it was marked as "DO NOT IMPLEMENT" due to pending changes
+ *
+ * This release of libssh2 implements Version 5 with automatic downgrade
+ * based on server's declaration
+ */
+
+/* SFTP packet types */
+#define SSH_FXP_INIT                            1
+#define SSH_FXP_VERSION                         2
+#define SSH_FXP_OPEN                            3
+#define SSH_FXP_CLOSE                           4
+#define SSH_FXP_READ                            5
+#define SSH_FXP_WRITE                           6
+#define SSH_FXP_LSTAT                           7
+#define SSH_FXP_FSTAT                           8
+#define SSH_FXP_SETSTAT                         9
+#define SSH_FXP_FSETSTAT                        10
+#define SSH_FXP_OPENDIR                         11
+#define SSH_FXP_READDIR                         12
+#define SSH_FXP_REMOVE                          13
+#define SSH_FXP_MKDIR                           14
+#define SSH_FXP_RMDIR                           15
+#define SSH_FXP_REALPATH                        16
+#define SSH_FXP_STAT                            17
+#define SSH_FXP_RENAME                          18
+#define SSH_FXP_READLINK                        19
+#define SSH_FXP_SYMLINK                         20
+#define SSH_FXP_STATUS                          101
+#define SSH_FXP_HANDLE                          102
+#define SSH_FXP_DATA                            103
+#define SSH_FXP_NAME                            104
+#define SSH_FXP_ATTRS                           105
+#define SSH_FXP_EXTENDED                        200
+#define SSH_FXP_EXTENDED_REPLY                  201
+
+/* S_IFREG */
+#define LIBSSH2_SFTP_ATTR_PFILETYPE_FILE        0100000
+/* S_IFDIR */
+#define LIBSSH2_SFTP_ATTR_PFILETYPE_DIR         0040000
+
+#define SSH_FXE_STATVFS_ST_RDONLY               0x00000001
+#define SSH_FXE_STATVFS_ST_NOSUID               0x00000002
+
+/* This is the maximum packet length to accept, as larger than this indicate
+   some kind of server problem. */
+#define LIBSSH2_SFTP_PACKET_MAXLEN  (256 * 1024)
+
+static int sftp_packet_ask(LIBSSH2_SFTP *sftp, unsigned char packet_type,
+                           uint32_t request_id, unsigned char **data,
+                           size_t *data_len);
+static void sftp_packet_flush(LIBSSH2_SFTP *sftp);
+
+/* sftp_attrsize
+ * Size that attr with this flagset will occupy when turned into a bin struct
+ */
+static int sftp_attrsize(unsigned long flags)
+{
+    return (4 +                                 /* flags(4) */
+            ((flags & LIBSSH2_SFTP_ATTR_SIZE) ? 8 : 0) +
+            ((flags & LIBSSH2_SFTP_ATTR_UIDGID) ? 8 : 0) +
+            ((flags & LIBSSH2_SFTP_ATTR_PERMISSIONS) ? 4 : 0) +
+            ((flags & LIBSSH2_SFTP_ATTR_ACMODTIME) ? 8 : 0));
+    /* atime + mtime as u32 */
+}
+
+/* _libssh2_store_u64
+ */
+static void _libssh2_store_u64(unsigned char **ptr, libssh2_uint64_t value)
+{
+    uint32_t msl = (uint32_t)(value >> 32);
+    unsigned char *buf = *ptr;
+
+    buf[0] = (unsigned char)((msl >> 24) & 0xFF);
+    buf[1] = (unsigned char)((msl >> 16) & 0xFF);
+    buf[2] = (unsigned char)((msl >> 8)  & 0xFF);
+    buf[3] = (unsigned char)( msl        & 0xFF);
+
+    buf[4] = (unsigned char)((value >> 24) & 0xFF);
+    buf[5] = (unsigned char)((value >> 16) & 0xFF);
+    buf[6] = (unsigned char)((value >> 8)  & 0xFF);
+    buf[7] = (unsigned char)( value        & 0xFF);
+
+    *ptr += 8;
+}
+
+/*
+ * Search list of zombied FXP_READ request IDs.
+ *
+ * Returns NULL if ID not in list.
+ */
+static struct sftp_zombie_requests *
+find_zombie_request(LIBSSH2_SFTP *sftp, uint32_t request_id)
+{
+    struct sftp_zombie_requests *zombie =
+        _libssh2_list_first(&sftp->zombie_requests);
+
+    while(zombie) {
+        if(zombie->request_id == request_id)
+            break;
+        else
+            zombie = _libssh2_list_next(&zombie->node);
+    }
+
+    return zombie;
+}
+
+static void
+remove_zombie_request(LIBSSH2_SFTP *sftp, uint32_t request_id)
+{
+    LIBSSH2_SESSION *session = sftp->channel->session;
+
+    struct sftp_zombie_requests *zombie = find_zombie_request(sftp,
+                                                              request_id);
+    if(zombie) {
+        _libssh2_debug(session, LIBSSH2_TRACE_SFTP,
+                       "Removing request ID %ld from the list of "
+                       "zombie requests",
+                       request_id);
+
+        _libssh2_list_remove(&zombie->node);
+        LIBSSH2_FREE(session, zombie);
+    }
+}
+
+static int
+add_zombie_request(LIBSSH2_SFTP *sftp, uint32_t request_id)
+{
+    LIBSSH2_SESSION *session = sftp->channel->session;
+
+    struct sftp_zombie_requests *zombie;
+
+    _libssh2_debug(session, LIBSSH2_TRACE_SFTP,
+                   "Marking request ID %ld as a zombie request", request_id);
+
+    zombie = LIBSSH2_ALLOC(sftp->channel->session,
+                           sizeof(struct sftp_zombie_requests));
+    if(!zombie)
+        return _libssh2_error(session, LIBSSH2_ERROR_ALLOC,
+                              "malloc fail for zombie request  ID");
+    else {
+        zombie->request_id = request_id;
+        _libssh2_list_add(&sftp->zombie_requests, &zombie->node);
+        return LIBSSH2_ERROR_NONE;
+    }
+}
+
+/*
+ * sftp_packet_add
+ *
+ * Add a packet to the SFTP packet brigade
+ */
+static int
+sftp_packet_add(LIBSSH2_SFTP *sftp, unsigned char *data,
+                size_t data_len)
+{
+    LIBSSH2_SESSION *session = sftp->channel->session;
+    LIBSSH2_SFTP_PACKET *packet;
+    uint32_t request_id;
+
+    if(data_len < 5) {
+        return LIBSSH2_ERROR_OUT_OF_BOUNDARY;
+    }
+
+    _libssh2_debug(session, LIBSSH2_TRACE_SFTP,
+                   "Received packet type %d (len %d)",
+                   (int) data[0], data_len);
+
+    /*
+     * Experience shows that if we mess up EAGAIN handling somewhere or
+     * otherwise get out of sync with the channel, this is where we first get
+     * a wrong byte and if so we need to bail out at once to aid tracking the
+     * problem better.
+     */
+
+    switch(data[0]) {
+    case SSH_FXP_INIT:
+    case SSH_FXP_VERSION:
+    case SSH_FXP_OPEN:
+    case SSH_FXP_CLOSE:
+    case SSH_FXP_READ:
+    case SSH_FXP_WRITE:
+    case SSH_FXP_LSTAT:
+    case SSH_FXP_FSTAT:
+    case SSH_FXP_SETSTAT:
+    case SSH_FXP_FSETSTAT:
+    case SSH_FXP_OPENDIR:
+    case SSH_FXP_READDIR:
+    case SSH_FXP_REMOVE:
+    case SSH_FXP_MKDIR:
+    case SSH_FXP_RMDIR:
+    case SSH_FXP_REALPATH:
+    case SSH_FXP_STAT:
+    case SSH_FXP_RENAME:
+    case SSH_FXP_READLINK:
+    case SSH_FXP_SYMLINK:
+    case SSH_FXP_STATUS:
+    case SSH_FXP_HANDLE:
+    case SSH_FXP_DATA:
+    case SSH_FXP_NAME:
+    case SSH_FXP_ATTRS:
+    case SSH_FXP_EXTENDED:
+    case SSH_FXP_EXTENDED_REPLY:
+        break;
+    default:
+        return _libssh2_error(session, LIBSSH2_ERROR_SFTP_PROTOCOL,
+                              "Out of sync with the world");
+    }
+
+    request_id = _libssh2_ntohu32(&data[1]);
+
+    _libssh2_debug(session, LIBSSH2_TRACE_SFTP, "Received packet id %d",
+                   request_id);
+
+    /* Don't add the packet if it answers a request we've given up on. */
+    if((data[0] == SSH_FXP_STATUS || data[0] == SSH_FXP_DATA)
+       && find_zombie_request(sftp, request_id)) {
+
+        /* If we get here, the file ended before the response arrived. We
+           are no longer interested in the request so we discard it */
+
+        LIBSSH2_FREE(session, data);
+
+        remove_zombie_request(sftp, request_id);
+        return LIBSSH2_ERROR_NONE;
+    }
+
+    packet = LIBSSH2_ALLOC(session, sizeof(LIBSSH2_SFTP_PACKET));
+    if(!packet) {
+        return _libssh2_error(session, LIBSSH2_ERROR_ALLOC,
+                              "Unable to allocate datablock for SFTP packet");
+    }
+
+    packet->data = data;
+    packet->data_len = data_len;
+    packet->request_id = request_id;
+
+    _libssh2_list_add(&sftp->packets, &packet->node);
+
+    return LIBSSH2_ERROR_NONE;
+}
+
+/*
+ * sftp_packet_read
+ *
+ * Frame an SFTP packet off the channel
+ */
+static int
+sftp_packet_read(LIBSSH2_SFTP *sftp)
+{
+    LIBSSH2_CHANNEL *channel = sftp->channel;
+    LIBSSH2_SESSION *session = channel->session;
+    unsigned char *packet = NULL;
+    ssize_t rc;
+    unsigned long recv_window;
+    int packet_type;
+
+    _libssh2_debug(session, LIBSSH2_TRACE_SFTP, "recv packet");
+
+    switch(sftp->packet_state) {
+    case libssh2_NB_state_sent: /* EAGAIN from window adjusting */
+        sftp->packet_state = libssh2_NB_state_idle;
+
+        packet = sftp->partial_packet;
+        goto window_adjust;
+
+    case libssh2_NB_state_sent1: /* EAGAIN from channel read */
+        sftp->packet_state = libssh2_NB_state_idle;
+
+        packet = sftp->partial_packet;
+
+        _libssh2_debug(session, LIBSSH2_TRACE_SFTP,
+                       "partial read cont, len: %lu", sftp->partial_len);
+        _libssh2_debug(session, LIBSSH2_TRACE_SFTP,
+                       "partial read cont, already recvd: %lu",
+                       sftp->partial_received);
+        /* fall-through */
+    default:
+        if(!packet) {
+            /* only do this if there's not already a packet buffer allocated
+               to use */
+
+            /* each packet starts with a 32 bit length field */
+            rc = _libssh2_channel_read(channel, 0,
+                                       (char *)&sftp->partial_size[
+                                           sftp->partial_size_len],
+                                       4 - sftp->partial_size_len);
+            if(rc == LIBSSH2_ERROR_EAGAIN)
+                return rc;
+            else if(rc < 0)
+                return _libssh2_error(session, rc, "channel read");
+
+            sftp->partial_size_len += rc;
+
+            if(4 != sftp->partial_size_len)
+                /* we got a short read for the length part */
+                return LIBSSH2_ERROR_EAGAIN;
+
+            sftp->partial_len = _libssh2_ntohu32(sftp->partial_size);
+            /* make sure we don't proceed if the packet size is unreasonably
+               large */
+            if(sftp->partial_len > LIBSSH2_SFTP_PACKET_MAXLEN) {
+                libssh2_channel_flush(channel);
+                sftp->partial_size_len = 0;
+                return _libssh2_error(session,
+                                      LIBSSH2_ERROR_CHANNEL_PACKET_EXCEEDED,
+                                      "SFTP packet too large");
+            }
+
+            if(sftp->partial_len == 0)
+                return _libssh2_error(session,
+                                      LIBSSH2_ERROR_ALLOC,
+                                      "Unable to allocate empty SFTP packet");
+
+            _libssh2_debug(session, LIBSSH2_TRACE_SFTP,
+                           "Data begin - Packet Length: %lu",
+                           sftp->partial_len);
+            packet = LIBSSH2_ALLOC(session, sftp->partial_len);
+            if(!packet)
+                return _libssh2_error(session, LIBSSH2_ERROR_ALLOC,
+                                      "Unable to allocate SFTP packet");
+            sftp->partial_size_len = 0;
+            sftp->partial_received = 0; /* how much of the packet already
+                                           received */
+            sftp->partial_packet = packet;
+
+          window_adjust:
+            recv_window = libssh2_channel_window_read_ex(channel, NULL, NULL);
+
+            if(sftp->partial_len > recv_window) {
+                /* ask for twice the data amount we need at once */
+                rc = _libssh2_channel_receive_window_adjust(channel,
+                                                            sftp->partial_len
+                                                            * 2,
+                                                            1, NULL);
+                /* store the state so that we continue with the correct
+                   operation at next invoke */
+                sftp->packet_state = (rc == LIBSSH2_ERROR_EAGAIN)?
+                    libssh2_NB_state_sent:
+                    libssh2_NB_state_idle;
+
+                if(rc == LIBSSH2_ERROR_EAGAIN)
+                    return rc;
+            }
+        }
+
+        /* Read as much of the packet as we can */
+        while(sftp->partial_len > sftp->partial_received) {
+            rc = _libssh2_channel_read(channel, 0,
+                                       (char *)&packet[sftp->partial_received],
+                                       sftp->partial_len -
+                                       sftp->partial_received);
+
+            if(rc == LIBSSH2_ERROR_EAGAIN) {
+                /*
+                 * We received EAGAIN, save what we have and return EAGAIN to
+                 * the caller. Set 'partial_packet' so that this function
+                 * knows how to continue on the next invoke.
+                 */
+                sftp->packet_state = libssh2_NB_state_sent1;
+                return rc;
+            }
+            else if(rc < 0) {
+                LIBSSH2_FREE(session, packet);
+                sftp->partial_packet = NULL;
+                return _libssh2_error(session, rc,
+                                      "Error waiting for SFTP packet");
+            }
+            sftp->partial_received += rc;
+        }
+
+        sftp->partial_packet = NULL;
+
+        /* sftp_packet_add takes ownership of the packet and might free it
+           so we take a copy of the packet type before we call it. */
+        packet_type = packet[0];
+        rc = sftp_packet_add(sftp, packet, sftp->partial_len);
+        if(rc) {
+            LIBSSH2_FREE(session, packet);
+            return rc;
+        }
+        else {
+            return packet_type;
+        }
+    }
+    /* WON'T REACH */
+}
+/*
+ * sftp_packetlist_flush
+ *
+ * Remove all pending packets in the packet_list and the corresponding one(s)
+ * in the SFTP packet brigade.
+ */
+static void sftp_packetlist_flush(LIBSSH2_SFTP_HANDLE *handle)
+{
+    struct sftp_pipeline_chunk *chunk;
+    LIBSSH2_SFTP *sftp = handle->sftp;
+    LIBSSH2_SESSION *session = sftp->channel->session;
+
+    /* remove pending packets, if any */
+    chunk = _libssh2_list_first(&handle->packet_list);
+    while(chunk) {
+        unsigned char *data;
+        size_t data_len;
+        int rc;
+        struct sftp_pipeline_chunk *next = _libssh2_list_next(&chunk->node);
+
+        rc = sftp_packet_ask(sftp, SSH_FXP_STATUS,
+                             chunk->request_id, &data, &data_len);
+        if(rc)
+            rc = sftp_packet_ask(sftp, SSH_FXP_DATA,
+                                 chunk->request_id, &data, &data_len);
+
+        if(!rc)
+            /* we found a packet, free it */
+            LIBSSH2_FREE(session, data);
+        else if(chunk->sent)
+            /* there was no incoming packet for this request, mark this
+               request as a zombie if it ever sent the request */
+            add_zombie_request(sftp, chunk->request_id);
+
+        _libssh2_list_remove(&chunk->node);
+        LIBSSH2_FREE(session, chunk);
+        chunk = next;
+    }
+}
+
+
+/*
+ * sftp_packet_ask()
+ *
+ * Checks if there's a matching SFTP packet available.
+ */
+static int
+sftp_packet_ask(LIBSSH2_SFTP *sftp, unsigned char packet_type,
+                uint32_t request_id, unsigned char **data,
+                size_t *data_len)
+{
+    LIBSSH2_SESSION *session = sftp->channel->session;
+    LIBSSH2_SFTP_PACKET *packet = _libssh2_list_first(&sftp->packets);
+
+    if(!packet)
+        return -1;
+
+    /* Special consideration when getting VERSION packet */
+
+    while(packet) {
+        if((packet->data[0] == packet_type) &&
+           ((packet_type == SSH_FXP_VERSION) ||
+            (packet->request_id == request_id))) {
+
+            /* Match! Fetch the data */
+            *data = packet->data;
+            *data_len = packet->data_len;
+
+            /* unlink and free this struct */
+            _libssh2_list_remove(&packet->node);
+            LIBSSH2_FREE(session, packet);
+
+            return 0;
+        }
+        /* check next struct in the list */
+        packet = _libssh2_list_next(&packet->node);
+    }
+    return -1;
+}
+
+/* sftp_packet_require
+ * A la libssh2_packet_require
+ */
+static int
+sftp_packet_require(LIBSSH2_SFTP *sftp, unsigned char packet_type,
+                    uint32_t request_id, unsigned char **data,
+                    size_t *data_len, size_t required_size)
+{
+    LIBSSH2_SESSION *session = sftp->channel->session;
+    int rc;
+
+    if(data == NULL || data_len == NULL || required_size == 0) {
+        return LIBSSH2_ERROR_BAD_USE;
+    }
+
+    _libssh2_debug(session, LIBSSH2_TRACE_SFTP, "Requiring packet %d id %ld",
+                   (int) packet_type, request_id);
+
+    if(sftp_packet_ask(sftp, packet_type, request_id, data, data_len) == 0) {
+        /* The right packet was available in the packet brigade */
+        _libssh2_debug(session, LIBSSH2_TRACE_SFTP, "Got %d",
+                       (int) packet_type);
+
+        if (*data_len < required_size) {
+            return LIBSSH2_ERROR_BUFFER_TOO_SMALL;
+        }
+
+        return LIBSSH2_ERROR_NONE;
+    }
+
+    while(session->socket_state == LIBSSH2_SOCKET_CONNECTED) {
+        rc = sftp_packet_read(sftp);
+        if(rc < 0)
+            return rc;
+
+        /* data was read, check the queue again */
+        if(!sftp_packet_ask(sftp, packet_type, request_id, data, data_len)) {
+            /* The right packet was available in the packet brigade */
+            _libssh2_debug(session, LIBSSH2_TRACE_SFTP, "Got %d",
+                           (int) packet_type);
+
+            if (*data_len < required_size) {
+                return LIBSSH2_ERROR_BUFFER_TOO_SMALL;
+            }
+
+            return LIBSSH2_ERROR_NONE;
+        }
+    }
+
+    /* Only reached if the socket died */
+    return LIBSSH2_ERROR_SOCKET_DISCONNECT;
+}
+
+/* sftp_packet_requirev
+ * Require one of N possible responses
+ */
+static int
+sftp_packet_requirev(LIBSSH2_SFTP *sftp, int num_valid_responses,
+                     const unsigned char *valid_responses,
+                     uint32_t request_id, unsigned char **data,
+                     size_t *data_len, size_t required_size)
+{
+    int i;
+    int rc;
+
+    if(data == NULL || data_len == NULL || required_size == 0) {
+        return LIBSSH2_ERROR_BAD_USE;
+    }
+
+    /* If no timeout is active, start a new one */
+    if(sftp->requirev_start == 0)
+        sftp->requirev_start = time(NULL);
+
+    while(sftp->channel->session->socket_state == LIBSSH2_SOCKET_CONNECTED) {
+        for(i = 0; i < num_valid_responses; i++) {
+            if(sftp_packet_ask(sftp, valid_responses[i], request_id,
+                                data, data_len) == 0) {
+                /*
+                 * Set to zero before all returns to say
+                 * the timeout is not active
+                 */
+                sftp->requirev_start = 0;
+
+                if (*data_len < required_size) {
+                    return LIBSSH2_ERROR_BUFFER_TOO_SMALL;
+                }
+
+                return LIBSSH2_ERROR_NONE;
+            }
+        }
+
+        rc = sftp_packet_read(sftp);
+        if((rc < 0) && (rc != LIBSSH2_ERROR_EAGAIN)) {
+            sftp->requirev_start = 0;
+            return rc;
+        }
+        else if(rc <= 0) {
+            /* prevent busy-looping */
+            long left =
+                LIBSSH2_READ_TIMEOUT -
+                (long)(time(NULL) - sftp->requirev_start);
+
+            if(left <= 0) {
+                sftp->requirev_start = 0;
+                return LIBSSH2_ERROR_TIMEOUT;
+            }
+            else if(rc == LIBSSH2_ERROR_EAGAIN) {
+                return rc;
+            }
+        }
+    }
+
+    sftp->requirev_start = 0;
+
+    /* Only reached if the socket died */
+    return LIBSSH2_ERROR_SOCKET_DISCONNECT;
+}
+
+/* sftp_attr2bin
+ * Populate attributes into an SFTP block
+ */
+static ssize_t
+sftp_attr2bin(unsigned char *p, const LIBSSH2_SFTP_ATTRIBUTES * attrs)
+{
+    unsigned char *s = p;
+    uint32_t flag_mask =
+        LIBSSH2_SFTP_ATTR_SIZE | LIBSSH2_SFTP_ATTR_UIDGID |
+        LIBSSH2_SFTP_ATTR_PERMISSIONS | LIBSSH2_SFTP_ATTR_ACMODTIME;
+
+    /* TODO: When we add SFTP4+ functionality flag_mask can get additional
+       bits */
+
+    if(!attrs) {
+        _libssh2_htonu32(s, 0);
+        return 4;
+    }
+
+    _libssh2_store_u32(&s, attrs->flags & flag_mask);
+
+    if(attrs->flags & LIBSSH2_SFTP_ATTR_SIZE) {
+        _libssh2_store_u64(&s, attrs->filesize);
+    }
+
+    if(attrs->flags & LIBSSH2_SFTP_ATTR_UIDGID) {
+        _libssh2_store_u32(&s, attrs->uid);
+        _libssh2_store_u32(&s, attrs->gid);
+    }
+
+    if(attrs->flags & LIBSSH2_SFTP_ATTR_PERMISSIONS) {
+        _libssh2_store_u32(&s, attrs->permissions);
+    }
+
+    if(attrs->flags & LIBSSH2_SFTP_ATTR_ACMODTIME) {
+        _libssh2_store_u32(&s, attrs->atime);
+        _libssh2_store_u32(&s, attrs->mtime);
+    }
+
+    return (s - p);
+}
+
+/* sftp_bin2attr
+ */
+static int
+sftp_bin2attr(LIBSSH2_SFTP_ATTRIBUTES *attrs, const unsigned char *p,
+              size_t data_len)
+{
+    struct string_buf buf;
+    uint32_t flags = 0;
+    buf.data = (unsigned char *)p;
+    buf.dataptr = buf.data;
+    buf.len = data_len;
+
+    if(_libssh2_get_u32(&buf, &flags) != 0) {
+        return LIBSSH2_ERROR_BUFFER_TOO_SMALL;
+    }
+    attrs->flags = flags;
+
+    if(attrs->flags & LIBSSH2_SFTP_ATTR_SIZE) {
+        if(_libssh2_get_u64(&buf, &(attrs->filesize)) != 0) {
+            return LIBSSH2_ERROR_BUFFER_TOO_SMALL;
+        }
+    }
+
+    if(attrs->flags & LIBSSH2_SFTP_ATTR_UIDGID) {
+        uint32_t uid = 0;
+        uint32_t gid = 0;
+        if(_libssh2_get_u32(&buf, &uid) != 0 ||
+           _libssh2_get_u32(&buf, &gid) != 0) {
+            return LIBSSH2_ERROR_BUFFER_TOO_SMALL;
+        }
+        attrs->uid = uid;
+        attrs->gid = gid;
+    }
+
+    if(attrs->flags & LIBSSH2_SFTP_ATTR_PERMISSIONS) {
+        uint32_t permissions;
+        if(_libssh2_get_u32(&buf, &permissions) != 0) {
+            return LIBSSH2_ERROR_BUFFER_TOO_SMALL;
+        }
+        attrs->permissions = permissions;
+    }
+
+    if(attrs->flags & LIBSSH2_SFTP_ATTR_ACMODTIME) {
+        uint32_t atime;
+        uint32_t mtime;
+        if(_libssh2_get_u32(&buf, &atime) != 0 ||
+           _libssh2_get_u32(&buf, &mtime) != 0) {
+            return LIBSSH2_ERROR_BUFFER_TOO_SMALL;
+        }
+        attrs->atime = atime;
+        attrs->mtime = mtime;
+    }
+
+    return (buf.dataptr - buf.data);
+}
+
+/* ************
+ * SFTP API *
+ ************ */
+
+LIBSSH2_CHANNEL_CLOSE_FUNC(libssh2_sftp_dtor);
+
+/* libssh2_sftp_dtor
+ * Shutdown an SFTP stream when the channel closes
+ */
+LIBSSH2_CHANNEL_CLOSE_FUNC(libssh2_sftp_dtor)
+{
+    LIBSSH2_SFTP *sftp = (LIBSSH2_SFTP *) (*channel_abstract);
+
+    (void) session_abstract;
+    (void) channel;
+
+    /* Free the partial packet storage for sftp_packet_read */
+    if(sftp->partial_packet) {
+        LIBSSH2_FREE(session, sftp->partial_packet);
+    }
+
+    /* Free the packet storage for _libssh2_sftp_packet_readdir */
+    if(sftp->readdir_packet) {
+        LIBSSH2_FREE(session, sftp->readdir_packet);
+    }
+
+    LIBSSH2_FREE(session, sftp);
+}
+
+/*
+ * sftp_init
+ *
+ * Startup an SFTP session
+ */
+static LIBSSH2_SFTP *sftp_init(LIBSSH2_SESSION *session)
+{
+    unsigned char *data;
+    size_t data_len;
+    ssize_t rc;
+    LIBSSH2_SFTP *sftp_handle;
+    struct string_buf buf;
+    unsigned char *endp;
+
+    if(session->sftpInit_state == libssh2_NB_state_idle) {
+        _libssh2_debug(session, LIBSSH2_TRACE_SFTP,
+                       "Initializing SFTP subsystem");
+
+        /*
+         * The 'sftpInit_sftp' and 'sftpInit_channel' struct fields within the
+         * session struct are only to be used during the setup phase. As soon
+         * as the SFTP session is created they are cleared and can thus be
+         * re-used again to allow any amount of SFTP handles per sessions.
+         *
+         * Note that you MUST NOT try to call libssh2_sftp_init() again to get
+         * another handle until the previous call has finished and either
+         * successfully made a handle or failed and returned error (not
+         * including *EAGAIN).
+         */
+
+        assert(session->sftpInit_sftp == NULL);
+        session->sftpInit_sftp = NULL;
+        session->sftpInit_state = libssh2_NB_state_created;
+    }
+
+    sftp_handle = session->sftpInit_sftp;
+
+    if(session->sftpInit_state == libssh2_NB_state_created) {
+        session->sftpInit_channel =
+            _libssh2_channel_open(session, "session", sizeof("session") - 1,
+                                  LIBSSH2_CHANNEL_WINDOW_DEFAULT,
+                                  LIBSSH2_CHANNEL_PACKET_DEFAULT, NULL, 0);
+        if(!session->sftpInit_channel) {
+            if(libssh2_session_last_errno(session) == LIBSSH2_ERROR_EAGAIN) {
+                _libssh2_error(session, LIBSSH2_ERROR_EAGAIN,
+                               "Would block starting up channel");
+            }
+            else {
+                _libssh2_error(session, LIBSSH2_ERROR_CHANNEL_FAILURE,
+                               "Unable to startup channel");
+                session->sftpInit_state = libssh2_NB_state_idle;
+            }
+            return NULL;
+        }
+
+        session->sftpInit_state = libssh2_NB_state_sent;
+    }
+
+    if(session->sftpInit_state == libssh2_NB_state_sent) {
+        int ret = _libssh2_channel_process_startup(session->sftpInit_channel,
+                                                   "subsystem",
+                                                   sizeof("subsystem") - 1,
+                                                   "sftp",
+                                                   strlen("sftp"));
+        if(ret == LIBSSH2_ERROR_EAGAIN) {
+            _libssh2_error(session, LIBSSH2_ERROR_EAGAIN,
+                           "Would block to request SFTP subsystem");
+            return NULL;
+        }
+        else if(ret) {
+            _libssh2_error(session, LIBSSH2_ERROR_CHANNEL_FAILURE,
+                           "Unable to request SFTP subsystem");
+            goto sftp_init_error;
+        }
+
+        session->sftpInit_state = libssh2_NB_state_sent1;
+    }
+
+    if(session->sftpInit_state == libssh2_NB_state_sent1) {
+        rc = _libssh2_channel_extended_data(session->sftpInit_channel,
+                                         LIBSSH2_CHANNEL_EXTENDED_DATA_IGNORE);
+        if(rc == LIBSSH2_ERROR_EAGAIN) {
+            _libssh2_error(session, LIBSSH2_ERROR_EAGAIN,
+                           "Would block requesting handle extended data");
+            return NULL;
+        }
+
+        sftp_handle =
+            session->sftpInit_sftp =
+            LIBSSH2_CALLOC(session, sizeof(LIBSSH2_SFTP));
+        if(!sftp_handle) {
+            _libssh2_error(session, LIBSSH2_ERROR_ALLOC,
+                           "Unable to allocate a new SFTP structure");
+            goto sftp_init_error;
+        }
+        sftp_handle->channel = session->sftpInit_channel;
+        sftp_handle->request_id = 0;
+
+        _libssh2_htonu32(session->sftpInit_buffer, 5);
+        session->sftpInit_buffer[4] = SSH_FXP_INIT;
+        _libssh2_htonu32(session->sftpInit_buffer + 5, LIBSSH2_SFTP_VERSION);
+        session->sftpInit_sent = 0; /* nothing's sent yet */
+
+        _libssh2_debug(session, LIBSSH2_TRACE_SFTP,
+                       "Sending FXP_INIT packet advertising "
+                       "version %d support",
+                       (int) LIBSSH2_SFTP_VERSION);
+
+        session->sftpInit_state = libssh2_NB_state_sent2;
+    }
+
+    if(session->sftpInit_state == libssh2_NB_state_sent2) {
+        /* sent off what's left of the init buffer to send */
+        rc = _libssh2_channel_write(session->sftpInit_channel, 0,
+                                    session->sftpInit_buffer +
+                                    session->sftpInit_sent,
+                                    9 - session->sftpInit_sent);
+        if(rc == LIBSSH2_ERROR_EAGAIN) {
+            _libssh2_error(session, LIBSSH2_ERROR_EAGAIN,
+                           "Would block sending SSH_FXP_INIT");
+            return NULL;
+        }
+        else if(rc < 0) {
+            _libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND,
+                           "Unable to send SSH_FXP_INIT");
+            goto sftp_init_error;
+        }
+        else {
+            /* add up the number of bytes sent */
+            session->sftpInit_sent += rc;
+
+            if(session->sftpInit_sent == 9)
+                /* move on */
+                session->sftpInit_state = libssh2_NB_state_sent3;
+
+            /* if less than 9, we remain in this state to send more later on */
+        }
+    }
+
+    rc = sftp_packet_require(sftp_handle, SSH_FXP_VERSION,
+                             0, &data, &data_len, 5);
+    if(rc == LIBSSH2_ERROR_EAGAIN) {
+        _libssh2_error(session, LIBSSH2_ERROR_EAGAIN,
+                       "Would block receiving SSH_FXP_VERSION");
+        return NULL;
+    }
+    else if(rc == LIBSSH2_ERROR_BUFFER_TOO_SMALL) {
+        if(data_len > 0) {
+            LIBSSH2_FREE(session, data);
+        }
+        _libssh2_error(session, LIBSSH2_ERROR_SFTP_PROTOCOL,
+                       "Invalid SSH_FXP_VERSION response");
+        goto sftp_init_error;
+    }
+    else if(rc) {
+        _libssh2_error(session, rc,
+                       "Timeout waiting for response from SFTP subsystem");
+        goto sftp_init_error;
+    }
+
+    buf.data = data;
+    buf.dataptr = buf.data + 1;
+    buf.len = data_len;
+    endp = &buf.data[data_len];
+
+    if(_libssh2_get_u32(&buf, &(sftp_handle->version)) != 0) {
+        LIBSSH2_FREE(session, data);
+        rc = LIBSSH2_ERROR_BUFFER_TOO_SMALL;
+        goto sftp_init_error;
+    }
+
+    if(sftp_handle->version > LIBSSH2_SFTP_VERSION) {
+        _libssh2_debug(session, LIBSSH2_TRACE_SFTP,
+                       "Truncating remote SFTP version from %lu",
+                       sftp_handle->version);
+        sftp_handle->version = LIBSSH2_SFTP_VERSION;
+    }
+    _libssh2_debug(session, LIBSSH2_TRACE_SFTP,
+                   "Enabling SFTP version %lu compatibility",
+                   sftp_handle->version);
+    while(buf.dataptr < endp) {
+        unsigned char *extname, *extdata;
+
+        if(_libssh2_get_string(&buf, &extname, NULL)) {
+            LIBSSH2_FREE(session, data);
+            _libssh2_error(session, LIBSSH2_ERROR_BUFFER_TOO_SMALL,
+                           "Data too short when extracting extname");
+            goto sftp_init_error;
+        }
+
+        if(_libssh2_get_string(&buf, &extdata, NULL)) {
+            LIBSSH2_FREE(session, data);
+            _libssh2_error(session, LIBSSH2_ERROR_BUFFER_TOO_SMALL,
+                           "Data too short when extracting extdata");
+            goto sftp_init_error;
+        }
+    }
+    LIBSSH2_FREE(session, data);
+
+    /* Make sure that when the channel gets closed, the SFTP service is shut
+       down too */
+    sftp_handle->channel->abstract = sftp_handle;
+    sftp_handle->channel->close_cb = libssh2_sftp_dtor;
+
+    session->sftpInit_state = libssh2_NB_state_idle;
+
+    /* clear the sftp and channel pointers in this session struct now */
+    session->sftpInit_sftp = NULL;
+    session->sftpInit_channel = NULL;
+
+    _libssh2_list_init(&sftp_handle->sftp_handles);
+
+    return sftp_handle;
+
+  sftp_init_error:
+    while(_libssh2_channel_free(session->sftpInit_channel) ==
+           LIBSSH2_ERROR_EAGAIN);
+    session->sftpInit_channel = NULL;
+    if(session->sftpInit_sftp) {
+        LIBSSH2_FREE(session, session->sftpInit_sftp);
+        session->sftpInit_sftp = NULL;
+    }
+    session->sftpInit_state = libssh2_NB_state_idle;
+    return NULL;
+}
+
+/*
+ * libssh2_sftp_init
+ *
+ * Startup an SFTP session
+ */
+LIBSSH2_API LIBSSH2_SFTP *libssh2_sftp_init(LIBSSH2_SESSION *session)
+{
+    LIBSSH2_SFTP *ptr;
+
+    if(!session)
+        return NULL;
+
+    if(!(session->state & LIBSSH2_STATE_AUTHENTICATED)) {
+        _libssh2_error(session, LIBSSH2_ERROR_INVAL,
+                       "session not authenticated yet");
+        return NULL;
+    }
+
+    BLOCK_ADJUST_ERRNO(ptr, session, sftp_init(session));
+    return ptr;
+}
+
+/*
+ * sftp_shutdown
+ *
+ * Shuts down the SFTP subsystem
+ */
+static int
+sftp_shutdown(LIBSSH2_SFTP *sftp)
+{
+    int rc;
+    LIBSSH2_SESSION *session = sftp->channel->session;
+    /*
+     * Make sure all memory used in the state variables are free
+     */
+    if(sftp->partial_packet) {
+        LIBSSH2_FREE(session, sftp->partial_packet);
+        sftp->partial_packet = NULL;
+    }
+    if(sftp->open_packet) {
+        LIBSSH2_FREE(session, sftp->open_packet);
+        sftp->open_packet = NULL;
+    }
+    if(sftp->readdir_packet) {
+        LIBSSH2_FREE(session, sftp->readdir_packet);
+        sftp->readdir_packet = NULL;
+    }
+    if(sftp->fstat_packet) {
+        LIBSSH2_FREE(session, sftp->fstat_packet);
+        sftp->fstat_packet = NULL;
+    }
+    if(sftp->unlink_packet) {
+        LIBSSH2_FREE(session, sftp->unlink_packet);
+        sftp->unlink_packet = NULL;
+    }
+    if(sftp->rename_packet) {
+        LIBSSH2_FREE(session, sftp->rename_packet);
+        sftp->rename_packet = NULL;
+    }
+    if(sftp->fstatvfs_packet) {
+        LIBSSH2_FREE(session, sftp->fstatvfs_packet);
+        sftp->fstatvfs_packet = NULL;
+    }
+    if(sftp->statvfs_packet) {
+        LIBSSH2_FREE(session, sftp->statvfs_packet);
+        sftp->statvfs_packet = NULL;
+    }
+    if(sftp->mkdir_packet) {
+        LIBSSH2_FREE(session, sftp->mkdir_packet);
+        sftp->mkdir_packet = NULL;
+    }
+    if(sftp->rmdir_packet) {
+        LIBSSH2_FREE(session, sftp->rmdir_packet);
+        sftp->rmdir_packet = NULL;
+    }
+    if(sftp->stat_packet) {
+        LIBSSH2_FREE(session, sftp->stat_packet);
+        sftp->stat_packet = NULL;
+    }
+    if(sftp->symlink_packet) {
+        LIBSSH2_FREE(session, sftp->symlink_packet);
+        sftp->symlink_packet = NULL;
+    }
+    if(sftp->fsync_packet) {
+        LIBSSH2_FREE(session, sftp->fsync_packet);
+        sftp->fsync_packet = NULL;
+    }
+
+    sftp_packet_flush(sftp);
+
+    /* TODO: We should consider walking over the sftp_handles list and kill
+     * any remaining sftp handles ... */
+
+    rc = _libssh2_channel_free(sftp->channel);
+
+    return rc;
+}
+
+/* libssh2_sftp_shutdown
+ * Shutsdown the SFTP subsystem
+ */
+LIBSSH2_API int
+libssh2_sftp_shutdown(LIBSSH2_SFTP *sftp)
+{
+    int rc;
+    if(!sftp)
+        return LIBSSH2_ERROR_BAD_USE;
+    BLOCK_ADJUST(rc, sftp->channel->session, sftp_shutdown(sftp));
+    return rc;
+}
+
+/* *******************************
+ * SFTP File and Directory Ops *
+ ******************************* */
+
+/* sftp_open
+ */
+static LIBSSH2_SFTP_HANDLE *
+sftp_open(LIBSSH2_SFTP *sftp, const char *filename,
+          size_t filename_len, uint32_t flags, long mode,
+          int open_type)
+{
+    LIBSSH2_CHANNEL *channel = sftp->channel;
+    LIBSSH2_SESSION *session = channel->session;
+    LIBSSH2_SFTP_HANDLE *fp;
+    LIBSSH2_SFTP_ATTRIBUTES attrs = {
+        LIBSSH2_SFTP_ATTR_PERMISSIONS, 0, 0, 0, 0, 0, 0
+    };
+    unsigned char *s;
+    ssize_t rc;
+    int open_file = (open_type == LIBSSH2_SFTP_OPENFILE)?1:0;
+
+    if(sftp->open_state == libssh2_NB_state_idle) {
+        /* packet_len(4) + packet_type(1) + request_id(4) + filename_len(4) +
+           flags(4) */
+        sftp->open_packet_len = filename_len + 13 +
+            (open_file? (4 +
+                         sftp_attrsize(LIBSSH2_SFTP_ATTR_PERMISSIONS)) : 0);
+
+        /* surprise! this starts out with nothing sent */
+        sftp->open_packet_sent = 0;
+        s = sftp->open_packet = LIBSSH2_ALLOC(session, sftp->open_packet_len);
+        if(!sftp->open_packet) {
+            _libssh2_error(session, LIBSSH2_ERROR_ALLOC,
+                           "Unable to allocate memory for FXP_OPEN or "
+                           "FXP_OPENDIR packet");
+            return NULL;
+        }
+        /* Filetype in SFTP 3 and earlier */
+        attrs.permissions = mode |
+            (open_file ? LIBSSH2_SFTP_ATTR_PFILETYPE_FILE :
+             LIBSSH2_SFTP_ATTR_PFILETYPE_DIR);
+
+        _libssh2_store_u32(&s, sftp->open_packet_len - 4);
+        *(s++) = open_file? SSH_FXP_OPEN : SSH_FXP_OPENDIR;
+        sftp->open_request_id = sftp->request_id++;
+        _libssh2_store_u32(&s, sftp->open_request_id);
+        _libssh2_store_str(&s, filename, filename_len);
+
+        if(open_file) {
+            _libssh2_store_u32(&s, flags);
+            s += sftp_attr2bin(s, &attrs);
+        }
+
+        _libssh2_debug(session, LIBSSH2_TRACE_SFTP, "Sending %s open request",
+                       open_file? "file" : "directory");
+
+        sftp->open_state = libssh2_NB_state_created;
+    }
+
+    if(sftp->open_state == libssh2_NB_state_created) {
+        rc = _libssh2_channel_write(channel, 0, sftp->open_packet+
+                                    sftp->open_packet_sent,
+                                    sftp->open_packet_len -
+                                    sftp->open_packet_sent);
+        if(rc == LIBSSH2_ERROR_EAGAIN) {
+            _libssh2_error(session, LIBSSH2_ERROR_EAGAIN,
+                           "Would block sending FXP_OPEN or "
+                           "FXP_OPENDIR command");
+            return NULL;
+        }
+        else if(rc < 0) {
+            _libssh2_error(session, rc, "Unable to send FXP_OPEN*");
+            LIBSSH2_FREE(session, sftp->open_packet);
+            sftp->open_packet = NULL;
+            sftp->open_state = libssh2_NB_state_idle;
+            return NULL;
+        }
+
+        /* bump the sent counter and remain in this state until the whole
+           data is off */
+        sftp->open_packet_sent += rc;
+
+        if(sftp->open_packet_len == sftp->open_packet_sent) {
+            LIBSSH2_FREE(session, sftp->open_packet);
+            sftp->open_packet = NULL;
+
+            sftp->open_state = libssh2_NB_state_sent;
+        }
+    }
+
+    if(sftp->open_state == libssh2_NB_state_sent) {
+        size_t data_len;
+        unsigned char *data;
+        static const unsigned char fopen_responses[2] =
+            { SSH_FXP_HANDLE, SSH_FXP_STATUS };
+        rc = sftp_packet_requirev(sftp, 2, fopen_responses,
+                                  sftp->open_request_id, &data,
+                                  &data_len, 1);
+        if(rc == LIBSSH2_ERROR_EAGAIN) {
+            _libssh2_error(session, LIBSSH2_ERROR_EAGAIN,
+                           "Would block waiting for status message");
+            return NULL;
+        }
+        else if(rc == LIBSSH2_ERROR_BUFFER_TOO_SMALL) {
+            if(data_len > 0) {
+                LIBSSH2_FREE(session, data);
+            }
+            _libssh2_error(session, LIBSSH2_ERROR_SFTP_PROTOCOL,
+                           "Response too small");
+            return NULL;
+        }
+        sftp->open_state = libssh2_NB_state_idle;
+        if(rc) {
+            _libssh2_error(session, rc, "Timeout waiting for status message");
+            return NULL;
+        }
+
+        /* OPEN can basically get STATUS or HANDLE back, where HANDLE implies
+           a fine response while STATUS means error. It seems though that at
+           times we get an SSH_FX_OK back in a STATUS, followed the "real"
+           HANDLE so we need to properly deal with that. */
+        if(data[0] == SSH_FXP_STATUS) {
+            int badness = 1;
+
+            if(data_len < 9) {
+                _libssh2_error(session, LIBSSH2_ERROR_SFTP_PROTOCOL,
+                               "Too small FXP_STATUS");
+                LIBSSH2_FREE(session, data);
+                return NULL;
+            }
+
+            sftp->last_errno = _libssh2_ntohu32(data + 5);
+
+            if(LIBSSH2_FX_OK == sftp->last_errno) {
+                _libssh2_debug(session, LIBSSH2_TRACE_SFTP,
+                               "got HANDLE FXOK!");
+
+                LIBSSH2_FREE(session, data);
+
+                /* silly situation, but check for a HANDLE */
+                rc = sftp_packet_require(sftp, SSH_FXP_HANDLE,
+                                         sftp->open_request_id, &data,
+                                         &data_len, 10);
+                if(rc == LIBSSH2_ERROR_EAGAIN) {
+                    /* go back to sent state and wait for something else */
+                    sftp->open_state = libssh2_NB_state_sent;
+                    return NULL;
+                }
+                else if(rc == LIBSSH2_ERROR_BUFFER_TOO_SMALL) {
+                    if(data_len > 0) {
+                        LIBSSH2_FREE(session, data);
+                    }
+                    _libssh2_error(session, LIBSSH2_ERROR_SFTP_PROTOCOL,
+                                   "Too small FXP_HANDLE");
+                    return NULL;
+                }
+                else if(!rc)
+                    /* we got the handle so this is not a bad situation */
+                    badness = 0;
+            }
+
+            if(badness) {
+                _libssh2_error(session, LIBSSH2_ERROR_SFTP_PROTOCOL,
+                               "Failed opening remote file");
+                _libssh2_debug(session, LIBSSH2_TRACE_SFTP,
+                               "got FXP_STATUS %d",
+                               sftp->last_errno);
+                LIBSSH2_FREE(session, data);
+                return NULL;
+            }
+        }
+
+        if(data_len < 10) {
+            _libssh2_error(session, LIBSSH2_ERROR_SFTP_PROTOCOL,
+                           "Too small FXP_HANDLE");
+            LIBSSH2_FREE(session, data);
+            return NULL;
+        }
+
+        fp = LIBSSH2_CALLOC(session, sizeof(LIBSSH2_SFTP_HANDLE));
+        if(!fp) {
+            _libssh2_error(session, LIBSSH2_ERROR_ALLOC,
+                           "Unable to allocate new SFTP handle structure");
+            LIBSSH2_FREE(session, data);
+            return NULL;
+        }
+        fp->handle_type = open_file ? LIBSSH2_SFTP_HANDLE_FILE :
+            LIBSSH2_SFTP_HANDLE_DIR;
+
+        fp->handle_len = _libssh2_ntohu32(data + 5);
+        if(fp->handle_len > SFTP_HANDLE_MAXLEN)
+            /* SFTP doesn't allow handles longer than 256 characters */
+            fp->handle_len = SFTP_HANDLE_MAXLEN;
+
+        if(fp->handle_len > (data_len - 9))
+            /* do not reach beyond the end of the data we got */
+            fp->handle_len = data_len - 9;
+
+        memcpy(fp->handle, data + 9, fp->handle_len);
+
+        LIBSSH2_FREE(session, data);
+
+        /* add this file handle to the list kept in the sftp session */
+        _libssh2_list_add(&sftp->sftp_handles, &fp->node);
+
+        fp->sftp = sftp; /* point to the parent struct */
+
+        fp->u.file.offset = 0;
+        fp->u.file.offset_sent = 0;
+
+        _libssh2_debug(session, LIBSSH2_TRACE_SFTP, "Open command successful");
+        return fp;
+    }
+    return NULL;
+}
+
+/* libssh2_sftp_open_ex
+ */
+LIBSSH2_API LIBSSH2_SFTP_HANDLE *
+libssh2_sftp_open_ex(LIBSSH2_SFTP *sftp, const char *filename,
+                     unsigned int filename_len, unsigned long flags, long mode,
+                     int open_type)
+{
+    LIBSSH2_SFTP_HANDLE *hnd;
+
+    if(!sftp)
+        return NULL;
+
+    BLOCK_ADJUST_ERRNO(hnd, sftp->channel->session,
+                       sftp_open(sftp, filename, filename_len, flags, mode,
+                                 open_type));
+    return hnd;
+}
+
+/*
+ * sftp_read
+ *
+ * Read from an SFTP file handle
+ *
+ */
+static ssize_t sftp_read(LIBSSH2_SFTP_HANDLE * handle, char *buffer,
+                         size_t buffer_size)
+{
+    LIBSSH2_SFTP *sftp = handle->sftp;
+    LIBSSH2_CHANNEL *channel = sftp->channel;
+    LIBSSH2_SESSION *session = channel->session;
+    size_t count = 0;
+    struct sftp_pipeline_chunk *chunk;
+    struct sftp_pipeline_chunk *next;
+    ssize_t rc;
+    struct _libssh2_sftp_handle_file_data *filep =
+        &handle->u.file;
+    size_t bytes_in_buffer = 0;
+    char *sliding_bufferp = buffer;
+
+    /* This function can be interrupted in three different places where it
+       might need to wait for data from the network.  It returns EAGAIN to
+       allow non-blocking clients to do other work but these client are
+       expected to call this function again (possibly many times) to finish
+       the operation.
+
+       The tricky part is that if we previously aborted a sftp_read due to
+       EAGAIN, we must continue at the same spot to continue the previously
+       interrupted operation.  This is done using a state machine to record
+       what phase of execution we were at.  The state is stored in
+       sftp->read_state.
+
+       libssh2_NB_state_idle: The first phase is where we prepare multiple
+       FXP_READ packets to do optimistic read-ahead.  We send off as many as
+       possible in the second phase without waiting for a response to each
+       one; this is the key to fast reads. But we may have to adjust the
+       channel window size to do this which may interrupt this function while
+       waiting.  The state machine saves the phase as libssh2_NB_state_idle so
+       it returns here on the next call.
+
+       libssh2_NB_state_sent: The second phase is where we send the FXP_READ
+       packets.  Writing them to the channel can be interrupted with EAGAIN
+       but the state machine ensures we skip the first phase on the next call
+       and resume sending.
+
+       libssh2_NB_state_sent2: In the third phase (indicated by ) we read the
+       data from the responses that have arrived so far.  Reading can be
+       interrupted with EAGAIN but the state machine ensures we skip the first
+       and second phases on the next call and resume sending.
+    */
+
+    switch(sftp->read_state) {
+    case libssh2_NB_state_idle:
+
+        /* Some data may already have been read from the server in the
+           previous call but didn't fit in the buffer at the time.  If so, we
+           return that now as we can't risk being interrupted later with data
+           partially written to the buffer. */
+        if(filep->data_left) {
+            size_t copy = MIN(buffer_size, filep->data_left);
+
+            memcpy(buffer, &filep->data[ filep->data_len - filep->data_left],
+                   copy);
+
+            filep->data_left -= copy;
+            filep->offset += copy;
+
+            if(!filep->data_left) {
+                LIBSSH2_FREE(session, filep->data);
+                filep->data = NULL;
+            }
+
+            return copy;
+        }
+
+        if(filep->eof) {
+            return 0;
+        }
+        else {
+            /* We allow a number of bytes being requested at any given time
+               without having been acked - until we reach EOF. */
+
+            /* Number of bytes asked for that haven't been acked yet */
+            size_t already = (size_t)(filep->offset_sent - filep->offset);
+
+            size_t max_read_ahead = buffer_size*4;
+            unsigned long recv_window;
+
+            if(max_read_ahead > LIBSSH2_CHANNEL_WINDOW_DEFAULT*4)
+                max_read_ahead = LIBSSH2_CHANNEL_WINDOW_DEFAULT*4;
+
+            /* if the buffer_size passed in now is smaller than what has
+               already been sent, we risk getting count become a very large
+               number */
+            if(max_read_ahead > already)
+                count = max_read_ahead - already;
+
+            /* 'count' is how much more data to ask for, and 'already' is how
+               much data that already has been asked for but not yet returned.
+               Specificly, 'count' means how much data that have or will be
+               asked for by the nodes that are already added to the linked
+               list. Some of those read requests may not actually have been
+               sent off successfully yet.
+
+               If 'already' is very large it should be perfectly fine to have
+               count set to 0 as then we don't have to ask for more data
+               (right now).
+
+               buffer_size*4 is just picked more or less out of the air. The
+               idea is that when reading SFTP from a remote server, we send
+               away multiple read requests guessing that the client will read
+               more than only this 'buffer_size' amount of memory. So we ask
+               for maximum buffer_size*4 amount of data so that we can return
+               them very fast in subsequent calls.
+            */
+
+            recv_window = libssh2_channel_window_read_ex(sftp->channel,
+                                                         NULL, NULL);
+            if(max_read_ahead > recv_window) {
+                /* more data will be asked for than what the window currently
+                   allows, expand it! */
+
+                rc = _libssh2_channel_receive_window_adjust(sftp->channel,
+                                                            max_read_ahead*8,
+                                                            1, NULL);
+                /* if this returns EAGAIN, we will get back to this function
+                   at next call */
+                assert(rc != LIBSSH2_ERROR_EAGAIN || !filep->data_left);
+                assert(rc != LIBSSH2_ERROR_EAGAIN || !filep->eof);
+                if(rc)
+                    return rc;
+            }
+        }
+
+        while(count > 0) {
+            unsigned char *s;
+
+            /* 25 = packet_len(4) + packet_type(1) + request_id(4) +
+               handle_len(4) + offset(8) + count(4) */
+            uint32_t packet_len = (uint32_t)handle->handle_len + 25;
+            uint32_t request_id;
+
+            uint32_t size = count;
+            if(size < buffer_size)
+                size = buffer_size;
+            if(size > MAX_SFTP_READ_SIZE)
+                size = MAX_SFTP_READ_SIZE;
+
+            chunk = LIBSSH2_ALLOC(session, packet_len +
+                                  sizeof(struct sftp_pipeline_chunk));
+            if(!chunk)
+                return _libssh2_error(session, LIBSSH2_ERROR_ALLOC,
+                                      "malloc fail for FXP_WRITE");
+
+            chunk->offset = filep->offset_sent;
+            chunk->len = size;
+            chunk->lefttosend = packet_len;
+            chunk->sent = 0;
+
+            s = chunk->packet;
+
+            _libssh2_store_u32(&s, packet_len - 4);
+            *s++ = SSH_FXP_READ;
+            request_id = sftp->request_id++;
+            chunk->request_id = request_id;
+            _libssh2_store_u32(&s, request_id);
+            _libssh2_store_str(&s, handle->handle, handle->handle_len);
+            _libssh2_store_u64(&s, filep->offset_sent);
+            filep->offset_sent += size; /* advance offset at once */
+            _libssh2_store_u32(&s, size);
+
+            /* add this new entry LAST in the list */
+            _libssh2_list_add(&handle->packet_list, &chunk->node);
+            count -= MIN(size, count); /* deduct the size we used, as we might
+                                        * have to create more packets */
+            _libssh2_debug(session, LIBSSH2_TRACE_SFTP,
+                           "read request id %d sent (offset: %d, size: %d)",
+                           request_id, (int)chunk->offset, (int)chunk->len);
+        }
+        /* FALL-THROUGH */
+    case libssh2_NB_state_sent:
+
+        sftp->read_state = libssh2_NB_state_idle;
+
+        /* move through the READ packets that haven't been sent and send as
+           many as possible - remember that we don't block */
+        chunk = _libssh2_list_first(&handle->packet_list);
+
+        while(chunk) {
+            if(chunk->lefttosend) {
+
+                rc = _libssh2_channel_write(channel, 0,
+                                            &chunk->packet[chunk->sent],
+                                            chunk->lefttosend);
+                if(rc < 0) {
+                    sftp->read_state = libssh2_NB_state_sent;
+                    return rc;
+                }
+
+                /* remember where to continue sending the next time */
+                chunk->lefttosend -= rc;
+                chunk->sent += rc;
+
+                if(chunk->lefttosend) {
+                    /* We still have data left to send for this chunk.
+                     * If there is at least one completely sent chunk,
+                     * we can get out of this loop and start reading.  */
+                    if(chunk != _libssh2_list_first(&handle->packet_list)) {
+                        break;
+                    }
+                    else {
+                        continue;
+                    }
+                }
+            }
+
+            /* move on to the next chunk with data to send */
+            chunk = _libssh2_list_next(&chunk->node);
+        }
+        /* FALL-THROUGH */
+
+    case libssh2_NB_state_sent2:
+
+        sftp->read_state = libssh2_NB_state_idle;
+
+        /*
+         * Count all ACKed packets and act on the contents of them.
+         */
+        chunk = _libssh2_list_first(&handle->packet_list);
+
+        while(chunk) {
+            unsigned char *data;
+            size_t data_len;
+            uint32_t rc32;
+            static const unsigned char read_responses[2] = {
+                SSH_FXP_DATA, SSH_FXP_STATUS
+            };
+
+            if(chunk->lefttosend) {
+                /* if the chunk still has data left to send, we shouldn't wait
+                   for an ACK for it just yet */
+                if(bytes_in_buffer > 0) {
+                    return bytes_in_buffer;
+                }
+                else {
+                    /* we should never reach this point */
+                    return _libssh2_error(session, LIBSSH2_ERROR_SFTP_PROTOCOL,
+                                          "sftp_read() internal error");
+                }
+            }
+
+            rc = sftp_packet_requirev(sftp, 2, read_responses,
+                                      chunk->request_id, &data, &data_len, 9);
+            if(rc == LIBSSH2_ERROR_EAGAIN && bytes_in_buffer != 0) {
+                /* do not return EAGAIN if we have already
+                 * written data into the buffer */
+                return bytes_in_buffer;
+            }
+
+            if(rc == LIBSSH2_ERROR_BUFFER_TOO_SMALL) {
+                if(data_len > 0) {
+                    LIBSSH2_FREE(session, data);
+                }
+                return _libssh2_error(session, LIBSSH2_ERROR_SFTP_PROTOCOL,
+                                      "Response too small");
+            }
+            else if(rc < 0) {
+                sftp->read_state = libssh2_NB_state_sent2;
+                return rc;
+            }
+
+            /*
+             * We get DATA or STATUS back. STATUS can be error, or it is
+             * FX_EOF when we reach the end of the file.
+             */
+
+            switch(data[0]) {
+            case SSH_FXP_STATUS:
+                /* remove the chunk we just processed */
+
+                _libssh2_list_remove(&chunk->node);
+                LIBSSH2_FREE(session, chunk);
+
+                /* we must remove all outstanding READ requests, as either we
+                   got an error or we're at end of file */
+                sftp_packetlist_flush(handle);
+
+                rc32 = _libssh2_ntohu32(data + 5);
+                LIBSSH2_FREE(session, data);
+
+                if(rc32 == LIBSSH2_FX_EOF) {
+                    filep->eof = TRUE;
+                    return bytes_in_buffer;
+                }
+                else {
+                    sftp->last_errno = rc32;
+                    return _libssh2_error(session, LIBSSH2_ERROR_SFTP_PROTOCOL,
+                                          "SFTP READ error");
+                }
+                break;
+
+            case SSH_FXP_DATA:
+                if(chunk->offset != filep->offset) {
+                    /* This could happen if the server returns less bytes than
+                       requested, which shouldn't happen for normal files. See:
+                       https://tools.ietf.org/html/draft-ietf-secsh-filexfer-02
+                       #section-6.4
+                    */
+                    return _libssh2_error(session, LIBSSH2_ERROR_SFTP_PROTOCOL,
+                                          "Read Packet At Unexpected Offset");
+                }
+
+                rc32 = _libssh2_ntohu32(data + 5);
+                if(rc32 > (data_len - 9))
+                    return _libssh2_error(session, LIBSSH2_ERROR_SFTP_PROTOCOL,
+                                          "SFTP Protocol badness");
+
+                if(rc32 > chunk->len) {
+                    /* A chunk larger than we requested was returned to us.
+                       This is a protocol violation and we don't know how to
+                       deal with it. Bail out! */
+                    return _libssh2_error(session, LIBSSH2_ERROR_SFTP_PROTOCOL,
+                                          "FXP_READ response too big");
+                }
+
+                if(rc32 != chunk->len) {
+                    /* a short read does not imply end of file, but we must
+                       adjust the offset_sent since it was advanced with a
+                       full chunk->len before */
+                    filep->offset_sent -= (chunk->len - rc32);
+                }
+
+                if((bytes_in_buffer + rc32) > buffer_size) {
+                    /* figure out the overlap amount */
+                    filep->data_left = (bytes_in_buffer + rc32) - buffer_size;
+
+                    /* getting the full packet would overflow the buffer, so
+                       only get the correct amount and keep the remainder */
+                    rc32 = (uint32_t)buffer_size - bytes_in_buffer;
+
+                    /* store data to keep for next call */
+                    filep->data = data;
+                    filep->data_len = data_len;
+                }
+                else
+                    filep->data_len = 0;
+
+                /* copy the received data from the received FXP_DATA packet to
+                   the buffer at the correct index */
+                memcpy(sliding_bufferp, data + 9, rc32);
+                filep->offset += rc32;
+                bytes_in_buffer += rc32;
+                sliding_bufferp += rc32;
+
+                if(filep->data_len == 0)
+                    /* free the allocated data if not stored to keep */
+                    LIBSSH2_FREE(session, data);
+
+                /* remove the chunk we just processed keeping track of the
+                 * next one in case we need it */
+                next = _libssh2_list_next(&chunk->node);
+                _libssh2_list_remove(&chunk->node);
+                LIBSSH2_FREE(session, chunk);
+
+                /* check if we have space left in the buffer
+                 * and either continue to the next chunk or stop
+                 */
+                if(bytes_in_buffer < buffer_size) {
+                    chunk = next;
+                }
+                else {
+                    chunk = NULL;
+                }
+
+                break;
+            default:
+                return _libssh2_error(session, LIBSSH2_ERROR_SFTP_PROTOCOL,
+                                      "SFTP Protocol badness: unrecognised "
+                                      "read request response");
+            }
+        }
+
+        if(bytes_in_buffer > 0)
+            return bytes_in_buffer;
+
+        break;
+
+    default:
+        assert(!"State machine error; unrecognised read state");
+    }
+
+    /* we should never reach this point */
+    return _libssh2_error(session, LIBSSH2_ERROR_SFTP_PROTOCOL,
+                          "sftp_read() internal error");
+}
+
+/* libssh2_sftp_read
+ * Read from an SFTP file handle
+ */
+LIBSSH2_API ssize_t
+libssh2_sftp_read(LIBSSH2_SFTP_HANDLE *hnd, char *buffer,
+                  size_t buffer_maxlen)
+{
+    ssize_t rc;
+    if(!hnd)
+        return LIBSSH2_ERROR_BAD_USE;
+    BLOCK_ADJUST(rc, hnd->sftp->channel->session,
+                 sftp_read(hnd, buffer, buffer_maxlen));
+    return rc;
+}
+
+/* sftp_readdir
+ * Read from an SFTP directory handle
+ */
+static ssize_t sftp_readdir(LIBSSH2_SFTP_HANDLE *handle, char *buffer,
+                            size_t buffer_maxlen, char *longentry,
+                            size_t longentry_maxlen,
+                            LIBSSH2_SFTP_ATTRIBUTES *attrs)
+{
+    LIBSSH2_SFTP *sftp = handle->sftp;
+    LIBSSH2_CHANNEL *channel = sftp->channel;
+    LIBSSH2_SESSION *session = channel->session;
+    size_t data_len;
+    uint32_t num_names;
+    /* 13 = packet_len(4) + packet_type(1) + request_id(4) + handle_len(4) */
+    uint32_t packet_len = handle->handle_len + 13;
+    unsigned char *s, *data;
+    static const unsigned char read_responses[2] = {
+        SSH_FXP_NAME, SSH_FXP_STATUS };
+    ssize_t retcode;
+
+    if(sftp->readdir_state == libssh2_NB_state_idle) {
+        if(handle->u.dir.names_left) {
+            /*
+             * A prior request returned more than one directory entry,
+             * feed it back from the buffer
+             */
+            LIBSSH2_SFTP_ATTRIBUTES attrs_dummy;
+            size_t real_longentry_len;
+            size_t real_filename_len;
+            size_t filename_len;
+            size_t longentry_len;
+            size_t names_packet_len = handle->u.dir.names_packet_len;
+            int attr_len = 0;
+
+            if(names_packet_len >= 4) {
+                s = (unsigned char *) handle->u.dir.next_name;
+                real_filename_len = _libssh2_ntohu32(s);
+                s += 4;
+                names_packet_len -= 4;
+            }
+            else {
+                filename_len = (size_t)LIBSSH2_ERROR_BUFFER_TOO_SMALL;
+                goto end;
+            }
+
+            filename_len = real_filename_len;
+            if(filename_len >= buffer_maxlen) {
+                filename_len = (size_t)LIBSSH2_ERROR_BUFFER_TOO_SMALL;
+                goto end;
+            }
+
+            if(buffer_maxlen >= filename_len && names_packet_len >=
+               filename_len) {
+                memcpy(buffer, s, filename_len);
+                buffer[filename_len] = '\0';           /* zero terminate */
+                s += real_filename_len;
+                names_packet_len -= real_filename_len;
+            }
+            else {
+                filename_len = (size_t)LIBSSH2_ERROR_BUFFER_TOO_SMALL;
+                goto end;
+            }
+
+            if(names_packet_len >= 4) {
+                real_longentry_len = _libssh2_ntohu32(s);
+                s += 4;
+                names_packet_len -= 4;
+            }
+            else {
+                filename_len = (size_t)LIBSSH2_ERROR_BUFFER_TOO_SMALL;
+                goto end;
+            }
+
+            if(longentry && (longentry_maxlen>1)) {
+                longentry_len = real_longentry_len;
+
+                if(longentry_len >= longentry_maxlen ||
+                   longentry_len > names_packet_len) {
+                    filename_len = (size_t)LIBSSH2_ERROR_BUFFER_TOO_SMALL;
+                    goto end;
+                }
+
+                memcpy(longentry, s, longentry_len);
+                longentry[longentry_len] = '\0'; /* zero terminate */
+            }
+
+            if(real_longentry_len <= names_packet_len) {
+                s += real_longentry_len;
+                names_packet_len -= real_longentry_len;
+            }
+            else {
+                filename_len = (size_t)LIBSSH2_ERROR_BUFFER_TOO_SMALL;
+                goto end;
+            }
+
+            if(attrs)
+                memset(attrs, 0, sizeof(LIBSSH2_SFTP_ATTRIBUTES));
+
+            attr_len = sftp_bin2attr(attrs ? attrs : &attrs_dummy, s,
+                                     names_packet_len);
+
+            if(attr_len >= 0) {
+                s += attr_len;
+                names_packet_len -= attr_len;
+            }
+            else {
+                filename_len = (size_t)LIBSSH2_ERROR_BUFFER_TOO_SMALL;
+                goto end;
+            }
+
+            handle->u.dir.next_name = (char *) s;
+            handle->u.dir.names_packet_len = names_packet_len;
+          end:
+
+            if((--handle->u.dir.names_left) == 0)
+                LIBSSH2_FREE(session, handle->u.dir.names_packet);
+
+            _libssh2_debug(session, LIBSSH2_TRACE_SFTP,
+                           "libssh2_sftp_readdir_ex() return %d",
+                           filename_len);
+            return (ssize_t)filename_len;
+        }
+
+        /* Request another entry(entries?) */
+
+        s = sftp->readdir_packet = LIBSSH2_ALLOC(session, packet_len);
+        if(!sftp->readdir_packet)
+            return _libssh2_error(session, LIBSSH2_ERROR_ALLOC,
+                                  "Unable to allocate memory for "
+                                  "FXP_READDIR packet");
+
+        _libssh2_store_u32(&s, packet_len - 4);
+        *(s++) = SSH_FXP_READDIR;
+        sftp->readdir_request_id = sftp->request_id++;
+        _libssh2_store_u32(&s, sftp->readdir_request_id);
+        _libssh2_store_str(&s, handle->handle, handle->handle_len);
+
+        sftp->readdir_state = libssh2_NB_state_created;
+    }
+
+    if(sftp->readdir_state == libssh2_NB_state_created) {
+        _libssh2_debug(session, LIBSSH2_TRACE_SFTP,
+                       "Reading entries from directory handle");
+        retcode = _libssh2_channel_write(channel, 0, sftp->readdir_packet,
+                                         packet_len);
+        if(retcode == LIBSSH2_ERROR_EAGAIN) {
+            return retcode;
+        }
+        else if((ssize_t)packet_len != retcode) {
+            LIBSSH2_FREE(session, sftp->readdir_packet);
+            sftp->readdir_packet = NULL;
+            sftp->readdir_state = libssh2_NB_state_idle;
+            return _libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND,
+                                  "_libssh2_channel_write() failed");
+        }
+
+        LIBSSH2_FREE(session, sftp->readdir_packet);
+        sftp->readdir_packet = NULL;
+
+        sftp->readdir_state = libssh2_NB_state_sent;
+    }
+
+    retcode = sftp_packet_requirev(sftp, 2, read_responses,
+                                   sftp->readdir_request_id, &data,
+                                   &data_len, 9);
+    if(retcode == LIBSSH2_ERROR_EAGAIN)
+        return retcode;
+    else if(retcode == LIBSSH2_ERROR_BUFFER_TOO_SMALL) {
+        if(data_len > 0) {
+            LIBSSH2_FREE(session, data);
+        }
+        return _libssh2_error(session, LIBSSH2_ERROR_SFTP_PROTOCOL,
+                              "Status message too short");
+    }
+    else if(retcode) {
+        sftp->readdir_state = libssh2_NB_state_idle;
+        return _libssh2_error(session, retcode,
+                              "Timeout waiting for status message");
+    }
+
+    if(data[0] == SSH_FXP_STATUS) {
+        retcode = _libssh2_ntohu32(data + 5);
+        LIBSSH2_FREE(session, data);
+        if(retcode == LIBSSH2_FX_EOF) {
+            sftp->readdir_state = libssh2_NB_state_idle;
+            return 0;
+        }
+        else {
+            sftp->last_errno = retcode;
+            sftp->readdir_state = libssh2_NB_state_idle;
+            return _libssh2_error(session, LIBSSH2_ERROR_SFTP_PROTOCOL,
+                                  "SFTP Protocol Error");
+        }
+    }
+
+    sftp->readdir_state = libssh2_NB_state_idle;
+
+    num_names = _libssh2_ntohu32(data + 5);
+    _libssh2_debug(session, LIBSSH2_TRACE_SFTP, "%lu entries returned",
+                   num_names);
+    if(!num_names) {
+        LIBSSH2_FREE(session, data);
+        return 0;
+    }
+
+    handle->u.dir.names_left = num_names;
+    handle->u.dir.names_packet = data;
+    handle->u.dir.next_name = (char *) data + 9;
+    handle->u.dir.names_packet_len = data_len - 9;
+
+    /* use the name popping mechanism from the start of the function */
+    return sftp_readdir(handle, buffer, buffer_maxlen, longentry,
+                        longentry_maxlen, attrs);
+}
+
+/* libssh2_sftp_readdir_ex
+ * Read from an SFTP directory handle
+ */
+LIBSSH2_API int
+libssh2_sftp_readdir_ex(LIBSSH2_SFTP_HANDLE *hnd, char *buffer,
+                        size_t buffer_maxlen, char *longentry,
+                        size_t longentry_maxlen,
+                        LIBSSH2_SFTP_ATTRIBUTES *attrs)
+{
+    int rc;
+    if(!hnd)
+        return LIBSSH2_ERROR_BAD_USE;
+    BLOCK_ADJUST(rc, hnd->sftp->channel->session,
+                 sftp_readdir(hnd, buffer, buffer_maxlen, longentry,
+                              longentry_maxlen, attrs));
+    return rc;
+}
+
+/*
+ * sftp_write
+ *
+ * Write data to an SFTP handle. Returns the number of bytes written, or
+ * a negative error code.
+ *
+ * We recommend sending very large data buffers to this function!
+ *
+ * Concept:
+ *
+ * - Detect how much of the given buffer that was already sent in a previous
+ *   call by inspecting the linked list of outgoing chunks. Make sure to skip
+ *   passed the data that has already been taken care of.
+ *
+ * - Split all (new) outgoing data in chunks no larger than N.
+ *
+ * - Each N bytes chunk gets created as a separate SFTP packet.
+ *
+ * - Add all created outgoing packets to the linked list.
+ *
+ * - Walk through the list and send the chunks that haven't been sent,
+ *   as many as possible until EAGAIN. Some of the chunks may have been put
+ *   in the list in a previous invoke.
+ *
+ * - For all the chunks in the list that have been completely sent off, check
+ *   for ACKs. If a chunk has been ACKed, it is removed from the linked
+ *   list and the "acked" counter gets increased with that data amount.
+ *
+ * - Return TOTAL bytes acked so far.
+ *
+ * Caveats:
+ * -  be careful: we must not return a higher number than what was given!
+ *
+ * TODO:
+ *   Introduce an option that disables this sort of "speculative" ahead writing
+ *   as there's a risk that it will do harm to some app.
+ */
+
+static ssize_t sftp_write(LIBSSH2_SFTP_HANDLE *handle, const char *buffer,
+                          size_t count)
+{
+    LIBSSH2_SFTP *sftp = handle->sftp;
+    LIBSSH2_CHANNEL *channel = sftp->channel;
+    LIBSSH2_SESSION *session = channel->session;
+    size_t data_len;
+    uint32_t retcode;
+    uint32_t packet_len;
+    unsigned char *s, *data;
+    ssize_t rc;
+    struct sftp_pipeline_chunk *chunk;
+    struct sftp_pipeline_chunk *next;
+    size_t acked = 0;
+    size_t org_count = count;
+    size_t already;
+
+    switch(sftp->write_state) {
+    default:
+    case libssh2_NB_state_idle:
+
+        /* Number of bytes sent off that haven't been acked and therefore we
+           will get passed in here again.
+
+           Also, add up the number of bytes that actually already have been
+           acked but we haven't been able to return as such yet, so we will
+           get that data as well passed in here again.
+        */
+        already = (size_t) (handle->u.file.offset_sent -
+                            handle->u.file.offset)+
+            handle->u.file.acked;
+
+        if(count >= already) {
+            /* skip the part already made into packets */
+            buffer += already;
+            count -= already;
+        }
+        else
+            /* there is more data already fine than what we got in this call */
+            count = 0;
+
+        sftp->write_state = libssh2_NB_state_idle;
+        while(count) {
+            /* TODO: Possibly this should have some logic to prevent a very
+               very small fraction to be left but lets ignore that for now */
+            uint32_t size = MIN(MAX_SFTP_OUTGOING_SIZE, count);
+            uint32_t request_id;
+
+            /* 25 = packet_len(4) + packet_type(1) + request_id(4) +
+               handle_len(4) + offset(8) + count(4) */
+            packet_len = handle->handle_len + size + 25;
+
+            chunk = LIBSSH2_ALLOC(session, packet_len +
+                                  sizeof(struct sftp_pipeline_chunk));
+            if(!chunk)
+                return _libssh2_error(session, LIBSSH2_ERROR_ALLOC,
+                                      "malloc fail for FXP_WRITE");
+
+            chunk->len = size;
+            chunk->sent = 0;
+            chunk->lefttosend = packet_len;
+
+            s = chunk->packet;
+            _libssh2_store_u32(&s, packet_len - 4);
+
+            *(s++) = SSH_FXP_WRITE;
+            request_id = sftp->request_id++;
+            chunk->request_id = request_id;
+            _libssh2_store_u32(&s, request_id);
+            _libssh2_store_str(&s, handle->handle, handle->handle_len);
+            _libssh2_store_u64(&s, handle->u.file.offset_sent);
+            handle->u.file.offset_sent += size; /* advance offset at once */
+            _libssh2_store_str(&s, buffer, size);
+
+            /* add this new entry LAST in the list */
+            _libssh2_list_add(&handle->packet_list, &chunk->node);
+
+            buffer += size;
+            count -= size; /* deduct the size we used, as we might have
+                              to create more packets */
+        }
+
+        /* move through the WRITE packets that haven't been sent and send as
+           many as possible - remember that we don't block */
+        chunk = _libssh2_list_first(&handle->packet_list);
+
+        while(chunk) {
+            if(chunk->lefttosend) {
+                rc = _libssh2_channel_write(channel, 0,
+                                            &chunk->packet[chunk->sent],
+                                            chunk->lefttosend);
+                if(rc < 0)
+                    /* remain in idle state */
+                    return rc;
+
+                /* remember where to continue sending the next time */
+                chunk->lefttosend -= rc;
+                chunk->sent += rc;
+
+                if(chunk->lefttosend)
+                    /* data left to send, get out of loop */
+                    break;
+            }
+
+            /* move on to the next chunk with data to send */
+            chunk = _libssh2_list_next(&chunk->node);
+        }
+
+        /* fall-through */
+    case libssh2_NB_state_sent:
+
+        sftp->write_state = libssh2_NB_state_idle;
+        /*
+         * Count all ACKed packets
+         */
+        chunk = _libssh2_list_first(&handle->packet_list);
+
+        while(chunk) {
+            if(chunk->lefttosend)
+                /* if the chunk still has data left to send, we shouldn't wait
+                   for an ACK for it just yet */
+                break;
+
+            else if(acked)
+                /* if we have sent data that is acked, we must return that
+                   info before we call a function that might return EAGAIN */
+                break;
+
+            /* we check the packets in order */
+            rc = sftp_packet_require(sftp, SSH_FXP_STATUS,
+                                     chunk->request_id, &data, &data_len, 9);
+            if(rc == LIBSSH2_ERROR_BUFFER_TOO_SMALL) {
+                if(data_len > 0) {
+                    LIBSSH2_FREE(session, data);
+                }
+                return _libssh2_error(session, LIBSSH2_ERROR_SFTP_PROTOCOL,
+                                      "FXP write packet too short");
+            }
+            else if(rc < 0) {
+                if(rc == LIBSSH2_ERROR_EAGAIN)
+                    sftp->write_state = libssh2_NB_state_sent;
+                return rc;
+            }
+
+            retcode = _libssh2_ntohu32(data + 5);
+            LIBSSH2_FREE(session, data);
+
+            sftp->last_errno = retcode;
+            if(retcode == LIBSSH2_FX_OK) {
+                acked += chunk->len; /* number of payload data that was acked
+                                        here */
+
+                /* we increase the offset value for all acks */
+                handle->u.file.offset += chunk->len;
+
+                next = _libssh2_list_next(&chunk->node);
+
+                _libssh2_list_remove(&chunk->node); /* remove from list */
+                LIBSSH2_FREE(session, chunk); /* free memory */
+
+                chunk = next;
+            }
+            else {
+                /* flush all pending packets from the outgoing list */
+                sftp_packetlist_flush(handle);
+
+                /* since we return error now, the application will not get any
+                   outstanding data acked, so we need to rewind the offset to
+                   where the application knows it has reached with acked
+                   data */
+                handle->u.file.offset -= handle->u.file.acked;
+
+                /* then reset the offset_sent to be the same as the offset */
+                handle->u.file.offset_sent = handle->u.file.offset;
+
+                /* clear the acked counter since we can have no pending data to
+                   ack after an error */
+                handle->u.file.acked = 0;
+
+                /* the server returned an error for that written chunk,
+                   propagate this back to our parent function */
+                return _libssh2_error(session, LIBSSH2_ERROR_SFTP_PROTOCOL,
+                                      "FXP write failed");
+            }
+        }
+        break;
+    }
+
+    /* if there were acked data in a previous call that wasn't returned then,
+       add that up and try to return it all now. This can happen if the app
+       first sends a huge buffer of data, and then in a second call it sends a
+       smaller one. */
+    acked += handle->u.file.acked;
+
+    if(acked) {
+        ssize_t ret = MIN(acked, org_count);
+        /* we got data acked so return that amount, but no more than what
+           was asked to get sent! */
+
+        /* store the remainder. 'ret' is always equal to or less than 'acked'
+           here */
+        handle->u.file.acked = acked - ret;
+
+        return ret;
+    }
+
+    else
+        return 0; /* nothing was acked, and no EAGAIN was received! */
+}
+
+/* libssh2_sftp_write
+ * Write data to a file handle
+ */
+LIBSSH2_API ssize_t
+libssh2_sftp_write(LIBSSH2_SFTP_HANDLE *hnd, const char *buffer,
+                   size_t count)
+{
+    ssize_t rc;
+    if(!hnd)
+        return LIBSSH2_ERROR_BAD_USE;
+    BLOCK_ADJUST(rc, hnd->sftp->channel->session,
+                 sftp_write(hnd, buffer, count));
+    return rc;
+
+}
+
+static int sftp_fsync(LIBSSH2_SFTP_HANDLE *handle)
+{
+    LIBSSH2_SFTP *sftp = handle->sftp;
+    LIBSSH2_CHANNEL *channel = sftp->channel;
+    LIBSSH2_SESSION *session = channel->session;
+    /* 34 = packet_len(4) + packet_type(1) + request_id(4) +
+       string_len(4) + strlen("fsync@openssh.com")(17) + handle_len(4) */
+    uint32_t packet_len = handle->handle_len + 34;
+    size_t data_len;
+    unsigned char *packet, *s, *data;
+    ssize_t rc;
+    uint32_t retcode;
+
+    if(sftp->fsync_state == libssh2_NB_state_idle) {
+        _libssh2_debug(session, LIBSSH2_TRACE_SFTP,
+                       "Issuing fsync command");
+        s = packet = LIBSSH2_ALLOC(session, packet_len);
+        if(!packet) {
+            return _libssh2_error(session, LIBSSH2_ERROR_ALLOC,
+                                  "Unable to allocate memory for FXP_EXTENDED "
+                                  "packet");
+        }
+
+        _libssh2_store_u32(&s, packet_len - 4);
+        *(s++) = SSH_FXP_EXTENDED;
+        sftp->fsync_request_id = sftp->request_id++;
+        _libssh2_store_u32(&s, sftp->fsync_request_id);
+        _libssh2_store_str(&s, "fsync@openssh.com", 17);
+        _libssh2_store_str(&s, handle->handle, handle->handle_len);
+
+        sftp->fsync_state = libssh2_NB_state_created;
+    }
+    else {
+        packet = sftp->fsync_packet;
+    }
+
+    if(sftp->fsync_state == libssh2_NB_state_created) {
+        rc = _libssh2_channel_write(channel, 0, packet, packet_len);
+        if(rc == LIBSSH2_ERROR_EAGAIN ||
+            (0 <= rc && rc < (ssize_t)packet_len)) {
+            sftp->fsync_packet = packet;
+            return LIBSSH2_ERROR_EAGAIN;
+        }
+
+        LIBSSH2_FREE(session, packet);
+        sftp->fsync_packet = NULL;
+
+        if(rc < 0) {
+            sftp->fsync_state = libssh2_NB_state_idle;
+            return _libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND,
+                                  "_libssh2_channel_write() failed");
+        }
+        sftp->fsync_state = libssh2_NB_state_sent;
+    }
+
+    rc = sftp_packet_require(sftp, SSH_FXP_STATUS,
+                             sftp->fsync_request_id, &data, &data_len, 9);
+    if(rc == LIBSSH2_ERROR_EAGAIN) {
+        return rc;
+    }
+    else if(rc == LIBSSH2_ERROR_BUFFER_TOO_SMALL) {
+        if(data_len > 0) {
+            LIBSSH2_FREE(session, data);
+        }
+        return _libssh2_error(session, LIBSSH2_ERROR_SFTP_PROTOCOL,
+                              "SFTP fsync packet too short");
+    }
+    else if(rc) {
+        sftp->fsync_state = libssh2_NB_state_idle;
+        return _libssh2_error(session, rc,
+                              "Error waiting for FXP EXTENDED REPLY");
+    }
+
+    sftp->fsync_state = libssh2_NB_state_idle;
+
+    retcode = _libssh2_ntohu32(data + 5);
+    LIBSSH2_FREE(session, data);
+
+    if(retcode != LIBSSH2_FX_OK) {
+        sftp->last_errno = retcode;
+        return _libssh2_error(session, LIBSSH2_ERROR_SFTP_PROTOCOL,
+                              "fsync failed");
+    }
+
+    return 0;
+}
+
+/* libssh2_sftp_fsync
+ * Commit data on the handle to disk.
+ */
+LIBSSH2_API int
+libssh2_sftp_fsync(LIBSSH2_SFTP_HANDLE *hnd)
+{
+    int rc;
+    if(!hnd)
+        return LIBSSH2_ERROR_BAD_USE;
+    BLOCK_ADJUST(rc, hnd->sftp->channel->session,
+                 sftp_fsync(hnd));
+    return rc;
+}
+
+
+/*
+ * sftp_fstat
+ *
+ * Get or Set stat on a file
+ */
+static int sftp_fstat(LIBSSH2_SFTP_HANDLE *handle,
+                      LIBSSH2_SFTP_ATTRIBUTES *attrs, int setstat)
+{
+    LIBSSH2_SFTP *sftp = handle->sftp;
+    LIBSSH2_CHANNEL *channel = sftp->channel;
+    LIBSSH2_SESSION *session = channel->session;
+    size_t data_len;
+    /* 13 = packet_len(4) + packet_type(1) + request_id(4) + handle_len(4) */
+    uint32_t packet_len =
+        handle->handle_len + 13 + (setstat ? sftp_attrsize(attrs->flags) : 0);
+    unsigned char *s, *data;
+    static const unsigned char fstat_responses[2] =
+        { SSH_FXP_ATTRS, SSH_FXP_STATUS };
+    ssize_t rc;
+
+    if(sftp->fstat_state == libssh2_NB_state_idle) {
+        _libssh2_debug(session, LIBSSH2_TRACE_SFTP, "Issuing %s command",
+                       setstat ? "set-stat" : "stat");
+        s = sftp->fstat_packet = LIBSSH2_ALLOC(session, packet_len);
+        if(!sftp->fstat_packet) {
+            return _libssh2_error(session, LIBSSH2_ERROR_ALLOC,
+                                  "Unable to allocate memory for "
+                                  "FSTAT/FSETSTAT packet");
+        }
+
+        _libssh2_store_u32(&s, packet_len - 4);
+        *(s++) = setstat ? SSH_FXP_FSETSTAT : SSH_FXP_FSTAT;
+        sftp->fstat_request_id = sftp->request_id++;
+        _libssh2_store_u32(&s, sftp->fstat_request_id);
+        _libssh2_store_str(&s, handle->handle, handle->handle_len);
+
+        if(setstat) {
+            s += sftp_attr2bin(s, attrs);
+        }
+
+        sftp->fstat_state = libssh2_NB_state_created;
+    }
+
+    if(sftp->fstat_state == libssh2_NB_state_created) {
+        rc = _libssh2_channel_write(channel, 0, sftp->fstat_packet,
+                                    packet_len);
+        if(rc == LIBSSH2_ERROR_EAGAIN) {
+            return rc;
+        }
+        else if((ssize_t)packet_len != rc) {
+            LIBSSH2_FREE(session, sftp->fstat_packet);
+            sftp->fstat_packet = NULL;
+            sftp->fstat_state = libssh2_NB_state_idle;
+            return _libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND,
+                                  (setstat ? "Unable to send FXP_FSETSTAT"
+                                   : "Unable to send FXP_FSTAT command"));
+        }
+        LIBSSH2_FREE(session, sftp->fstat_packet);
+        sftp->fstat_packet = NULL;
+
+        sftp->fstat_state = libssh2_NB_state_sent;
+    }
+
+    rc = sftp_packet_requirev(sftp, 2, fstat_responses,
+                              sftp->fstat_request_id, &data,
+                              &data_len, 9);
+    if(rc == LIBSSH2_ERROR_EAGAIN)
+        return rc;
+    else if(rc == LIBSSH2_ERROR_BUFFER_TOO_SMALL) {
+        if(data_len > 0) {
+            LIBSSH2_FREE(session, data);
+        }
+        return _libssh2_error(session, LIBSSH2_ERROR_SFTP_PROTOCOL,
+                              "SFTP fstat packet too short");
+    }
+    else if(rc) {
+        sftp->fstat_state = libssh2_NB_state_idle;
+        return _libssh2_error(session, rc,
+                              "Timeout waiting for status message");
+    }
+
+    sftp->fstat_state = libssh2_NB_state_idle;
+
+    if(data[0] == SSH_FXP_STATUS) {
+        uint32_t retcode;
+
+        retcode = _libssh2_ntohu32(data + 5);
+        LIBSSH2_FREE(session, data);
+        if(retcode == LIBSSH2_FX_OK) {
+            return 0;
+        }
+        else {
+            sftp->last_errno = retcode;
+            return _libssh2_error(session, LIBSSH2_ERROR_SFTP_PROTOCOL,
+                                  "SFTP Protocol Error");
+        }
+    }
+
+    if(sftp_bin2attr(attrs, data + 5, data_len - 5) < 0) {
+        LIBSSH2_FREE(session, data);
+        return _libssh2_error(session, LIBSSH2_ERROR_SFTP_PROTOCOL,
+                              "Attributes too short in SFTP fstat");
+    }
+
+    LIBSSH2_FREE(session, data);
+
+    return 0;
+}
+
+/* libssh2_sftp_fstat_ex
+ * Get or Set stat on a file
+ */
+LIBSSH2_API int
+libssh2_sftp_fstat_ex(LIBSSH2_SFTP_HANDLE *hnd,
+                      LIBSSH2_SFTP_ATTRIBUTES *attrs, int setstat)
+{
+    int rc;
+    if(!hnd || !attrs)
+        return LIBSSH2_ERROR_BAD_USE;
+    BLOCK_ADJUST(rc, hnd->sftp->channel->session,
+                 sftp_fstat(hnd, attrs, setstat));
+    return rc;
+}
+
+
+/* libssh2_sftp_seek64
+ * Set the read/write pointer to an arbitrary position within the file
+ */
+LIBSSH2_API void
+libssh2_sftp_seek64(LIBSSH2_SFTP_HANDLE *handle, libssh2_uint64_t offset)
+{
+    if(!handle)
+        return;
+    if(handle->u.file.offset == offset && handle->u.file.offset_sent == offset)
+        return;
+
+    handle->u.file.offset = handle->u.file.offset_sent = offset;
+    /* discard all pending requests and currently read data */
+    sftp_packetlist_flush(handle);
+
+    /* free the left received buffered data */
+    if(handle->u.file.data_left) {
+        LIBSSH2_FREE(handle->sftp->channel->session, handle->u.file.data);
+        handle->u.file.data_left = handle->u.file.data_len = 0;
+        handle->u.file.data = NULL;
+    }
+
+    /* reset EOF to False */
+    handle->u.file.eof = FALSE;
+}
+
+/* libssh2_sftp_seek
+ * Set the read/write pointer to an arbitrary position within the file
+ */
+LIBSSH2_API void
+libssh2_sftp_seek(LIBSSH2_SFTP_HANDLE *handle, size_t offset)
+{
+    libssh2_sftp_seek64(handle, (libssh2_uint64_t)offset);
+}
+
+/* libssh2_sftp_tell
+ * Return the current read/write pointer's offset
+ */
+LIBSSH2_API size_t
+libssh2_sftp_tell(LIBSSH2_SFTP_HANDLE *handle)
+{
+    if(!handle)
+        return 0; /* no handle, no size */
+
+    /* NOTE: this may very well truncate the size if it is larger than what
+       size_t can hold, so libssh2_sftp_tell64() is really the function you
+       should use */
+    return (size_t)(handle->u.file.offset);
+}
+
+/* libssh2_sftp_tell64
+ * Return the current read/write pointer's offset
+ */
+LIBSSH2_API libssh2_uint64_t
+libssh2_sftp_tell64(LIBSSH2_SFTP_HANDLE *handle)
+{
+    if(!handle)
+        return 0; /* no handle, no size */
+
+    return handle->u.file.offset;
+}
+
+/*
+ * Flush all remaining incoming SFTP packets and zombies.
+ */
+static void sftp_packet_flush(LIBSSH2_SFTP *sftp)
+{
+    LIBSSH2_CHANNEL *channel = sftp->channel;
+    LIBSSH2_SESSION *session = channel->session;
+    LIBSSH2_SFTP_PACKET *packet = _libssh2_list_first(&sftp->packets);
+    struct sftp_zombie_requests *zombie =
+        _libssh2_list_first(&sftp->zombie_requests);
+
+    while(packet) {
+        LIBSSH2_SFTP_PACKET *next;
+
+        /* check next struct in the list */
+        next =  _libssh2_list_next(&packet->node);
+        _libssh2_list_remove(&packet->node);
+        LIBSSH2_FREE(session, packet->data);
+        LIBSSH2_FREE(session, packet);
+
+        packet = next;
+    }
+
+    while(zombie) {
+        /* figure out the next node */
+        struct sftp_zombie_requests *next = _libssh2_list_next(&zombie->node);
+        /* unlink the current one */
+        _libssh2_list_remove(&zombie->node);
+        /* free the memory */
+        LIBSSH2_FREE(session, zombie);
+        zombie = next;
+    }
+
+}
+
+/* sftp_close_handle
+ *
+ * Close a file or directory handle.
+ * Also frees handle resource and unlinks it from the SFTP structure.
+ * The handle is no longer usable after return of this function, unless
+ * the return value is LIBSSH2_ERROR_EAGAIN in which case this function
+ * should be called again.
+ */
+static int
+sftp_close_handle(LIBSSH2_SFTP_HANDLE *handle)
+{
+    LIBSSH2_SFTP *sftp = handle->sftp;
+    LIBSSH2_CHANNEL *channel = sftp->channel;
+    LIBSSH2_SESSION *session = channel->session;
+    size_t data_len;
+    /* 13 = packet_len(4) + packet_type(1) + request_id(4) + handle_len(4) */
+    uint32_t packet_len = handle->handle_len + 13;
+    unsigned char *s, *data = NULL;
+    int rc = 0;
+
+    if(handle->close_state == libssh2_NB_state_idle) {
+        _libssh2_debug(session, LIBSSH2_TRACE_SFTP, "Closing handle");
+        s = handle->close_packet = LIBSSH2_ALLOC(session, packet_len);
+        if(!handle->close_packet) {
+            handle->close_state = libssh2_NB_state_idle;
+            rc = _libssh2_error(session, LIBSSH2_ERROR_ALLOC,
+                                "Unable to allocate memory for FXP_CLOSE "
+                                "packet");
+        }
+        else {
+
+            _libssh2_store_u32(&s, packet_len - 4);
+            *(s++) = SSH_FXP_CLOSE;
+            handle->close_request_id = sftp->request_id++;
+            _libssh2_store_u32(&s, handle->close_request_id);
+            _libssh2_store_str(&s, handle->handle, handle->handle_len);
+            handle->close_state = libssh2_NB_state_created;
+        }
+    }
+
+    if(handle->close_state == libssh2_NB_state_created) {
+        rc = _libssh2_channel_write(channel, 0, handle->close_packet,
+                                    packet_len);
+        if(rc == LIBSSH2_ERROR_EAGAIN) {
+            return rc;
+        }
+        else if((ssize_t)packet_len != rc) {
+            handle->close_state = libssh2_NB_state_idle;
+            rc = _libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND,
+                                "Unable to send FXP_CLOSE command");
+        }
+        else
+            handle->close_state = libssh2_NB_state_sent;
+
+        LIBSSH2_FREE(session, handle->close_packet);
+        handle->close_packet = NULL;
+    }
+
+    if(handle->close_state == libssh2_NB_state_sent) {
+        rc = sftp_packet_require(sftp, SSH_FXP_STATUS,
+                                 handle->close_request_id, &data,
+                                 &data_len, 9);
+        if(rc == LIBSSH2_ERROR_EAGAIN) {
+            return rc;
+        }
+        else if(rc == LIBSSH2_ERROR_BUFFER_TOO_SMALL) {
+            if(data_len > 0) {
+                LIBSSH2_FREE(session, data);
+            }
+            data = NULL;
+            _libssh2_error(session, LIBSSH2_ERROR_SFTP_PROTOCOL,
+                           "Packet too short in FXP_CLOSE command");
+        }
+        else if(rc) {
+            _libssh2_error(session, rc,
+                           "Error waiting for status message");
+        }
+
+        handle->close_state = libssh2_NB_state_sent1;
+    }
+
+    if(!data) {
+        /* if it reaches this point with data unset, something unwanted
+           happened for which we should have set an error code */
+        assert(rc);
+
+    }
+    else {
+        int retcode = _libssh2_ntohu32(data + 5);
+        LIBSSH2_FREE(session, data);
+
+        if(retcode != LIBSSH2_FX_OK) {
+            sftp->last_errno = retcode;
+            handle->close_state = libssh2_NB_state_idle;
+            rc = _libssh2_error(session, LIBSSH2_ERROR_SFTP_PROTOCOL,
+                                "SFTP Protocol Error");
+        }
+    }
+
+    /* remove this handle from the parent's list */
+    _libssh2_list_remove(&handle->node);
+
+    if(handle->handle_type == LIBSSH2_SFTP_HANDLE_DIR) {
+        if(handle->u.dir.names_left)
+            LIBSSH2_FREE(session, handle->u.dir.names_packet);
+    }
+    else if(handle->handle_type == LIBSSH2_SFTP_HANDLE_FILE) {
+        if(handle->u.file.data)
+            LIBSSH2_FREE(session, handle->u.file.data);
+    }
+
+    sftp_packetlist_flush(handle);
+    sftp->read_state = libssh2_NB_state_idle;
+
+    handle->close_state = libssh2_NB_state_idle;
+
+    LIBSSH2_FREE(session, handle);
+
+    return rc;
+}
+
+/* libssh2_sftp_close_handle
+ *
+ * Close a file or directory handle
+ * Also frees handle resource and unlinks it from the SFTP structure
+ */
+LIBSSH2_API int
+libssh2_sftp_close_handle(LIBSSH2_SFTP_HANDLE *hnd)
+{
+    int rc;
+    if(!hnd)
+        return LIBSSH2_ERROR_BAD_USE;
+    BLOCK_ADJUST(rc, hnd->sftp->channel->session, sftp_close_handle(hnd));
+    return rc;
+}
+
+/* sftp_unlink
+ * Delete a file from the remote server
+ */
+static int sftp_unlink(LIBSSH2_SFTP *sftp, const char *filename,
+                       size_t filename_len)
+{
+    LIBSSH2_CHANNEL *channel = sftp->channel;
+    LIBSSH2_SESSION *session = channel->session;
+    size_t data_len;
+    int retcode;
+    /* 13 = packet_len(4) + packet_type(1) + request_id(4) + filename_len(4) */
+    uint32_t packet_len = filename_len + 13;
+    unsigned char *s, *data;
+    int rc;
+
+    if(sftp->unlink_state == libssh2_NB_state_idle) {
+        _libssh2_debug(session, LIBSSH2_TRACE_SFTP, "Unlinking %s", filename);
+        s = sftp->unlink_packet = LIBSSH2_ALLOC(session, packet_len);
+        if(!sftp->unlink_packet) {
+            return _libssh2_error(session, LIBSSH2_ERROR_ALLOC,
+                                  "Unable to allocate memory for FXP_REMOVE "
+                                  "packet");
+        }
+
+        _libssh2_store_u32(&s, packet_len - 4);
+        *(s++) = SSH_FXP_REMOVE;
+        sftp->unlink_request_id = sftp->request_id++;
+        _libssh2_store_u32(&s, sftp->unlink_request_id);
+        _libssh2_store_str(&s, filename, filename_len);
+        sftp->unlink_state = libssh2_NB_state_created;
+    }
+
+    if(sftp->unlink_state == libssh2_NB_state_created) {
+        rc = _libssh2_channel_write(channel, 0, sftp->unlink_packet,
+                                    packet_len);
+        if(rc == LIBSSH2_ERROR_EAGAIN) {
+            return rc;
+        }
+        else if((ssize_t)packet_len != rc) {
+            LIBSSH2_FREE(session, sftp->unlink_packet);
+            sftp->unlink_packet = NULL;
+            sftp->unlink_state = libssh2_NB_state_idle;
+            return _libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND,
+                                  "Unable to send FXP_REMOVE command");
+        }
+        LIBSSH2_FREE(session, sftp->unlink_packet);
+        sftp->unlink_packet = NULL;
+
+        sftp->unlink_state = libssh2_NB_state_sent;
+    }
+
+    rc = sftp_packet_require(sftp, SSH_FXP_STATUS,
+                             sftp->unlink_request_id, &data,
+                             &data_len, 9);
+    if(rc == LIBSSH2_ERROR_EAGAIN) {
+        return rc;
+    }
+    else if(rc == LIBSSH2_ERROR_BUFFER_TOO_SMALL) {
+        if(data_len > 0) {
+            LIBSSH2_FREE(session, data);
+        }
+        return _libssh2_error(session, LIBSSH2_ERROR_SFTP_PROTOCOL,
+                              "SFTP unlink packet too short");
+    }
+    else if(rc) {
+        sftp->unlink_state = libssh2_NB_state_idle;
+        return _libssh2_error(session, rc,
+                              "Error waiting for FXP STATUS");
+    }
+
+    sftp->unlink_state = libssh2_NB_state_idle;
+
+    retcode = _libssh2_ntohu32(data + 5);
+    LIBSSH2_FREE(session, data);
+
+    if(retcode == LIBSSH2_FX_OK) {
+        return 0;
+    }
+    else {
+        sftp->last_errno = retcode;
+        return _libssh2_error(session, LIBSSH2_ERROR_SFTP_PROTOCOL,
+                              "SFTP Protocol Error");
+    }
+}
+
+/* libssh2_sftp_unlink_ex
+ * Delete a file from the remote server
+ */
+LIBSSH2_API int
+libssh2_sftp_unlink_ex(LIBSSH2_SFTP *sftp, const char *filename,
+                       unsigned int filename_len)
+{
+    int rc;
+    if(!sftp)
+        return LIBSSH2_ERROR_BAD_USE;
+    BLOCK_ADJUST(rc, sftp->channel->session,
+                 sftp_unlink(sftp, filename, filename_len));
+    return rc;
+}
+
+/*
+ * sftp_rename
+ *
+ * Rename a file on the remote server
+ */
+static int sftp_rename(LIBSSH2_SFTP *sftp, const char *source_filename,
+                       unsigned int source_filename_len,
+                       const char *dest_filename,
+                       unsigned int dest_filename_len, long flags)
+{
+    LIBSSH2_CHANNEL *channel = sftp->channel;
+    LIBSSH2_SESSION *session = channel->session;
+    size_t data_len;
+    int retcode;
+    uint32_t packet_len =
+        source_filename_len + dest_filename_len + 17 + (sftp->version >=
+                                                        5 ? 4 : 0);
+    /* packet_len(4) + packet_type(1) + request_id(4) +
+       source_filename_len(4) + dest_filename_len(4) + flags(4){SFTP5+) */
+    unsigned char *data;
+    ssize_t rc;
+
+    if(sftp->version < 2) {
+        return _libssh2_error(session, LIBSSH2_ERROR_SFTP_PROTOCOL,
+                              "Server does not support RENAME");
+    }
+
+    if(sftp->rename_state == libssh2_NB_state_idle) {
+        _libssh2_debug(session, LIBSSH2_TRACE_SFTP, "Renaming %s to %s",
+                       source_filename, dest_filename);
+        sftp->rename_s = sftp->rename_packet =
+            LIBSSH2_ALLOC(session, packet_len);
+        if(!sftp->rename_packet) {
+            return _libssh2_error(session, LIBSSH2_ERROR_ALLOC,
+                                  "Unable to allocate memory for FXP_RENAME "
+                                  "packet");
+        }
+
+        _libssh2_store_u32(&sftp->rename_s, packet_len - 4);
+        *(sftp->rename_s++) = SSH_FXP_RENAME;
+        sftp->rename_request_id = sftp->request_id++;
+        _libssh2_store_u32(&sftp->rename_s, sftp->rename_request_id);
+        _libssh2_store_str(&sftp->rename_s, source_filename,
+                           source_filename_len);
+        _libssh2_store_str(&sftp->rename_s, dest_filename, dest_filename_len);
+
+        if(sftp->version >= 5)
+            _libssh2_store_u32(&sftp->rename_s, flags);
+
+        sftp->rename_state = libssh2_NB_state_created;
+    }
+
+    if(sftp->rename_state == libssh2_NB_state_created) {
+        rc = _libssh2_channel_write(channel, 0, sftp->rename_packet,
+                                    sftp->rename_s - sftp->rename_packet);
+        if(rc == LIBSSH2_ERROR_EAGAIN) {
+            return rc;
+        }
+        else if((ssize_t)packet_len != rc) {
+            LIBSSH2_FREE(session, sftp->rename_packet);
+            sftp->rename_packet = NULL;
+            sftp->rename_state = libssh2_NB_state_idle;
+            return _libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND,
+                                  "Unable to send FXP_RENAME command");
+        }
+        LIBSSH2_FREE(session, sftp->rename_packet);
+        sftp->rename_packet = NULL;
+
+        sftp->rename_state = libssh2_NB_state_sent;
+    }
+
+    rc = sftp_packet_require(sftp, SSH_FXP_STATUS,
+                             sftp->rename_request_id, &data,
+                             &data_len, 9);
+    if(rc == LIBSSH2_ERROR_EAGAIN) {
+        return rc;
+    }
+    else if(rc == LIBSSH2_ERROR_BUFFER_TOO_SMALL) {
+        if(data_len > 0) {
+            LIBSSH2_FREE(session, data);
+        }
+        return _libssh2_error(session, LIBSSH2_ERROR_SFTP_PROTOCOL,
+                              "SFTP rename packet too short");
+    }
+    else if(rc) {
+        sftp->rename_state = libssh2_NB_state_idle;
+        return _libssh2_error(session, rc,
+                              "Error waiting for FXP STATUS");
+    }
+
+    sftp->rename_state = libssh2_NB_state_idle;
+
+    retcode = _libssh2_ntohu32(data + 5);
+    LIBSSH2_FREE(session, data);
+
+    sftp->last_errno = retcode;
+
+    /* now convert the SFTP error code to libssh2 return code or error
+       message */
+    switch(retcode) {
+    case LIBSSH2_FX_OK:
+        retcode = LIBSSH2_ERROR_NONE;
+        break;
+
+    case LIBSSH2_FX_FILE_ALREADY_EXISTS:
+        retcode = _libssh2_error(session, LIBSSH2_ERROR_SFTP_PROTOCOL,
+                                 "File already exists and "
+                                 "SSH_FXP_RENAME_OVERWRITE not specified");
+        break;
+
+    case LIBSSH2_FX_OP_UNSUPPORTED:
+        retcode = _libssh2_error(session, LIBSSH2_ERROR_SFTP_PROTOCOL,
+                                 "Operation Not Supported");
+        break;
+
+    default:
+        retcode = _libssh2_error(session, LIBSSH2_ERROR_SFTP_PROTOCOL,
+                                 "SFTP Protocol Error");
+        break;
+    }
+
+    return retcode;
+}
+
+/* libssh2_sftp_rename_ex
+ * Rename a file on the remote server
+ */
+LIBSSH2_API int
+libssh2_sftp_rename_ex(LIBSSH2_SFTP *sftp, const char *source_filename,
+                       unsigned int source_filename_len,
+                       const char *dest_filename,
+                       unsigned int dest_filename_len, long flags)
+{
+    int rc;
+    if(!sftp)
+        return LIBSSH2_ERROR_BAD_USE;
+    BLOCK_ADJUST(rc, sftp->channel->session,
+                 sftp_rename(sftp, source_filename, source_filename_len,
+                             dest_filename, dest_filename_len, flags));
+    return rc;
+}
+
+/*
+ * sftp_fstatvfs
+ *
+ * Get file system statistics
+ */
+static int sftp_fstatvfs(LIBSSH2_SFTP_HANDLE *handle, LIBSSH2_SFTP_STATVFS *st)
+{
+    LIBSSH2_SFTP *sftp = handle->sftp;
+    LIBSSH2_CHANNEL *channel = sftp->channel;
+    LIBSSH2_SESSION *session = channel->session;
+    size_t data_len;
+    /* 17 = packet_len(4) + packet_type(1) + request_id(4) + ext_len(4)
+       + handle_len (4) */
+    /* 20 = strlen ("fstatvfs@openssh.com") */
+    uint32_t packet_len = handle->handle_len + 20 + 17;
+    unsigned char *packet, *s, *data;
+    ssize_t rc;
+    unsigned int flag;
+    static const unsigned char responses[2] =
+        { SSH_FXP_EXTENDED_REPLY, SSH_FXP_STATUS };
+
+    if(sftp->fstatvfs_state == libssh2_NB_state_idle) {
+        _libssh2_debug(session, LIBSSH2_TRACE_SFTP,
+                       "Getting file system statistics");
+        s = packet = LIBSSH2_ALLOC(session, packet_len);
+        if(!packet) {
+            return _libssh2_error(session, LIBSSH2_ERROR_ALLOC,
+                                  "Unable to allocate memory for FXP_EXTENDED "
+                                  "packet");
+        }
+
+        _libssh2_store_u32(&s, packet_len - 4);
+        *(s++) = SSH_FXP_EXTENDED;
+        sftp->fstatvfs_request_id = sftp->request_id++;
+        _libssh2_store_u32(&s, sftp->fstatvfs_request_id);
+        _libssh2_store_str(&s, "fstatvfs@openssh.com", 20);
+        _libssh2_store_str(&s, handle->handle, handle->handle_len);
+
+        sftp->fstatvfs_state = libssh2_NB_state_created;
+    }
+    else {
+        packet = sftp->fstatvfs_packet;
+    }
+
+    if(sftp->fstatvfs_state == libssh2_NB_state_created) {
+        rc = _libssh2_channel_write(channel, 0, packet, packet_len);
+        if(rc == LIBSSH2_ERROR_EAGAIN ||
+            (0 <= rc && rc < (ssize_t)packet_len)) {
+            sftp->fstatvfs_packet = packet;
+            return LIBSSH2_ERROR_EAGAIN;
+        }
+
+        LIBSSH2_FREE(session, packet);
+        sftp->fstatvfs_packet = NULL;
+
+        if(rc < 0) {
+            sftp->fstatvfs_state = libssh2_NB_state_idle;
+            return _libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND,
+                                  "_libssh2_channel_write() failed");
+        }
+        sftp->fstatvfs_state = libssh2_NB_state_sent;
+    }
+
+    rc = sftp_packet_requirev(sftp, 2, responses, sftp->fstatvfs_request_id,
+                              &data, &data_len, 9);
+
+    if(rc == LIBSSH2_ERROR_EAGAIN) {
+        return rc;
+    }
+    else if(rc == LIBSSH2_ERROR_BUFFER_TOO_SMALL) {
+        if(data_len > 0) {
+            LIBSSH2_FREE(session, data);
+        }
+        return _libssh2_error(session, LIBSSH2_ERROR_SFTP_PROTOCOL,
+                              "SFTP rename packet too short");
+    }
+    else if(rc) {
+        sftp->fstatvfs_state = libssh2_NB_state_idle;
+        return _libssh2_error(session, rc,
+                              "Error waiting for FXP EXTENDED REPLY");
+    }
+
+    if(data[0] == SSH_FXP_STATUS) {
+        int retcode = _libssh2_ntohu32(data + 5);
+        sftp->fstatvfs_state = libssh2_NB_state_idle;
+        LIBSSH2_FREE(session, data);
+        sftp->last_errno = retcode;
+        return _libssh2_error(session, LIBSSH2_ERROR_SFTP_PROTOCOL,
+                              "SFTP Protocol Error");
+    }
+
+    if(data_len < 93) {
+        LIBSSH2_FREE(session, data);
+        sftp->fstatvfs_state = libssh2_NB_state_idle;
+        return _libssh2_error(session, LIBSSH2_ERROR_SFTP_PROTOCOL,
+                              "SFTP Protocol Error: short response");
+    }
+
+    sftp->fstatvfs_state = libssh2_NB_state_idle;
+
+    st->f_bsize = _libssh2_ntohu64(data + 5);
+    st->f_frsize = _libssh2_ntohu64(data + 13);
+    st->f_blocks = _libssh2_ntohu64(data + 21);
+    st->f_bfree = _libssh2_ntohu64(data + 29);
+    st->f_bavail = _libssh2_ntohu64(data + 37);
+    st->f_files = _libssh2_ntohu64(data + 45);
+    st->f_ffree = _libssh2_ntohu64(data + 53);
+    st->f_favail = _libssh2_ntohu64(data + 61);
+    st->f_fsid = _libssh2_ntohu64(data + 69);
+    flag = (unsigned int)_libssh2_ntohu64(data + 77);
+    st->f_namemax = _libssh2_ntohu64(data + 85);
+
+    st->f_flag = (flag & SSH_FXE_STATVFS_ST_RDONLY)
+        ? LIBSSH2_SFTP_ST_RDONLY : 0;
+    st->f_flag |= (flag & SSH_FXE_STATVFS_ST_NOSUID)
+        ? LIBSSH2_SFTP_ST_NOSUID : 0;
+
+    LIBSSH2_FREE(session, data);
+    return 0;
+}
+
+/* libssh2_sftp_fstatvfs
+ * Get filesystem space and inode utilization (requires fstatvfs@openssh.com
+ * support on the server)
+ */
+LIBSSH2_API int
+libssh2_sftp_fstatvfs(LIBSSH2_SFTP_HANDLE *handle, LIBSSH2_SFTP_STATVFS *st)
+{
+    int rc;
+    if(!handle || !st)
+        return LIBSSH2_ERROR_BAD_USE;
+    BLOCK_ADJUST(rc, handle->sftp->channel->session,
+                 sftp_fstatvfs(handle, st));
+    return rc;
+}
+
+/*
+ * sftp_statvfs
+ *
+ * Get file system statistics
+ */
+static int sftp_statvfs(LIBSSH2_SFTP *sftp, const char *path,
+                        unsigned int path_len, LIBSSH2_SFTP_STATVFS *st)
+{
+    LIBSSH2_CHANNEL *channel = sftp->channel;
+    LIBSSH2_SESSION *session = channel->session;
+    size_t data_len;
+    /* 17 = packet_len(4) + packet_type(1) + request_id(4) + ext_len(4)
+       + path_len (4) */
+    /* 19 = strlen ("statvfs@openssh.com") */
+    uint32_t packet_len = path_len + 19 + 17;
+    unsigned char *packet, *s, *data;
+    ssize_t rc;
+    unsigned int flag;
+    static const unsigned char responses[2] =
+        { SSH_FXP_EXTENDED_REPLY, SSH_FXP_STATUS };
+
+    if(sftp->statvfs_state == libssh2_NB_state_idle) {
+        _libssh2_debug(session, LIBSSH2_TRACE_SFTP,
+                       "Getting file system statistics of %s", path);
+        s = packet = LIBSSH2_ALLOC(session, packet_len);
+        if(!packet) {
+            return _libssh2_error(session, LIBSSH2_ERROR_ALLOC,
+                                  "Unable to allocate memory for FXP_EXTENDED "
+                                  "packet");
+        }
+
+        _libssh2_store_u32(&s, packet_len - 4);
+        *(s++) = SSH_FXP_EXTENDED;
+        sftp->statvfs_request_id = sftp->request_id++;
+        _libssh2_store_u32(&s, sftp->statvfs_request_id);
+        _libssh2_store_str(&s, "statvfs@openssh.com", 19);
+        _libssh2_store_str(&s, path, path_len);
+
+        sftp->statvfs_state = libssh2_NB_state_created;
+    }
+    else {
+        packet = sftp->statvfs_packet;
+    }
+
+    if(sftp->statvfs_state == libssh2_NB_state_created) {
+        rc = _libssh2_channel_write(channel, 0, packet, packet_len);
+        if(rc == LIBSSH2_ERROR_EAGAIN ||
+            (0 <= rc && rc < (ssize_t)packet_len)) {
+            sftp->statvfs_packet = packet;
+            return LIBSSH2_ERROR_EAGAIN;
+        }
+
+        LIBSSH2_FREE(session, packet);
+        sftp->statvfs_packet = NULL;
+
+        if(rc < 0) {
+            sftp->statvfs_state = libssh2_NB_state_idle;
+            return _libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND,
+                                  "_libssh2_channel_write() failed");
+        }
+        sftp->statvfs_state = libssh2_NB_state_sent;
+    }
+
+    rc = sftp_packet_requirev(sftp, 2, responses, sftp->statvfs_request_id,
+                              &data, &data_len, 9);
+    if(rc == LIBSSH2_ERROR_EAGAIN) {
+        return rc;
+    }
+    else if(rc == LIBSSH2_ERROR_BUFFER_TOO_SMALL) {
+        if(data_len > 0) {
+            LIBSSH2_FREE(session, data);
+        }
+        return _libssh2_error(session, LIBSSH2_ERROR_SFTP_PROTOCOL,
+                              "SFTP fstat packet too short");
+    }
+    else if(rc) {
+        sftp->statvfs_state = libssh2_NB_state_idle;
+        return _libssh2_error(session, rc,
+                              "Error waiting for FXP EXTENDED REPLY");
+    }
+
+    if(data[0] == SSH_FXP_STATUS) {
+        int retcode = _libssh2_ntohu32(data + 5);
+        sftp->statvfs_state = libssh2_NB_state_idle;
+        LIBSSH2_FREE(session, data);
+        sftp->last_errno = retcode;
+        return _libssh2_error(session, LIBSSH2_ERROR_SFTP_PROTOCOL,
+                              "SFTP Protocol Error");
+    }
+
+    if(data_len < 93) {
+        LIBSSH2_FREE(session, data);
+        sftp->statvfs_state = libssh2_NB_state_idle;
+        return _libssh2_error(session, LIBSSH2_ERROR_SFTP_PROTOCOL,
+                              "SFTP Protocol Error: short response");
+    }
+
+    sftp->statvfs_state = libssh2_NB_state_idle;
+
+    st->f_bsize = _libssh2_ntohu64(data + 5);
+    st->f_frsize = _libssh2_ntohu64(data + 13);
+    st->f_blocks = _libssh2_ntohu64(data + 21);
+    st->f_bfree = _libssh2_ntohu64(data + 29);
+    st->f_bavail = _libssh2_ntohu64(data + 37);
+    st->f_files = _libssh2_ntohu64(data + 45);
+    st->f_ffree = _libssh2_ntohu64(data + 53);
+    st->f_favail = _libssh2_ntohu64(data + 61);
+    st->f_fsid = _libssh2_ntohu64(data + 69);
+    flag = (unsigned int)_libssh2_ntohu64(data + 77);
+    st->f_namemax = _libssh2_ntohu64(data + 85);
+
+    st->f_flag = (flag & SSH_FXE_STATVFS_ST_RDONLY)
+        ? LIBSSH2_SFTP_ST_RDONLY : 0;
+    st->f_flag |= (flag & SSH_FXE_STATVFS_ST_NOSUID)
+        ? LIBSSH2_SFTP_ST_NOSUID : 0;
+
+    LIBSSH2_FREE(session, data);
+    return 0;
+}
+
+/* libssh2_sftp_statvfs_ex
+ * Get filesystem space and inode utilization (requires statvfs@openssh.com
+ * support on the server)
+ */
+LIBSSH2_API int
+libssh2_sftp_statvfs(LIBSSH2_SFTP *sftp, const char *path,
+                     size_t path_len, LIBSSH2_SFTP_STATVFS *st)
+{
+    int rc;
+    if(!sftp || !st)
+        return LIBSSH2_ERROR_BAD_USE;
+    BLOCK_ADJUST(rc, sftp->channel->session, sftp_statvfs(sftp, path, path_len,
+                                                          st));
+    return rc;
+}
+
+
+/*
+ * sftp_mkdir
+ *
+ * Create an SFTP directory
+ */
+static int sftp_mkdir(LIBSSH2_SFTP *sftp, const char *path,
+                      unsigned int path_len, long mode)
+{
+    LIBSSH2_CHANNEL *channel = sftp->channel;
+    LIBSSH2_SESSION *session = channel->session;
+    LIBSSH2_SFTP_ATTRIBUTES attrs = {
+        0, 0, 0, 0, 0, 0, 0
+    };
+    size_t data_len;
+    int retcode;
+    ssize_t packet_len;
+    unsigned char *packet, *s, *data;
+    int rc;
+
+    if(mode != LIBSSH2_SFTP_DEFAULT_MODE) {
+        /* Filetype in SFTP 3 and earlier */
+        attrs.flags = LIBSSH2_SFTP_ATTR_PERMISSIONS;
+        attrs.permissions = mode | LIBSSH2_SFTP_ATTR_PFILETYPE_DIR;
+    }
+
+    /* 13 = packet_len(4) + packet_type(1) + request_id(4) + path_len(4) */
+    packet_len = path_len + 13 + sftp_attrsize(attrs.flags);
+
+    if(sftp->mkdir_state == libssh2_NB_state_idle) {
+        _libssh2_debug(session, LIBSSH2_TRACE_SFTP,
+                       "Creating directory %s with mode 0%lo", path, mode);
+        s = packet = LIBSSH2_ALLOC(session, packet_len);
+        if(!packet) {
+            return _libssh2_error(session, LIBSSH2_ERROR_ALLOC,
+                                  "Unable to allocate memory for FXP_MKDIR "
+                                  "packet");
+        }
+
+        _libssh2_store_u32(&s, packet_len - 4);
+        *(s++) = SSH_FXP_MKDIR;
+        sftp->mkdir_request_id = sftp->request_id++;
+        _libssh2_store_u32(&s, sftp->mkdir_request_id);
+        _libssh2_store_str(&s, path, path_len);
+
+        s += sftp_attr2bin(s, &attrs);
+
+        sftp->mkdir_state = libssh2_NB_state_created;
+    }
+    else {
+        packet = sftp->mkdir_packet;
+    }
+
+    if(sftp->mkdir_state == libssh2_NB_state_created) {
+        rc = _libssh2_channel_write(channel, 0, packet, packet_len);
+        if(rc == LIBSSH2_ERROR_EAGAIN) {
+            sftp->mkdir_packet = packet;
+            return rc;
+        }
+        if(packet_len != rc) {
+            LIBSSH2_FREE(session, packet);
+            sftp->mkdir_state = libssh2_NB_state_idle;
+            return _libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND,
+                                  "_libssh2_channel_write() failed");
+        }
+        LIBSSH2_FREE(session, packet);
+        sftp->mkdir_state = libssh2_NB_state_sent;
+        sftp->mkdir_packet = NULL;
+    }
+
+    rc = sftp_packet_require(sftp, SSH_FXP_STATUS, sftp->mkdir_request_id,
+                             &data, &data_len, 9);
+    if(rc == LIBSSH2_ERROR_EAGAIN) {
+        return rc;
+    }
+    else if(rc == LIBSSH2_ERROR_BUFFER_TOO_SMALL) {
+        if(data_len > 0) {
+            LIBSSH2_FREE(session, data);
+        }
+        return _libssh2_error(session, LIBSSH2_ERROR_SFTP_PROTOCOL,
+                              "SFTP mkdir packet too short");
+    }
+    else if(rc) {
+        sftp->mkdir_state = libssh2_NB_state_idle;
+        return _libssh2_error(session, rc,
+                              "Error waiting for FXP STATUS");
+    }
+
+    sftp->mkdir_state = libssh2_NB_state_idle;
+
+    retcode = _libssh2_ntohu32(data + 5);
+    LIBSSH2_FREE(session, data);
+
+    if(retcode == LIBSSH2_FX_OK) {
+        _libssh2_debug(session, LIBSSH2_TRACE_SFTP, "OK!");
+        return 0;
+    }
+    else {
+        sftp->last_errno = retcode;
+        return _libssh2_error(session, LIBSSH2_ERROR_SFTP_PROTOCOL,
+                              "SFTP Protocol Error");
+    }
+}
+
+/*
+ * libssh2_sftp_mkdir_ex
+ *
+ * Create an SFTP directory
+ */
+LIBSSH2_API int
+libssh2_sftp_mkdir_ex(LIBSSH2_SFTP *sftp, const char *path,
+                      unsigned int path_len, long mode)
+{
+    int rc;
+    if(!sftp)
+        return LIBSSH2_ERROR_BAD_USE;
+    BLOCK_ADJUST(rc, sftp->channel->session,
+                 sftp_mkdir(sftp, path, path_len, mode));
+    return rc;
+}
+
+/* sftp_rmdir
+ * Remove a directory
+ */
+static int sftp_rmdir(LIBSSH2_SFTP *sftp, const char *path,
+                      unsigned int path_len)
+{
+    LIBSSH2_CHANNEL *channel = sftp->channel;
+    LIBSSH2_SESSION *session = channel->session;
+    size_t data_len;
+    int retcode;
+    /* 13 = packet_len(4) + packet_type(1) + request_id(4) + path_len(4) */
+    ssize_t packet_len = path_len + 13;
+    unsigned char *s, *data;
+    int rc;
+
+    if(sftp->rmdir_state == libssh2_NB_state_idle) {
+        _libssh2_debug(session, LIBSSH2_TRACE_SFTP, "Removing directory: %s",
+                       path);
+        s = sftp->rmdir_packet = LIBSSH2_ALLOC(session, packet_len);
+        if(!sftp->rmdir_packet) {
+            return _libssh2_error(session, LIBSSH2_ERROR_ALLOC,
+                                  "Unable to allocate memory for FXP_RMDIR "
+                                  "packet");
+        }
+
+        _libssh2_store_u32(&s, packet_len - 4);
+        *(s++) = SSH_FXP_RMDIR;
+        sftp->rmdir_request_id = sftp->request_id++;
+        _libssh2_store_u32(&s, sftp->rmdir_request_id);
+        _libssh2_store_str(&s, path, path_len);
+
+        sftp->rmdir_state = libssh2_NB_state_created;
+    }
+
+    if(sftp->rmdir_state == libssh2_NB_state_created) {
+        rc = _libssh2_channel_write(channel, 0, sftp->rmdir_packet,
+                                    packet_len);
+        if(rc == LIBSSH2_ERROR_EAGAIN) {
+            return rc;
+        }
+        else if(packet_len != rc) {
+            LIBSSH2_FREE(session, sftp->rmdir_packet);
+            sftp->rmdir_packet = NULL;
+            sftp->rmdir_state = libssh2_NB_state_idle;
+            return _libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND,
+                                  "Unable to send FXP_RMDIR command");
+        }
+        LIBSSH2_FREE(session, sftp->rmdir_packet);
+        sftp->rmdir_packet = NULL;
+
+        sftp->rmdir_state = libssh2_NB_state_sent;
+    }
+
+    rc = sftp_packet_require(sftp, SSH_FXP_STATUS,
+                             sftp->rmdir_request_id, &data, &data_len, 9);
+    if(rc == LIBSSH2_ERROR_EAGAIN) {
+        return rc;
+    }
+    else if(rc == LIBSSH2_ERROR_BUFFER_TOO_SMALL) {
+        if(data_len > 0) {
+            LIBSSH2_FREE(session, data);
+        }
+        return _libssh2_error(session, LIBSSH2_ERROR_SFTP_PROTOCOL,
+                              "SFTP rmdir packet too short");
+    }
+    else if(rc) {
+        sftp->rmdir_state = libssh2_NB_state_idle;
+        return _libssh2_error(session, rc,
+                              "Error waiting for FXP STATUS");
+    }
+
+    sftp->rmdir_state = libssh2_NB_state_idle;
+
+    retcode = _libssh2_ntohu32(data + 5);
+    LIBSSH2_FREE(session, data);
+
+    if(retcode == LIBSSH2_FX_OK) {
+        return 0;
+    }
+    else {
+        sftp->last_errno = retcode;
+        return _libssh2_error(session, LIBSSH2_ERROR_SFTP_PROTOCOL,
+                              "SFTP Protocol Error");
+    }
+}
+
+/* libssh2_sftp_rmdir_ex
+ * Remove a directory
+ */
+LIBSSH2_API int
+libssh2_sftp_rmdir_ex(LIBSSH2_SFTP *sftp, const char *path,
+                      unsigned int path_len)
+{
+    int rc;
+    if(!sftp)
+        return LIBSSH2_ERROR_BAD_USE;
+    BLOCK_ADJUST(rc, sftp->channel->session,
+                 sftp_rmdir(sftp, path, path_len));
+    return rc;
+}
+
+/* sftp_stat
+ * Stat a file or symbolic link
+ */
+static int sftp_stat(LIBSSH2_SFTP *sftp, const char *path,
+                     unsigned int path_len, int stat_type,
+                     LIBSSH2_SFTP_ATTRIBUTES * attrs)
+{
+    LIBSSH2_CHANNEL *channel = sftp->channel;
+    LIBSSH2_SESSION *session = channel->session;
+    size_t data_len;
+    /* 13 = packet_len(4) + packet_type(1) + request_id(4) + path_len(4) */
+    ssize_t packet_len =
+        path_len + 13 +
+        ((stat_type ==
+          LIBSSH2_SFTP_SETSTAT) ? sftp_attrsize(attrs->flags) : 0);
+    unsigned char *s, *data;
+    static const unsigned char stat_responses[2] =
+        { SSH_FXP_ATTRS, SSH_FXP_STATUS };
+    int rc;
+
+    if(sftp->stat_state == libssh2_NB_state_idle) {
+        _libssh2_debug(session, LIBSSH2_TRACE_SFTP, "%s %s",
+                       (stat_type == LIBSSH2_SFTP_SETSTAT) ? "Set-statting" :
+                       (stat_type ==
+                        LIBSSH2_SFTP_LSTAT ? "LStatting" : "Statting"), path);
+        s = sftp->stat_packet = LIBSSH2_ALLOC(session, packet_len);
+        if(!sftp->stat_packet) {
+            return _libssh2_error(session, LIBSSH2_ERROR_ALLOC,
+                                  "Unable to allocate memory for FXP_*STAT "
+                                  "packet");
+        }
+
+        _libssh2_store_u32(&s, packet_len - 4);
+
+        switch(stat_type) {
+        case LIBSSH2_SFTP_SETSTAT:
+            *(s++) = SSH_FXP_SETSTAT;
+            break;
+
+        case LIBSSH2_SFTP_LSTAT:
+            *(s++) = SSH_FXP_LSTAT;
+            break;
+
+        case LIBSSH2_SFTP_STAT:
+        default:
+            *(s++) = SSH_FXP_STAT;
+        }
+        sftp->stat_request_id = sftp->request_id++;
+        _libssh2_store_u32(&s, sftp->stat_request_id);
+        _libssh2_store_str(&s, path, path_len);
+
+        if(stat_type == LIBSSH2_SFTP_SETSTAT)
+            s += sftp_attr2bin(s, attrs);
+
+        sftp->stat_state = libssh2_NB_state_created;
+    }
+
+    if(sftp->stat_state == libssh2_NB_state_created) {
+        rc = _libssh2_channel_write(channel, 0, sftp->stat_packet, packet_len);
+        if(rc == LIBSSH2_ERROR_EAGAIN) {
+            return rc;
+        }
+        else if(packet_len != rc) {
+            LIBSSH2_FREE(session, sftp->stat_packet);
+            sftp->stat_packet = NULL;
+            sftp->stat_state = libssh2_NB_state_idle;
+            return _libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND,
+                                  "Unable to send STAT/LSTAT/SETSTAT command");
+        }
+        LIBSSH2_FREE(session, sftp->stat_packet);
+        sftp->stat_packet = NULL;
+
+        sftp->stat_state = libssh2_NB_state_sent;
+    }
+
+    rc = sftp_packet_requirev(sftp, 2, stat_responses,
+                              sftp->stat_request_id, &data, &data_len, 9);
+    if(rc == LIBSSH2_ERROR_EAGAIN)
+        return rc;
+    else if(rc == LIBSSH2_ERROR_BUFFER_TOO_SMALL) {
+        if(data_len > 0) {
+            LIBSSH2_FREE(session, data);
+        }
+        return _libssh2_error(session, LIBSSH2_ERROR_SFTP_PROTOCOL,
+                              "SFTP stat packet too short");
+    }
+    else if(rc) {
+        sftp->stat_state = libssh2_NB_state_idle;
+        return _libssh2_error(session, rc,
+                              "Timeout waiting for status message");
+    }
+
+    sftp->stat_state = libssh2_NB_state_idle;
+
+    if(data[0] == SSH_FXP_STATUS) {
+        int retcode;
+
+        retcode = _libssh2_ntohu32(data + 5);
+        LIBSSH2_FREE(session, data);
+        if(retcode == LIBSSH2_FX_OK) {
+            memset(attrs, 0, sizeof(LIBSSH2_SFTP_ATTRIBUTES));
+            return 0;
+        }
+        else {
+            sftp->last_errno = retcode;
+            return _libssh2_error(session, LIBSSH2_ERROR_SFTP_PROTOCOL,
+                                  "SFTP Protocol Error");
+        }
+    }
+
+    memset(attrs, 0, sizeof(LIBSSH2_SFTP_ATTRIBUTES));
+    if(sftp_bin2attr(attrs, data + 5, data_len - 5) < 0) {
+        LIBSSH2_FREE(session, data);
+        return _libssh2_error(session, LIBSSH2_ERROR_SFTP_PROTOCOL,
+                              "Attributes too short in SFTP fstat");
+    }
+
+    LIBSSH2_FREE(session, data);
+
+    return 0;
+}
+
+/* libssh2_sftp_stat_ex
+ * Stat a file or symbolic link
+ */
+LIBSSH2_API int
+libssh2_sftp_stat_ex(LIBSSH2_SFTP *sftp, const char *path,
+                     unsigned int path_len, int stat_type,
+                     LIBSSH2_SFTP_ATTRIBUTES *attrs)
+{
+    int rc;
+    if(!sftp)
+        return LIBSSH2_ERROR_BAD_USE;
+    BLOCK_ADJUST(rc, sftp->channel->session,
+                 sftp_stat(sftp, path, path_len, stat_type, attrs));
+    return rc;
+}
+
+/* sftp_symlink
+ * Read or set a symlink
+ */
+static int sftp_symlink(LIBSSH2_SFTP *sftp, const char *path,
+                        unsigned int path_len, char *target,
+                        unsigned int target_len, int link_type)
+{
+    LIBSSH2_CHANNEL *channel = sftp->channel;
+    LIBSSH2_SESSION *session = channel->session;
+    size_t data_len, link_len;
+    /* 13 = packet_len(4) + packet_type(1) + request_id(4) + path_len(4) */
+    ssize_t packet_len =
+        path_len + 13 +
+        ((link_type == LIBSSH2_SFTP_SYMLINK) ? (4 + target_len) : 0);
+    unsigned char *s, *data;
+    static const unsigned char link_responses[2] =
+        { SSH_FXP_NAME, SSH_FXP_STATUS };
+    int retcode;
+
+    if((sftp->version < 3) && (link_type != LIBSSH2_SFTP_REALPATH)) {
+        return _libssh2_error(session, LIBSSH2_ERROR_SFTP_PROTOCOL,
+                              "Server does not support SYMLINK or READLINK");
+    }
+
+    if(sftp->symlink_state == libssh2_NB_state_idle) {
+        s = sftp->symlink_packet = LIBSSH2_ALLOC(session, packet_len);
+        if(!sftp->symlink_packet) {
+            return _libssh2_error(session, LIBSSH2_ERROR_ALLOC,
+                                  "Unable to allocate memory for "
+                                  "SYMLINK/READLINK/REALPATH packet");
+        }
+
+        _libssh2_debug(session, LIBSSH2_TRACE_SFTP, "%s %s on %s",
+                       (link_type ==
+                        LIBSSH2_SFTP_SYMLINK) ? "Creating" : "Reading",
+                       (link_type ==
+                        LIBSSH2_SFTP_REALPATH) ? "realpath" : "symlink", path);
+
+        _libssh2_store_u32(&s, packet_len - 4);
+
+        switch(link_type) {
+        case LIBSSH2_SFTP_REALPATH:
+            *(s++) = SSH_FXP_REALPATH;
+            break;
+
+        case LIBSSH2_SFTP_SYMLINK:
+            *(s++) = SSH_FXP_SYMLINK;
+            break;
+
+        case LIBSSH2_SFTP_READLINK:
+        default:
+            *(s++) = SSH_FXP_READLINK;
+        }
+        sftp->symlink_request_id = sftp->request_id++;
+        _libssh2_store_u32(&s, sftp->symlink_request_id);
+        _libssh2_store_str(&s, path, path_len);
+
+        if(link_type == LIBSSH2_SFTP_SYMLINK)
+            _libssh2_store_str(&s, target, target_len);
+
+        sftp->symlink_state = libssh2_NB_state_created;
+    }
+
+    if(sftp->symlink_state == libssh2_NB_state_created) {
+        ssize_t rc = _libssh2_channel_write(channel, 0, sftp->symlink_packet,
+                                            packet_len);
+        if(rc == LIBSSH2_ERROR_EAGAIN)
+            return rc;
+        else if(packet_len != rc) {
+            LIBSSH2_FREE(session, sftp->symlink_packet);
+            sftp->symlink_packet = NULL;
+            sftp->symlink_state = libssh2_NB_state_idle;
+            return _libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND,
+                                  "Unable to send SYMLINK/READLINK command");
+        }
+        LIBSSH2_FREE(session, sftp->symlink_packet);
+        sftp->symlink_packet = NULL;
+
+        sftp->symlink_state = libssh2_NB_state_sent;
+    }
+
+    retcode = sftp_packet_requirev(sftp, 2, link_responses,
+                                   sftp->symlink_request_id, &data,
+                                   &data_len, 9);
+    if(retcode == LIBSSH2_ERROR_EAGAIN)
+        return retcode;
+    else if(retcode == LIBSSH2_ERROR_BUFFER_TOO_SMALL) {
+        if(data_len > 0) {
+            LIBSSH2_FREE(session, data);
+        }
+        return _libssh2_error(session, LIBSSH2_ERROR_SFTP_PROTOCOL,
+                              "SFTP symlink packet too short");
+    }
+    else if(retcode) {
+        sftp->symlink_state = libssh2_NB_state_idle;
+        return _libssh2_error(session, retcode,
+                              "Error waiting for status message");
+    }
+
+    sftp->symlink_state = libssh2_NB_state_idle;
+
+    if(data[0] == SSH_FXP_STATUS) {
+        retcode = _libssh2_ntohu32(data + 5);
+        LIBSSH2_FREE(session, data);
+        if(retcode == LIBSSH2_FX_OK)
+            return LIBSSH2_ERROR_NONE;
+        else {
+            sftp->last_errno = retcode;
+            return _libssh2_error(session, LIBSSH2_ERROR_SFTP_PROTOCOL,
+                                  "SFTP Protocol Error");
+        }
+    }
+
+    if(_libssh2_ntohu32(data + 5) < 1) {
+        LIBSSH2_FREE(session, data);
+        return _libssh2_error(session, LIBSSH2_ERROR_SFTP_PROTOCOL,
+                              "Invalid READLINK/REALPATH response, "
+                              "no name entries");
+    }
+
+    if(data_len < 13) {
+        if(data_len > 0) {
+            LIBSSH2_FREE(session, data);
+        }
+        return _libssh2_error(session, LIBSSH2_ERROR_SFTP_PROTOCOL,
+                              "SFTP stat packet too short");
+    }
+
+    /* this reads a u32 and stores it into a signed 32bit value */
+    link_len = _libssh2_ntohu32(data + 9);
+    if(link_len < target_len) {
+        memcpy(target, data + 13, link_len);
+        target[link_len] = 0;
+        retcode = (int)link_len;
+    }
+    else
+        retcode = LIBSSH2_ERROR_BUFFER_TOO_SMALL;
+    LIBSSH2_FREE(session, data);
+
+    return retcode;
+}
+
+/* libssh2_sftp_symlink_ex
+ * Read or set a symlink
+ */
+LIBSSH2_API int
+libssh2_sftp_symlink_ex(LIBSSH2_SFTP *sftp, const char *path,
+                        unsigned int path_len, char *target,
+                        unsigned int target_len, int link_type)
+{
+    int rc;
+    if(!sftp)
+        return LIBSSH2_ERROR_BAD_USE;
+    BLOCK_ADJUST(rc, sftp->channel->session,
+                 sftp_symlink(sftp, path, path_len, target, target_len,
+                              link_type));
+    return rc;
+}
+
+/* libssh2_sftp_last_error
+ * Returns the last error code reported by SFTP
+ */
+LIBSSH2_API unsigned long
+libssh2_sftp_last_error(LIBSSH2_SFTP *sftp)
+{
+    if(!sftp)
+        return 0;
+
+    return sftp->last_errno;
+}
+
+/* libssh2_sftp_get_channel
+ * Return the channel of sftp, then caller can control the channel's behavior.
+ */
+LIBSSH2_API LIBSSH2_CHANNEL *
+libssh2_sftp_get_channel(LIBSSH2_SFTP *sftp)
+{
+    if(!sftp)
+        return NULL;
+
+    return sftp->channel;
+}

+ 238 - 0
libssh2/libssh2/src/sftp.h

@@ -0,0 +1,238 @@
+#ifndef _LIBSSH2_SFTP_H
+#define _LIBSSH2_SFTP_H
+/*
+ * Copyright (C) 2010 - 2012 by Daniel Stenberg
+ * Author: Daniel Stenberg <daniel@haxx.se>
+ *
+ * Redistribution and use in source and binary forms,
+ * with or without modification, are permitted provided
+ * that the following conditions are met:
+ *
+ *   Redistributions of source code must retain the above
+ *   copyright notice, this list of conditions and the
+ *   following disclaimer.
+ *
+ *   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.
+ *
+ *   Neither the name of the copyright holder nor the names
+ *   of any other contributors may be used to endorse or
+ *   promote products derived from this software without
+ *   specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+ * CONTRIBUTORS "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 COPYRIGHT OWNER OR
+ * CONTRIBUTORS 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.
+ *
+ */
+
+/*
+ * MAX_SFTP_OUTGOING_SIZE MUST not be larger than 32500 or so. This is the
+ * amount of data sent in each FXP_WRITE packet
+ */
+#define MAX_SFTP_OUTGOING_SIZE 30000
+
+/* MAX_SFTP_READ_SIZE is how much data is asked for at max in each FXP_READ
+ * packets.
+ */
+#define MAX_SFTP_READ_SIZE 30000
+
+struct sftp_pipeline_chunk {
+    struct list_node node;
+    libssh2_uint64_t offset; /* READ: offset at which to start reading
+                                WRITE: not used */
+    size_t len; /* WRITE: size of the data to write
+                   READ: how many bytes that was asked for */
+    size_t sent;
+    ssize_t lefttosend; /* if 0, the entire packet has been sent off */
+    uint32_t request_id;
+    unsigned char packet[1]; /* data */
+};
+
+struct sftp_zombie_requests {
+    struct list_node node;
+    uint32_t request_id;
+};
+
+#ifndef MIN
+#define MIN(x,y) ((x)<(y)?(x):(y))
+#endif
+
+struct _LIBSSH2_SFTP_PACKET
+{
+    struct list_node node;   /* linked list header */
+    uint32_t request_id;
+    unsigned char *data;
+    size_t data_len;              /* payload size */
+};
+
+typedef struct _LIBSSH2_SFTP_PACKET LIBSSH2_SFTP_PACKET;
+
+#define SFTP_HANDLE_MAXLEN 256 /* according to spec! */
+
+struct _LIBSSH2_SFTP_HANDLE
+{
+    struct list_node node;
+
+    LIBSSH2_SFTP *sftp;
+
+    char handle[SFTP_HANDLE_MAXLEN];
+    size_t handle_len;
+
+    enum {
+        LIBSSH2_SFTP_HANDLE_FILE,
+        LIBSSH2_SFTP_HANDLE_DIR
+    } handle_type;
+
+    union _libssh2_sftp_handle_data
+    {
+        struct _libssh2_sftp_handle_file_data
+        {
+            libssh2_uint64_t offset;
+            libssh2_uint64_t offset_sent;
+            size_t acked; /* container for acked data that hasn't been
+                             returned to caller yet, used for sftp_write */
+
+            /* 'data' is used by sftp_read() and is allocated data that has
+               been received already from the server but wasn't returned to
+               the caller yet. It is of size 'data_len' and 'data_left is the
+               number of bytes not yet returned, counted from the end of the
+               buffer. */
+            unsigned char *data;
+            size_t data_len;
+            size_t data_left;
+
+            char eof; /* we have read to the end */
+        } file;
+        struct _libssh2_sftp_handle_dir_data
+        {
+            uint32_t names_left;
+            void *names_packet;
+            char *next_name;
+            size_t names_packet_len;
+        } dir;
+    } u;
+
+    /* State variables used in libssh2_sftp_close_handle() */
+    libssh2_nonblocking_states close_state;
+    uint32_t close_request_id;
+    unsigned char *close_packet;
+
+    /* list of outstanding packets sent to server */
+    struct list_head packet_list;
+
+};
+
+struct _LIBSSH2_SFTP
+{
+    LIBSSH2_CHANNEL *channel;
+
+    uint32_t request_id, version;
+
+    struct list_head packets;
+
+    /* List of FXP_READ responses to ignore because EOF already received. */
+    struct list_head zombie_requests;
+
+    /* a list of _LIBSSH2_SFTP_HANDLE structs */
+    struct list_head sftp_handles;
+
+    uint32_t last_errno;
+
+    /* Holder for partial packet, use in libssh2_sftp_packet_read() */
+    unsigned char partial_size[4];      /* buffer for size field   */
+    size_t partial_size_len;            /* size field length       */
+    unsigned char *partial_packet;      /* The data                */
+    uint32_t partial_len;               /* Desired number of bytes */
+    size_t partial_received;            /* Bytes received so far   */
+
+    /* Time that libssh2_sftp_packet_requirev() started reading */
+    time_t requirev_start;
+
+    /* State variables used in libssh2_sftp_open_ex() */
+    libssh2_nonblocking_states open_state;
+    unsigned char *open_packet;
+    uint32_t open_packet_len; /* 32 bit on the wire */
+    size_t open_packet_sent;
+    uint32_t open_request_id;
+
+    /* State variable used in sftp_read() */
+    libssh2_nonblocking_states read_state;
+
+    /* State variable used in sftp_packet_read() */
+    libssh2_nonblocking_states packet_state;
+
+    /* State variable used in sftp_write() */
+    libssh2_nonblocking_states write_state;
+
+    /* State variables used in sftp_fsync() */
+    libssh2_nonblocking_states fsync_state;
+    unsigned char *fsync_packet;
+    uint32_t fsync_request_id;
+
+    /* State variables used in libssh2_sftp_readdir() */
+    libssh2_nonblocking_states readdir_state;
+    unsigned char *readdir_packet;
+    uint32_t readdir_request_id;
+
+    /* State variables used in libssh2_sftp_fstat_ex() */
+    libssh2_nonblocking_states fstat_state;
+    unsigned char *fstat_packet;
+    uint32_t fstat_request_id;
+
+    /* State variables used in libssh2_sftp_unlink_ex() */
+    libssh2_nonblocking_states unlink_state;
+    unsigned char *unlink_packet;
+    uint32_t unlink_request_id;
+
+    /* State variables used in libssh2_sftp_rename_ex() */
+    libssh2_nonblocking_states rename_state;
+    unsigned char *rename_packet;
+    unsigned char *rename_s;
+    uint32_t rename_request_id;
+
+    /* State variables used in libssh2_sftp_fstatvfs() */
+    libssh2_nonblocking_states fstatvfs_state;
+    unsigned char *fstatvfs_packet;
+    uint32_t fstatvfs_request_id;
+
+    /* State variables used in libssh2_sftp_statvfs() */
+    libssh2_nonblocking_states statvfs_state;
+    unsigned char *statvfs_packet;
+    uint32_t statvfs_request_id;
+
+    /* State variables used in libssh2_sftp_mkdir() */
+    libssh2_nonblocking_states mkdir_state;
+    unsigned char *mkdir_packet;
+    uint32_t mkdir_request_id;
+
+    /* State variables used in libssh2_sftp_rmdir() */
+    libssh2_nonblocking_states rmdir_state;
+    unsigned char *rmdir_packet;
+    uint32_t rmdir_request_id;
+
+    /* State variables used in libssh2_sftp_stat() */
+    libssh2_nonblocking_states stat_state;
+    unsigned char *stat_packet;
+    uint32_t stat_request_id;
+
+    /* State variables used in libssh2_sftp_symlink() */
+    libssh2_nonblocking_states symlink_state;
+    unsigned char *symlink_packet;
+    uint32_t symlink_request_id;
+};
+
+#endif

+ 917 - 0
libssh2/libssh2/src/transport.c

@@ -0,0 +1,917 @@
+/* Copyright (C) 2007 The Written Word, Inc.  All rights reserved.
+ * Copyright (C) 2009-2010 by Daniel Stenberg
+ * Author: Daniel Stenberg <daniel@haxx.se>
+ *
+ * Redistribution and use in source and binary forms,
+ * with or without modification, are permitted provided
+ * that the following conditions are met:
+ *
+ *   Redistributions of source code must retain the above
+ *   copyright notice, this list of conditions and the
+ *   following disclaimer.
+ *
+ *   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.
+ *
+ *   Neither the name of the copyright holder nor the names
+ *   of any other contributors may be used to endorse or
+ *   promote products derived from this software without
+ *   specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+ * CONTRIBUTORS "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 COPYRIGHT OWNER OR
+ * CONTRIBUTORS 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.
+ *
+ * This file handles reading and writing to the SECSH transport layer. RFC4253.
+ */
+
+#include "libssh2_priv.h"
+#include <errno.h>
+#include <fcntl.h>
+#include <ctype.h>
+#ifdef LIBSSH2DEBUG
+#include <stdio.h>
+#endif
+
+#include <assert.h>
+
+#include "transport.h"
+#include "mac.h"
+
+#define MAX_BLOCKSIZE 32    /* MUST fit biggest crypto block size we use/get */
+#define MAX_MACSIZE 64      /* MUST fit biggest MAC length we support */
+
+#ifdef LIBSSH2DEBUG
+#define UNPRINTABLE_CHAR '.'
+static void
+debugdump(LIBSSH2_SESSION * session,
+          const char *desc, const unsigned char *ptr, size_t size)
+{
+    size_t i;
+    size_t c;
+    unsigned int width = 0x10;
+    char buffer[256];  /* Must be enough for width*4 + about 30 or so */
+    size_t used;
+    static const char *hex_chars = "0123456789ABCDEF";
+
+    if(!(session->showmask & LIBSSH2_TRACE_TRANS)) {
+        /* not asked for, bail out */
+        return;
+    }
+
+    used = snprintf(buffer, sizeof(buffer), "=> %s (%d bytes)\n",
+                    desc, (int) size);
+    if(session->tracehandler)
+        (session->tracehandler)(session, session->tracehandler_context,
+                                buffer, used);
+    else
+        fprintf(stderr, "%s", buffer);
+
+    for(i = 0; i < size; i += width) {
+
+        used = snprintf(buffer, sizeof(buffer), "%04lx: ", (long)i);
+
+        /* hex not disabled, show it */
+        for(c = 0; c < width; c++) {
+            if(i + c < size) {
+                buffer[used++] = hex_chars[(ptr[i + c] >> 4) & 0xF];
+                buffer[used++] = hex_chars[ptr[i + c] & 0xF];
+            }
+            else {
+                buffer[used++] = ' ';
+                buffer[used++] = ' ';
+            }
+
+            buffer[used++] = ' ';
+            if((width/2) - 1 == c)
+                buffer[used++] = ' ';
+        }
+
+        buffer[used++] = ':';
+        buffer[used++] = ' ';
+
+        for(c = 0; (c < width) && (i + c < size); c++) {
+            buffer[used++] = isprint(ptr[i + c]) ?
+                ptr[i + c] : UNPRINTABLE_CHAR;
+        }
+        buffer[used++] = '\n';
+        buffer[used] = 0;
+
+        if(session->tracehandler)
+            (session->tracehandler)(session, session->tracehandler_context,
+                                    buffer, used);
+        else
+            fprintf(stderr, "%s", buffer);
+    }
+}
+#else
+#define debugdump(a,x,y,z)
+#endif
+
+
+/* decrypt() decrypts 'len' bytes from 'source' to 'dest'.
+ *
+ * returns 0 on success and negative on failure
+ */
+
+static int
+decrypt(LIBSSH2_SESSION * session, unsigned char *source,
+        unsigned char *dest, int len)
+{
+    struct transportpacket *p = &session->packet;
+    int blocksize = session->remote.crypt->blocksize;
+
+    /* if we get called with a len that isn't an even number of blocksizes
+       we risk losing those extra bytes */
+    assert((len % blocksize) == 0);
+
+    while(len >= blocksize) {
+        if(session->remote.crypt->crypt(session, source, blocksize,
+                                         &session->remote.crypt_abstract)) {
+            LIBSSH2_FREE(session, p->payload);
+            return LIBSSH2_ERROR_DECRYPT;
+        }
+
+        /* if the crypt() function would write to a given address it
+           wouldn't have to memcpy() and we could avoid this memcpy()
+           too */
+        memcpy(dest, source, blocksize);
+
+        len -= blocksize;       /* less bytes left */
+        dest += blocksize;      /* advance write pointer */
+        source += blocksize;    /* advance read pointer */
+    }
+    return LIBSSH2_ERROR_NONE;         /* all is fine */
+}
+
+/*
+ * fullpacket() gets called when a full packet has been received and properly
+ * collected.
+ */
+static int
+fullpacket(LIBSSH2_SESSION * session, int encrypted /* 1 or 0 */ )
+{
+    unsigned char macbuf[MAX_MACSIZE];
+    struct transportpacket *p = &session->packet;
+    int rc;
+    int compressed;
+
+    if(session->fullpacket_state == libssh2_NB_state_idle) {
+        session->fullpacket_macstate = LIBSSH2_MAC_CONFIRMED;
+        session->fullpacket_payload_len = p->packet_length - 1;
+
+        if(encrypted) {
+
+            /* Calculate MAC hash */
+            session->remote.mac->hash(session, macbuf,  /* store hash here */
+                                      session->remote.seqno,
+                                      p->init, 5,
+                                      p->payload,
+                                      session->fullpacket_payload_len,
+                                      &session->remote.mac_abstract);
+
+            /* Compare the calculated hash with the MAC we just read from
+             * the network. The read one is at the very end of the payload
+             * buffer. Note that 'payload_len' here is the packet_length
+             * field which includes the padding but not the MAC.
+             */
+            if(memcmp(macbuf, p->payload + session->fullpacket_payload_len,
+                       session->remote.mac->mac_len)) {
+                session->fullpacket_macstate = LIBSSH2_MAC_INVALID;
+            }
+        }
+
+        session->remote.seqno++;
+
+        /* ignore the padding */
+        session->fullpacket_payload_len -= p->padding_length;
+
+        /* Check for and deal with decompression */
+        compressed =
+            session->local.comp != NULL &&
+            session->local.comp->compress &&
+            ((session->state & LIBSSH2_STATE_AUTHENTICATED) ||
+             session->local.comp->use_in_auth);
+
+        if(compressed && session->remote.comp_abstract) {
+            /*
+             * The buffer for the decompression (remote.comp_abstract) is
+             * initialised in time when it is needed so as long it is NULL we
+             * cannot decompress.
+             */
+
+            unsigned char *data;
+            size_t data_len;
+            rc = session->remote.comp->decomp(session,
+                                              &data, &data_len,
+                                              LIBSSH2_PACKET_MAXDECOMP,
+                                              p->payload,
+                                              session->fullpacket_payload_len,
+                                              &session->remote.comp_abstract);
+            LIBSSH2_FREE(session, p->payload);
+            if(rc)
+                return rc;
+
+            p->payload = data;
+            session->fullpacket_payload_len = data_len;
+        }
+
+        session->fullpacket_packet_type = p->payload[0];
+
+        debugdump(session, "libssh2_transport_read() plain",
+                  p->payload, session->fullpacket_payload_len);
+
+        session->fullpacket_state = libssh2_NB_state_created;
+    }
+
+    if(session->fullpacket_state == libssh2_NB_state_created) {
+        rc = _libssh2_packet_add(session, p->payload,
+                                 session->fullpacket_payload_len,
+                                 session->fullpacket_macstate);
+        if(rc == LIBSSH2_ERROR_EAGAIN)
+            return rc;
+        if(rc) {
+            session->fullpacket_state = libssh2_NB_state_idle;
+            return rc;
+        }
+    }
+
+    session->fullpacket_state = libssh2_NB_state_idle;
+
+    return session->fullpacket_packet_type;
+}
+
+
+/*
+ * _libssh2_transport_read
+ *
+ * Collect a packet into the input queue.
+ *
+ * Returns packet type added to input queue (0 if nothing added), or a
+ * negative error number.
+ */
+
+/*
+ * This function reads the binary stream as specified in chapter 6 of RFC4253
+ * "The Secure Shell (SSH) Transport Layer Protocol"
+ *
+ * DOES NOT call _libssh2_error() for ANY error case.
+ */
+int _libssh2_transport_read(LIBSSH2_SESSION * session)
+{
+    int rc;
+    struct transportpacket *p = &session->packet;
+    int remainbuf;
+    int remainpack;
+    int numbytes;
+    int numdecrypt;
+    unsigned char block[MAX_BLOCKSIZE];
+    int blocksize;
+    int encrypted = 1;
+
+    /* default clear the bit */
+    session->socket_block_directions &= ~LIBSSH2_SESSION_BLOCK_INBOUND;
+
+    /*
+     * All channels, systems, subsystems, etc eventually make it down here
+     * when looking for more incoming data. If a key exchange is going on
+     * (LIBSSH2_STATE_EXCHANGING_KEYS bit is set) then the remote end will
+     * ONLY send key exchange related traffic. In non-blocking mode, there is
+     * a chance to break out of the kex_exchange function with an EAGAIN
+     * status, and never come back to it. If LIBSSH2_STATE_EXCHANGING_KEYS is
+     * active, then we must redirect to the key exchange. However, if
+     * kex_exchange is active (as in it is the one that calls this execution
+     * of packet_read, then don't redirect, as that would be an infinite loop!
+     */
+
+    if(session->state & LIBSSH2_STATE_EXCHANGING_KEYS &&
+        !(session->state & LIBSSH2_STATE_KEX_ACTIVE)) {
+
+        /* Whoever wants a packet won't get anything until the key re-exchange
+         * is done!
+         */
+        _libssh2_debug(session, LIBSSH2_TRACE_TRANS, "Redirecting into the"
+                       " key re-exchange from _libssh2_transport_read");
+        rc = _libssh2_kex_exchange(session, 1, &session->startup_key_state);
+        if(rc)
+            return rc;
+    }
+
+    /*
+     * =============================== NOTE ===============================
+     * I know this is very ugly and not a really good use of "goto", but
+     * this case statement would be even uglier to do it any other way
+     */
+    if(session->readPack_state == libssh2_NB_state_jump1) {
+        session->readPack_state = libssh2_NB_state_idle;
+        encrypted = session->readPack_encrypted;
+        goto libssh2_transport_read_point1;
+    }
+
+    do {
+        if(session->socket_state == LIBSSH2_SOCKET_DISCONNECTED) {
+            return LIBSSH2_ERROR_NONE;
+        }
+
+        if(session->state & LIBSSH2_STATE_NEWKEYS) {
+            blocksize = session->remote.crypt->blocksize;
+        }
+        else {
+            encrypted = 0;      /* not encrypted */
+            blocksize = 5;      /* not strictly true, but we can use 5 here to
+                                   make the checks below work fine still */
+        }
+
+        /* read/use a whole big chunk into a temporary area stored in
+           the LIBSSH2_SESSION struct. We will decrypt data from that
+           buffer into the packet buffer so this temp one doesn't have
+           to be able to keep a whole SSH packet, just be large enough
+           so that we can read big chunks from the network layer. */
+
+        /* how much data there is remaining in the buffer to deal with
+           before we should read more from the network */
+        remainbuf = p->writeidx - p->readidx;
+
+        /* if remainbuf turns negative we have a bad internal error */
+        assert(remainbuf >= 0);
+
+        if(remainbuf < blocksize) {
+            /* If we have less than a blocksize left, it is too
+               little data to deal with, read more */
+            ssize_t nread;
+
+            /* move any remainder to the start of the buffer so
+               that we can do a full refill */
+            if(remainbuf) {
+                memmove(p->buf, &p->buf[p->readidx], remainbuf);
+                p->readidx = 0;
+                p->writeidx = remainbuf;
+            }
+            else {
+                /* nothing to move, just zero the indexes */
+                p->readidx = p->writeidx = 0;
+            }
+
+            /* now read a big chunk from the network into the temp buffer */
+            nread =
+                LIBSSH2_RECV(session, &p->buf[remainbuf],
+                              PACKETBUFSIZE - remainbuf,
+                              LIBSSH2_SOCKET_RECV_FLAGS(session));
+            if(nread <= 0) {
+                /* check if this is due to EAGAIN and return the special
+                   return code if so, error out normally otherwise */
+                if((nread < 0) && (nread == -EAGAIN)) {
+                    session->socket_block_directions |=
+                        LIBSSH2_SESSION_BLOCK_INBOUND;
+                    return LIBSSH2_ERROR_EAGAIN;
+                }
+                _libssh2_debug(session, LIBSSH2_TRACE_SOCKET,
+                               "Error recving %d bytes (got %d)",
+                               PACKETBUFSIZE - remainbuf, -nread);
+                return LIBSSH2_ERROR_SOCKET_RECV;
+            }
+            _libssh2_debug(session, LIBSSH2_TRACE_SOCKET,
+                           "Recved %d/%d bytes to %p+%d", nread,
+                           PACKETBUFSIZE - remainbuf, p->buf, remainbuf);
+
+            debugdump(session, "libssh2_transport_read() raw",
+                      &p->buf[remainbuf], nread);
+            /* advance write pointer */
+            p->writeidx += nread;
+
+            /* update remainbuf counter */
+            remainbuf = p->writeidx - p->readidx;
+        }
+
+        /* how much data to deal with from the buffer */
+        numbytes = remainbuf;
+
+        if(!p->total_num) {
+            size_t total_num;
+
+            /* No payload package area allocated yet. To know the
+               size of this payload, we need to decrypt the first
+               blocksize data. */
+
+            if(numbytes < blocksize) {
+                /* we can't act on anything less than blocksize, but this
+                   check is only done for the initial block since once we have
+                   got the start of a block we can in fact deal with fractions
+                */
+                session->socket_block_directions |=
+                    LIBSSH2_SESSION_BLOCK_INBOUND;
+                return LIBSSH2_ERROR_EAGAIN;
+            }
+
+            if(encrypted) {
+                rc = decrypt(session, &p->buf[p->readidx], block, blocksize);
+                if(rc != LIBSSH2_ERROR_NONE) {
+                    return rc;
+                }
+                /* save the first 5 bytes of the decrypted package, to be
+                   used in the hash calculation later down. */
+                memcpy(p->init, block, 5);
+            }
+            else {
+                /* the data is plain, just copy it verbatim to
+                   the working block buffer */
+                memcpy(block, &p->buf[p->readidx], blocksize);
+            }
+
+            /* advance the read pointer */
+            p->readidx += blocksize;
+
+            /* we now have the initial blocksize bytes decrypted,
+             * and we can extract packet and padding length from it
+             */
+            p->packet_length = _libssh2_ntohu32(block);
+            if(p->packet_length < 1) {
+                return LIBSSH2_ERROR_DECRYPT;
+            }
+            else if(p->packet_length > LIBSSH2_PACKET_MAXPAYLOAD) {
+                return LIBSSH2_ERROR_OUT_OF_BOUNDARY;
+            }
+
+            p->padding_length = block[4];
+            if(p->padding_length > p->packet_length - 1) {
+                return LIBSSH2_ERROR_DECRYPT;
+            }
+
+
+            /* total_num is the number of bytes following the initial
+               (5 bytes) packet length and padding length fields */
+            total_num =
+                p->packet_length - 1 +
+                (encrypted ? session->remote.mac->mac_len : 0);
+
+            /* RFC4253 section 6.1 Maximum Packet Length says:
+             *
+             * "All implementations MUST be able to process
+             * packets with uncompressed payload length of 32768
+             * bytes or less and total packet size of 35000 bytes
+             * or less (including length, padding length, payload,
+             * padding, and MAC.)."
+             */
+            if(total_num > LIBSSH2_PACKET_MAXPAYLOAD) {
+                return LIBSSH2_ERROR_OUT_OF_BOUNDARY;
+            }
+
+            /* Get a packet handle put data into. We get one to
+               hold all data, including padding and MAC. */
+            p->payload = LIBSSH2_ALLOC(session, total_num);
+            if(!p->payload) {
+                return LIBSSH2_ERROR_ALLOC;
+            }
+            p->total_num = total_num;
+            /* init write pointer to start of payload buffer */
+            p->wptr = p->payload;
+
+            if(blocksize > 5) {
+                /* copy the data from index 5 to the end of
+                   the blocksize from the temporary buffer to
+                   the start of the decrypted buffer */
+                if(blocksize - 5 <= (int) total_num) {
+                    memcpy(p->wptr, &block[5], blocksize - 5);
+                    p->wptr += blocksize - 5;       /* advance write pointer */
+                }
+                else {
+                    return LIBSSH2_ERROR_OUT_OF_BOUNDARY;
+                }
+            }
+
+            /* init the data_num field to the number of bytes of
+               the package read so far */
+            p->data_num = p->wptr - p->payload;
+
+            /* we already dealt with a blocksize worth of data */
+            numbytes -= blocksize;
+        }
+
+        /* how much there is left to add to the current payload
+           package */
+        remainpack = p->total_num - p->data_num;
+
+        if(numbytes > remainpack) {
+            /* if we have more data in the buffer than what is going into this
+               particular packet, we limit this round to this packet only */
+            numbytes = remainpack;
+        }
+
+        if(encrypted) {
+            /* At the end of the incoming stream, there is a MAC,
+               and we don't want to decrypt that since we need it
+               "raw". We MUST however decrypt the padding data
+               since it is used for the hash later on. */
+            int skip = session->remote.mac->mac_len;
+
+            /* if what we have plus numbytes is bigger than the
+               total minus the skip margin, we should lower the
+               amount to decrypt even more */
+            if((p->data_num + numbytes) > (p->total_num - skip)) {
+                numdecrypt = (p->total_num - skip) - p->data_num;
+            }
+            else {
+                int frac;
+                numdecrypt = numbytes;
+                frac = numdecrypt % blocksize;
+                if(frac) {
+                    /* not an aligned amount of blocks,
+                       align it */
+                    numdecrypt -= frac;
+                    /* and make it no unencrypted data
+                       after it */
+                    numbytes = 0;
+                }
+            }
+        }
+        else {
+            /* unencrypted data should not be decrypted at all */
+            numdecrypt = 0;
+        }
+
+        /* if there are bytes to decrypt, do that */
+        if(numdecrypt > 0) {
+            /* now decrypt the lot */
+            rc = decrypt(session, &p->buf[p->readidx], p->wptr, numdecrypt);
+            if(rc != LIBSSH2_ERROR_NONE) {
+                p->total_num = 0;   /* no packet buffer available */
+                return rc;
+            }
+
+            /* advance the read pointer */
+            p->readidx += numdecrypt;
+            /* advance write pointer */
+            p->wptr += numdecrypt;
+            /* increase data_num */
+            p->data_num += numdecrypt;
+
+            /* bytes left to take care of without decryption */
+            numbytes -= numdecrypt;
+        }
+
+        /* if there are bytes to copy that aren't decrypted, simply
+           copy them as-is to the target buffer */
+        if(numbytes > 0) {
+
+            if(numbytes <= (int)(p->total_num - (p->wptr - p->payload))) {
+                memcpy(p->wptr, &p->buf[p->readidx], numbytes);
+            }
+            else {
+                return LIBSSH2_ERROR_OUT_OF_BOUNDARY;
+            }
+
+            /* advance the read pointer */
+            p->readidx += numbytes;
+            /* advance write pointer */
+            p->wptr += numbytes;
+            /* increase data_num */
+            p->data_num += numbytes;
+        }
+
+        /* now check how much data there's left to read to finish the
+           current packet */
+        remainpack = p->total_num - p->data_num;
+
+        if(!remainpack) {
+            /* we have a full packet */
+          libssh2_transport_read_point1:
+            rc = fullpacket(session, encrypted);
+            if(rc == LIBSSH2_ERROR_EAGAIN) {
+
+                if(session->packAdd_state != libssh2_NB_state_idle) {
+                    /* fullpacket only returns LIBSSH2_ERROR_EAGAIN if
+                     * libssh2_packet_add returns LIBSSH2_ERROR_EAGAIN. If
+                     * that returns LIBSSH2_ERROR_EAGAIN but the packAdd_state
+                     * is idle, then the packet has been added to the brigade,
+                     * but some immediate action that was taken based on the
+                     * packet type (such as key re-exchange) is not yet
+                     * complete.  Clear the way for a new packet to be read
+                     * in.
+                     */
+                    session->readPack_encrypted = encrypted;
+                    session->readPack_state = libssh2_NB_state_jump1;
+                }
+
+                return rc;
+            }
+
+            p->total_num = 0;   /* no packet buffer available */
+
+            return rc;
+        }
+    } while(1);                /* loop */
+
+    return LIBSSH2_ERROR_SOCKET_RECV; /* we never reach this point */
+}
+
+static int
+send_existing(LIBSSH2_SESSION *session, const unsigned char *data,
+              size_t data_len, ssize_t *ret)
+{
+    ssize_t rc;
+    ssize_t length;
+    struct transportpacket *p = &session->packet;
+
+    if(!p->olen) {
+        *ret = 0;
+        return LIBSSH2_ERROR_NONE;
+    }
+
+    /* send as much as possible of the existing packet */
+    if((data != p->odata) || (data_len != p->olen)) {
+        /* When we are about to complete the sending of a packet, it is vital
+           that the caller doesn't try to send a new/different packet since
+           we don't add this one up until the previous one has been sent. To
+           make the caller really notice his/hers flaw, we return error for
+           this case */
+        return LIBSSH2_ERROR_BAD_USE;
+    }
+
+    *ret = 1;                   /* set to make our parent return */
+
+    /* number of bytes left to send */
+    length = p->ototal_num - p->osent;
+
+    rc = LIBSSH2_SEND(session, &p->outbuf[p->osent], length,
+                       LIBSSH2_SOCKET_SEND_FLAGS(session));
+    if(rc < 0)
+        _libssh2_debug(session, LIBSSH2_TRACE_SOCKET,
+                       "Error sending %d bytes: %d", length, -rc);
+    else {
+        _libssh2_debug(session, LIBSSH2_TRACE_SOCKET,
+                       "Sent %d/%d bytes at %p+%d", rc, length, p->outbuf,
+                       p->osent);
+        debugdump(session, "libssh2_transport_write send()",
+                  &p->outbuf[p->osent], rc);
+    }
+
+    if(rc == length) {
+        /* the remainder of the package was sent */
+        p->ototal_num = 0;
+        p->olen = 0;
+        /* we leave *ret set so that the parent returns as we MUST return back
+           a send success now, so that we don't risk sending EAGAIN later
+           which then would confuse the parent function */
+        return LIBSSH2_ERROR_NONE;
+
+    }
+    else if(rc < 0) {
+        /* nothing was sent */
+        if(rc != -EAGAIN)
+            /* send failure! */
+            return LIBSSH2_ERROR_SOCKET_SEND;
+
+        session->socket_block_directions |= LIBSSH2_SESSION_BLOCK_OUTBOUND;
+        return LIBSSH2_ERROR_EAGAIN;
+    }
+
+    p->osent += rc;         /* we sent away this much data */
+
+    return rc < length ? LIBSSH2_ERROR_EAGAIN : LIBSSH2_ERROR_NONE;
+}
+
+/*
+ * libssh2_transport_send
+ *
+ * Send a packet, encrypting it and adding a MAC code if necessary
+ * Returns 0 on success, non-zero on failure.
+ *
+ * The data is provided as _two_ data areas that are combined by this
+ * function.  The 'data' part is sent immediately before 'data2'. 'data2' may
+ * be set to NULL to only use a single part.
+ *
+ * Returns LIBSSH2_ERROR_EAGAIN if it would block or if the whole packet was
+ * not sent yet. If it does so, the caller should call this function again as
+ * soon as it is likely that more data can be sent, and this function MUST
+ * then be called with the same argument set (same data pointer and same
+ * data_len) until ERROR_NONE or failure is returned.
+ *
+ * This function DOES NOT call _libssh2_error() on any errors.
+ */
+int _libssh2_transport_send(LIBSSH2_SESSION *session,
+                            const unsigned char *data, size_t data_len,
+                            const unsigned char *data2, size_t data2_len)
+{
+    int blocksize =
+        (session->state & LIBSSH2_STATE_NEWKEYS) ?
+        session->local.crypt->blocksize : 8;
+    int padding_length;
+    size_t packet_length;
+    int total_length;
+#ifdef RANDOM_PADDING
+    int rand_max;
+    int seed = data[0];         /* FIXME: make this random */
+#endif
+    struct transportpacket *p = &session->packet;
+    int encrypted;
+    int compressed;
+    ssize_t ret;
+    int rc;
+    const unsigned char *orgdata = data;
+    size_t orgdata_len = data_len;
+
+    /*
+     * If the last read operation was interrupted in the middle of a key
+     * exchange, we must complete that key exchange before continuing to write
+     * further data.
+     *
+     * See the similar block in _libssh2_transport_read for more details.
+     */
+    if(session->state & LIBSSH2_STATE_EXCHANGING_KEYS &&
+        !(session->state & LIBSSH2_STATE_KEX_ACTIVE)) {
+        /* Don't write any new packets if we're still in the middle of a key
+         * exchange. */
+        _libssh2_debug(session, LIBSSH2_TRACE_TRANS, "Redirecting into the"
+                       " key re-exchange from _libssh2_transport_send");
+        rc = _libssh2_kex_exchange(session, 1, &session->startup_key_state);
+        if(rc)
+            return rc;
+    }
+
+    debugdump(session, "libssh2_transport_write plain", data, data_len);
+    if(data2)
+        debugdump(session, "libssh2_transport_write plain2", data2, data2_len);
+
+    /* FIRST, check if we have a pending write to complete. send_existing
+       only sanity-check data and data_len and not data2 and data2_len!! */
+    rc = send_existing(session, data, data_len, &ret);
+    if(rc)
+        return rc;
+
+    session->socket_block_directions &= ~LIBSSH2_SESSION_BLOCK_OUTBOUND;
+
+    if(ret)
+        /* set by send_existing if data was sent */
+        return rc;
+
+    encrypted = (session->state & LIBSSH2_STATE_NEWKEYS) ? 1 : 0;
+
+    compressed =
+        session->local.comp != NULL &&
+        session->local.comp->compress &&
+        ((session->state & LIBSSH2_STATE_AUTHENTICATED) ||
+         session->local.comp->use_in_auth);
+
+    if(encrypted && compressed) {
+        /* the idea here is that these function must fail if the output gets
+           larger than what fits in the assigned buffer so thus they don't
+           check the input size as we don't know how much it compresses */
+        size_t dest_len = MAX_SSH_PACKET_LEN-5-256;
+        size_t dest2_len = dest_len;
+
+        /* compress directly to the target buffer */
+        rc = session->local.comp->comp(session,
+                                       &p->outbuf[5], &dest_len,
+                                       data, data_len,
+                                       &session->local.comp_abstract);
+        if(rc)
+            return rc;     /* compression failure */
+
+        if(data2 && data2_len) {
+            /* compress directly to the target buffer right after where the
+               previous call put data */
+            dest2_len -= dest_len;
+
+            rc = session->local.comp->comp(session,
+                                           &p->outbuf[5 + dest_len],
+                                           &dest2_len,
+                                           data2, data2_len,
+                                           &session->local.comp_abstract);
+        }
+        else
+            dest2_len = 0;
+        if(rc)
+            return rc;     /* compression failure */
+
+        data_len = dest_len + dest2_len; /* use the combined length */
+    }
+    else {
+        if((data_len + data2_len) >= (MAX_SSH_PACKET_LEN-0x100))
+            /* too large packet, return error for this until we make this
+               function split it up and send multiple SSH packets */
+            return LIBSSH2_ERROR_INVAL;
+
+        /* copy the payload data */
+        memcpy(&p->outbuf[5], data, data_len);
+        if(data2 && data2_len)
+            memcpy(&p->outbuf[5 + data_len], data2, data2_len);
+        data_len += data2_len; /* use the combined length */
+    }
+
+
+    /* RFC4253 says: Note that the length of the concatenation of
+       'packet_length', 'padding_length', 'payload', and 'random padding'
+       MUST be a multiple of the cipher block size or 8, whichever is
+       larger. */
+
+    /* Plain math: (4 + 1 + packet_length + padding_length) % blocksize == 0 */
+
+    packet_length = data_len + 1 + 4;   /* 1 is for padding_length field
+                                           4 for the packet_length field */
+
+    /* at this point we have it all except the padding */
+
+    /* first figure out our minimum padding amount to make it an even
+       block size */
+    padding_length = blocksize - (packet_length % blocksize);
+
+    /* if the padding becomes too small we add another blocksize worth
+       of it (taken from the original libssh2 where it didn't have any
+       real explanation) */
+    if(padding_length < 4) {
+        padding_length += blocksize;
+    }
+#ifdef RANDOM_PADDING
+    /* FIXME: we can add padding here, but that also makes the packets
+       bigger etc */
+
+    /* now we can add 'blocksize' to the padding_length N number of times
+       (to "help thwart traffic analysis") but it must be less than 255 in
+       total */
+    rand_max = (255 - padding_length) / blocksize + 1;
+    padding_length += blocksize * (seed % rand_max);
+#endif
+
+    packet_length += padding_length;
+
+    /* append the MAC length to the total_length size */
+    total_length =
+        packet_length + (encrypted ? session->local.mac->mac_len : 0);
+
+    /* store packet_length, which is the size of the whole packet except
+       the MAC and the packet_length field itself */
+    _libssh2_htonu32(p->outbuf, packet_length - 4);
+    /* store padding_length */
+    p->outbuf[4] = (unsigned char)padding_length;
+
+    /* fill the padding area with random junk */
+    _libssh2_random(p->outbuf + 5 + data_len, padding_length);
+
+    if(encrypted) {
+        size_t i;
+
+        /* Calculate MAC hash. Put the output at index packet_length,
+           since that size includes the whole packet. The MAC is
+           calculated on the entire unencrypted packet, including all
+           fields except the MAC field itself. */
+        session->local.mac->hash(session, p->outbuf + packet_length,
+                                 session->local.seqno, p->outbuf,
+                                 packet_length, NULL, 0,
+                                 &session->local.mac_abstract);
+
+        /* Encrypt the whole packet data, one block size at a time.
+           The MAC field is not encrypted. */
+        for(i = 0; i < packet_length; i += session->local.crypt->blocksize) {
+            unsigned char *ptr = &p->outbuf[i];
+            if(session->local.crypt->crypt(session, ptr,
+                                            session->local.crypt->blocksize,
+                                            &session->local.crypt_abstract))
+                return LIBSSH2_ERROR_ENCRYPT;     /* encryption failure */
+        }
+    }
+
+    session->local.seqno++;
+
+    ret = LIBSSH2_SEND(session, p->outbuf, total_length,
+                        LIBSSH2_SOCKET_SEND_FLAGS(session));
+    if(ret < 0)
+        _libssh2_debug(session, LIBSSH2_TRACE_SOCKET,
+                       "Error sending %d bytes: %d", total_length, -ret);
+    else {
+        _libssh2_debug(session, LIBSSH2_TRACE_SOCKET, "Sent %d/%d bytes at %p",
+                       ret, total_length, p->outbuf);
+        debugdump(session, "libssh2_transport_write send()", p->outbuf, ret);
+    }
+
+    if(ret != total_length) {
+        if(ret >= 0 || ret == -EAGAIN) {
+            /* the whole packet could not be sent, save the rest */
+            session->socket_block_directions |= LIBSSH2_SESSION_BLOCK_OUTBOUND;
+            p->odata = orgdata;
+            p->olen = orgdata_len;
+            p->osent = ret <= 0 ? 0 : ret;
+            p->ototal_num = total_length;
+            return LIBSSH2_ERROR_EAGAIN;
+        }
+        return LIBSSH2_ERROR_SOCKET_SEND;
+    }
+
+    /* the whole thing got sent away */
+    p->odata = NULL;
+    p->olen = 0;
+
+    return LIBSSH2_ERROR_NONE;         /* all is good */
+}

+ 87 - 0
libssh2/libssh2/src/transport.h

@@ -0,0 +1,87 @@
+#ifndef __LIBSSH2_TRANSPORT_H
+#define __LIBSSH2_TRANSPORT_H
+
+/* Copyright (C) 2007 The Written Word, Inc.  All rights reserved.
+ * Copyright (C) 2009-2010 by Daniel Stenberg
+ * Author: Daniel Stenberg <daniel@haxx.se>
+ *
+ * Redistribution and use in source and binary forms,
+ * with or without modification, are permitted provided
+ * that the following conditions are met:
+ *
+ *   Redistributions of source code must retain the above
+ *   copyright notice, this list of conditions and the
+ *   following disclaimer.
+ *
+ *   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.
+ *
+ *   Neither the name of the copyright holder nor the names
+ *   of any other contributors may be used to endorse or
+ *   promote products derived from this software without
+ *   specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+ * CONTRIBUTORS "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 COPYRIGHT OWNER OR
+ * CONTRIBUTORS 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.
+ *
+ * This file handles reading and writing to the SECSH transport layer. RFC4253.
+ */
+
+#include "libssh2_priv.h"
+#include "packet.h"
+
+
+/*
+ * libssh2_transport_send
+ *
+ * Send a packet, encrypting it and adding a MAC code if necessary
+ * Returns 0 on success, non-zero on failure.
+ *
+ * The data is provided as _two_ data areas that are combined by this
+ * function.  The 'data' part is sent immediately before 'data2'. 'data2' can
+ * be set to NULL (or data2_len to 0) to only use a single part.
+ *
+ * Returns LIBSSH2_ERROR_EAGAIN if it would block or if the whole packet was
+ * not sent yet. If it does so, the caller should call this function again as
+ * soon as it is likely that more data can be sent, and this function MUST
+ * then be called with the same argument set (same data pointer and same
+ * data_len) until ERROR_NONE or failure is returned.
+ *
+ * This function DOES NOT call _libssh2_error() on any errors.
+ */
+int _libssh2_transport_send(LIBSSH2_SESSION *session,
+                            const unsigned char *data, size_t data_len,
+                            const unsigned char *data2, size_t data2_len);
+
+/*
+ * _libssh2_transport_read
+ *
+ * Collect a packet into the input brigade block only controls whether or not
+ * to wait for a packet to start.
+ *
+ * Returns packet type added to input brigade (PACKET_NONE if nothing added),
+ * or PACKET_FAIL on failure and PACKET_EAGAIN if it couldn't process a full
+ * packet.
+ */
+
+/*
+ * This function reads the binary stream as specified in chapter 6 of RFC4253
+ * "The Secure Shell (SSH) Transport Layer Protocol"
+ */
+int _libssh2_transport_read(LIBSSH2_SESSION * session);
+
+#endif /* __LIBSSH2_TRANSPORT_H */

+ 2110 - 0
libssh2/libssh2/src/userauth.c

@@ -0,0 +1,2110 @@
+/* Copyright (c) 2004-2007, Sara Golemon <sarag@libssh2.org>
+ * Copyright (c) 2005 Mikhail Gusarov <dottedmag@dottedmag.net>
+ * Copyright (c) 2009-2014 by Daniel Stenberg
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms,
+ * with or without modification, are permitted provided
+ * that the following conditions are met:
+ *
+ *   Redistributions of source code must retain the above
+ *   copyright notice, this list of conditions and the
+ *   following disclaimer.
+ *
+ *   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.
+ *
+ *   Neither the name of the copyright holder nor the names
+ *   of any other contributors may be used to endorse or
+ *   promote products derived from this software without
+ *   specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+ * CONTRIBUTORS "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 COPYRIGHT OWNER OR
+ * CONTRIBUTORS 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 "libssh2_priv.h"
+
+#include <ctype.h>
+#include <stdio.h>
+
+#include <assert.h>
+
+/* Needed for struct iovec on some platforms */
+#ifdef HAVE_SYS_UIO_H
+#include <sys/uio.h>
+#endif
+
+#include "transport.h"
+#include "session.h"
+#include "userauth.h"
+
+/* libssh2_userauth_list
+ *
+ * List authentication methods
+ * Will yield successful login if "none" happens to be allowable for this user
+ * Not a common configuration for any SSH server though
+ * username should be NULL, or a null terminated string
+ */
+static char *userauth_list(LIBSSH2_SESSION *session, const char *username,
+                           unsigned int username_len)
+{
+    static const unsigned char reply_codes[3] =
+        { SSH_MSG_USERAUTH_SUCCESS, SSH_MSG_USERAUTH_FAILURE, 0 };
+    /* packet_type(1) + username_len(4) + service_len(4) +
+       service(14)"ssh-connection" + method_len(4) = 27 */
+    unsigned long methods_len;
+    unsigned char *s;
+    int rc;
+
+    if(session->userauth_list_state == libssh2_NB_state_idle) {
+        /* Zero the whole thing out */
+        memset(&session->userauth_list_packet_requirev_state, 0,
+               sizeof(session->userauth_list_packet_requirev_state));
+
+        session->userauth_list_data_len = username_len + 27;
+
+        s = session->userauth_list_data =
+            LIBSSH2_ALLOC(session, session->userauth_list_data_len);
+        if(!session->userauth_list_data) {
+            _libssh2_error(session, LIBSSH2_ERROR_ALLOC,
+                           "Unable to allocate memory for userauth_list");
+            return NULL;
+        }
+
+        *(s++) = SSH_MSG_USERAUTH_REQUEST;
+        _libssh2_store_str(&s, username, username_len);
+        _libssh2_store_str(&s, "ssh-connection", 14);
+        _libssh2_store_u32(&s, 4); /* send "none" separately */
+
+        session->userauth_list_state = libssh2_NB_state_created;
+    }
+
+    if(session->userauth_list_state == libssh2_NB_state_created) {
+        rc = _libssh2_transport_send(session, session->userauth_list_data,
+                                     session->userauth_list_data_len,
+                                     (unsigned char *)"none", 4);
+        if(rc == LIBSSH2_ERROR_EAGAIN) {
+            _libssh2_error(session, LIBSSH2_ERROR_EAGAIN,
+                           "Would block requesting userauth list");
+            return NULL;
+        }
+        /* now free the packet that was sent */
+        LIBSSH2_FREE(session, session->userauth_list_data);
+        session->userauth_list_data = NULL;
+
+        if(rc) {
+            _libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND,
+                           "Unable to send userauth-none request");
+            session->userauth_list_state = libssh2_NB_state_idle;
+            return NULL;
+        }
+
+        session->userauth_list_state = libssh2_NB_state_sent;
+    }
+
+    if(session->userauth_list_state == libssh2_NB_state_sent) {
+        rc = _libssh2_packet_requirev(session, reply_codes,
+                                      &session->userauth_list_data,
+                                      &session->userauth_list_data_len, 0,
+                                      NULL, 0,
+                               &session->userauth_list_packet_requirev_state);
+        if(rc == LIBSSH2_ERROR_EAGAIN) {
+            _libssh2_error(session, LIBSSH2_ERROR_EAGAIN,
+                           "Would block requesting userauth list");
+            return NULL;
+        }
+        else if(rc || (session->userauth_list_data_len < 1)) {
+            _libssh2_error(session, rc, "Failed getting response");
+            session->userauth_list_state = libssh2_NB_state_idle;
+            return NULL;
+        }
+
+        if(session->userauth_list_data[0] == SSH_MSG_USERAUTH_SUCCESS) {
+            /* Wow, who'dve thought... */
+            _libssh2_error(session, LIBSSH2_ERROR_NONE, "No error");
+            LIBSSH2_FREE(session, session->userauth_list_data);
+            session->userauth_list_data = NULL;
+            session->state |= LIBSSH2_STATE_AUTHENTICATED;
+            session->userauth_list_state = libssh2_NB_state_idle;
+            return NULL;
+        }
+
+        if(session->userauth_list_data_len < 5) {
+            LIBSSH2_FREE(session, session->userauth_list_data);
+            session->userauth_list_data = NULL;
+            _libssh2_error(session, LIBSSH2_ERROR_PROTO,
+                           "Unexpected packet size");
+            return NULL;
+        }
+
+        methods_len = _libssh2_ntohu32(session->userauth_list_data + 1);
+        if(methods_len >= session->userauth_list_data_len - 5) {
+            _libssh2_error(session, LIBSSH2_ERROR_OUT_OF_BOUNDARY,
+                           "Unexpected userauth list size");
+            return NULL;
+        }
+
+        /* Do note that the memory areas overlap! */
+        memmove(session->userauth_list_data, session->userauth_list_data + 5,
+                methods_len);
+        session->userauth_list_data[methods_len] = '\0';
+        _libssh2_debug(session, LIBSSH2_TRACE_AUTH,
+                       "Permitted auth methods: %s",
+                       session->userauth_list_data);
+    }
+
+    session->userauth_list_state = libssh2_NB_state_idle;
+    return (char *) session->userauth_list_data;
+}
+
+/* libssh2_userauth_list
+ *
+ * List authentication methods
+ * Will yield successful login if "none" happens to be allowable for this user
+ * Not a common configuration for any SSH server though
+ * username should be NULL, or a null terminated string
+ */
+LIBSSH2_API char *
+libssh2_userauth_list(LIBSSH2_SESSION * session, const char *user,
+                      unsigned int user_len)
+{
+    char *ptr;
+    BLOCK_ADJUST_ERRNO(ptr, session,
+                       userauth_list(session, user, user_len));
+    return ptr;
+}
+
+/*
+ * libssh2_userauth_authenticated
+ *
+ * Returns: 0 if not yet authenticated
+ *          1 if already authenticated
+ */
+LIBSSH2_API int
+libssh2_userauth_authenticated(LIBSSH2_SESSION * session)
+{
+    return (session->state & LIBSSH2_STATE_AUTHENTICATED)?1:0;
+}
+
+
+
+/* userauth_password
+ * Plain ol' login
+ */
+static int
+userauth_password(LIBSSH2_SESSION *session,
+                  const char *username, unsigned int username_len,
+                  const unsigned char *password, unsigned int password_len,
+                  LIBSSH2_PASSWD_CHANGEREQ_FUNC((*passwd_change_cb)))
+{
+    unsigned char *s;
+    static const unsigned char reply_codes[4] =
+        { SSH_MSG_USERAUTH_SUCCESS, SSH_MSG_USERAUTH_FAILURE,
+          SSH_MSG_USERAUTH_PASSWD_CHANGEREQ, 0
+        };
+    int rc;
+
+    if(session->userauth_pswd_state == libssh2_NB_state_idle) {
+        /* Zero the whole thing out */
+        memset(&session->userauth_pswd_packet_requirev_state, 0,
+               sizeof(session->userauth_pswd_packet_requirev_state));
+
+        /*
+         * 40 = packet_type(1) + username_len(4) + service_len(4) +
+         * service(14)"ssh-connection" + method_len(4) + method(8)"password" +
+         * chgpwdbool(1) + password_len(4) */
+        session->userauth_pswd_data_len = username_len + 40;
+
+        session->userauth_pswd_data0 =
+            (unsigned char) ~SSH_MSG_USERAUTH_PASSWD_CHANGEREQ;
+
+        /* TODO: remove this alloc with a fixed buffer in the session
+           struct */
+        s = session->userauth_pswd_data =
+            LIBSSH2_ALLOC(session, session->userauth_pswd_data_len);
+        if(!session->userauth_pswd_data) {
+            return _libssh2_error(session, LIBSSH2_ERROR_ALLOC,
+                                  "Unable to allocate memory for "
+                                  "userauth-password request");
+        }
+
+        *(s++) = SSH_MSG_USERAUTH_REQUEST;
+        _libssh2_store_str(&s, username, username_len);
+        _libssh2_store_str(&s, "ssh-connection", sizeof("ssh-connection") - 1);
+        _libssh2_store_str(&s, "password", sizeof("password") - 1);
+        *s++ = '\0';
+        _libssh2_store_u32(&s, password_len);
+        /* 'password' is sent separately */
+
+        _libssh2_debug(session, LIBSSH2_TRACE_AUTH,
+                       "Attempting to login using password authentication");
+
+        session->userauth_pswd_state = libssh2_NB_state_created;
+    }
+
+    if(session->userauth_pswd_state == libssh2_NB_state_created) {
+        rc = _libssh2_transport_send(session, session->userauth_pswd_data,
+                                     session->userauth_pswd_data_len,
+                                     password, password_len);
+        if(rc == LIBSSH2_ERROR_EAGAIN) {
+            return _libssh2_error(session, LIBSSH2_ERROR_EAGAIN,
+                                  "Would block writing password request");
+        }
+
+        /* now free the sent packet */
+        LIBSSH2_FREE(session, session->userauth_pswd_data);
+        session->userauth_pswd_data = NULL;
+
+        if(rc) {
+            session->userauth_pswd_state = libssh2_NB_state_idle;
+            return _libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND,
+                                  "Unable to send userauth-password request");
+        }
+
+        session->userauth_pswd_state = libssh2_NB_state_sent;
+    }
+
+  password_response:
+
+    if((session->userauth_pswd_state == libssh2_NB_state_sent)
+        || (session->userauth_pswd_state == libssh2_NB_state_sent1)
+        || (session->userauth_pswd_state == libssh2_NB_state_sent2)) {
+        if(session->userauth_pswd_state == libssh2_NB_state_sent) {
+            rc = _libssh2_packet_requirev(session, reply_codes,
+                                          &session->userauth_pswd_data,
+                                          &session->userauth_pswd_data_len,
+                                          0, NULL, 0,
+                                          &session->
+                                          userauth_pswd_packet_requirev_state);
+
+            if(rc) {
+                if(rc != LIBSSH2_ERROR_EAGAIN)
+                    session->userauth_pswd_state = libssh2_NB_state_idle;
+
+                return _libssh2_error(session, rc,
+                                      "Waiting for password response");
+            }
+            else if(session->userauth_pswd_data_len < 1) {
+                session->userauth_pswd_state = libssh2_NB_state_idle;
+                return _libssh2_error(session, LIBSSH2_ERROR_PROTO,
+                                      "Unexpected packet size");
+            }
+
+            if(session->userauth_pswd_data[0] == SSH_MSG_USERAUTH_SUCCESS) {
+                _libssh2_debug(session, LIBSSH2_TRACE_AUTH,
+                               "Password authentication successful");
+                LIBSSH2_FREE(session, session->userauth_pswd_data);
+                session->userauth_pswd_data = NULL;
+                session->state |= LIBSSH2_STATE_AUTHENTICATED;
+                session->userauth_pswd_state = libssh2_NB_state_idle;
+                return 0;
+            }
+            else if(session->userauth_pswd_data[0] ==
+                    SSH_MSG_USERAUTH_FAILURE) {
+                _libssh2_debug(session, LIBSSH2_TRACE_AUTH,
+                               "Password authentication failed");
+                LIBSSH2_FREE(session, session->userauth_pswd_data);
+                session->userauth_pswd_data = NULL;
+                session->userauth_pswd_state = libssh2_NB_state_idle;
+                return _libssh2_error(session,
+                                      LIBSSH2_ERROR_AUTHENTICATION_FAILED,
+                                      "Authentication failed "
+                                      "(username/password)");
+            }
+
+            session->userauth_pswd_newpw = NULL;
+            session->userauth_pswd_newpw_len = 0;
+
+            session->userauth_pswd_state = libssh2_NB_state_sent1;
+        }
+
+        if(session->userauth_pswd_data_len < 1) {
+            session->userauth_pswd_state = libssh2_NB_state_idle;
+            return _libssh2_error(session, LIBSSH2_ERROR_PROTO,
+                                  "Unexpected packet size");
+        }
+
+        if((session->userauth_pswd_data[0] ==
+             SSH_MSG_USERAUTH_PASSWD_CHANGEREQ)
+            || (session->userauth_pswd_data0 ==
+                SSH_MSG_USERAUTH_PASSWD_CHANGEREQ)) {
+            session->userauth_pswd_data0 = SSH_MSG_USERAUTH_PASSWD_CHANGEREQ;
+
+            if((session->userauth_pswd_state == libssh2_NB_state_sent1) ||
+                (session->userauth_pswd_state == libssh2_NB_state_sent2)) {
+                if(session->userauth_pswd_state == libssh2_NB_state_sent1) {
+                    _libssh2_debug(session, LIBSSH2_TRACE_AUTH,
+                                   "Password change required");
+                    LIBSSH2_FREE(session, session->userauth_pswd_data);
+                    session->userauth_pswd_data = NULL;
+                }
+                if(passwd_change_cb) {
+                    if(session->userauth_pswd_state ==
+                       libssh2_NB_state_sent1) {
+                        passwd_change_cb(session,
+                                         &session->userauth_pswd_newpw,
+                                         &session->userauth_pswd_newpw_len,
+                                         &session->abstract);
+                        if(!session->userauth_pswd_newpw) {
+                            return _libssh2_error(session,
+                                                LIBSSH2_ERROR_PASSWORD_EXPIRED,
+                                                  "Password expired, and "
+                                                  "callback failed");
+                        }
+
+                        /* basic data_len + newpw_len(4) */
+                        if(username_len + password_len + 44 <= UINT_MAX) {
+                            session->userauth_pswd_data_len =
+                                username_len + password_len + 44;
+                            s = session->userauth_pswd_data =
+                                LIBSSH2_ALLOC(session,
+                                              session->userauth_pswd_data_len);
+                        }
+                        else {
+                            s = session->userauth_pswd_data = NULL;
+                            session->userauth_pswd_data_len = 0;
+                        }
+
+                        if(!session->userauth_pswd_data) {
+                            LIBSSH2_FREE(session,
+                                         session->userauth_pswd_newpw);
+                            session->userauth_pswd_newpw = NULL;
+                            return _libssh2_error(session, LIBSSH2_ERROR_ALLOC,
+                                                  "Unable to allocate memory "
+                                                  "for userauth password "
+                                                  "change request");
+                        }
+
+                        *(s++) = SSH_MSG_USERAUTH_REQUEST;
+                        _libssh2_store_str(&s, username, username_len);
+                        _libssh2_store_str(&s, "ssh-connection",
+                                           sizeof("ssh-connection") - 1);
+                        _libssh2_store_str(&s, "password",
+                                           sizeof("password") - 1);
+                        *s++ = 0x01;
+                        _libssh2_store_str(&s, (char *)password, password_len);
+                        _libssh2_store_u32(&s,
+                                           session->userauth_pswd_newpw_len);
+                        /* send session->userauth_pswd_newpw separately */
+
+                        session->userauth_pswd_state = libssh2_NB_state_sent2;
+                    }
+
+                    if(session->userauth_pswd_state ==
+                       libssh2_NB_state_sent2) {
+                        rc = _libssh2_transport_send(session,
+                                            session->userauth_pswd_data,
+                                            session->userauth_pswd_data_len,
+                                            (unsigned char *)
+                                            session->userauth_pswd_newpw,
+                                            session->userauth_pswd_newpw_len);
+                        if(rc == LIBSSH2_ERROR_EAGAIN) {
+                            return _libssh2_error(session,
+                                                  LIBSSH2_ERROR_EAGAIN,
+                                                  "Would block waiting");
+                        }
+
+                        /* free the allocated packets again */
+                        LIBSSH2_FREE(session, session->userauth_pswd_data);
+                        session->userauth_pswd_data = NULL;
+                        LIBSSH2_FREE(session, session->userauth_pswd_newpw);
+                        session->userauth_pswd_newpw = NULL;
+
+                        if(rc) {
+                            return _libssh2_error(session,
+                                                  LIBSSH2_ERROR_SOCKET_SEND,
+                                                  "Unable to send userauth "
+                                                  "password-change request");
+                        }
+
+                        /*
+                         * Ugliest use of goto ever.  Blame it on the
+                         * askN => requirev migration.
+                         */
+                        session->userauth_pswd_state = libssh2_NB_state_sent;
+                        goto password_response;
+                    }
+                }
+            }
+            else {
+                session->userauth_pswd_state = libssh2_NB_state_idle;
+                return _libssh2_error(session, LIBSSH2_ERROR_PASSWORD_EXPIRED,
+                                      "Password Expired, and no callback "
+                                      "specified");
+            }
+        }
+    }
+
+    /* FAILURE */
+    LIBSSH2_FREE(session, session->userauth_pswd_data);
+    session->userauth_pswd_data = NULL;
+    session->userauth_pswd_state = libssh2_NB_state_idle;
+
+    return _libssh2_error(session, LIBSSH2_ERROR_AUTHENTICATION_FAILED,
+                          "Authentication failed");
+}
+
+/*
+ * libssh2_userauth_password_ex
+ *
+ * Plain ol' login
+ */
+
+LIBSSH2_API int
+libssh2_userauth_password_ex(LIBSSH2_SESSION *session, const char *username,
+                             unsigned int username_len, const char *password,
+                             unsigned int password_len,
+                             LIBSSH2_PASSWD_CHANGEREQ_FUNC
+                             ((*passwd_change_cb)))
+{
+    int rc;
+    BLOCK_ADJUST(rc, session,
+                 userauth_password(session, username, username_len,
+                                   (unsigned char *)password, password_len,
+                                   passwd_change_cb));
+    return rc;
+}
+
+static int
+memory_read_publickey(LIBSSH2_SESSION * session, unsigned char **method,
+                      size_t *method_len,
+                      unsigned char **pubkeydata,
+                      size_t *pubkeydata_len,
+                      const char *pubkeyfiledata,
+                      size_t pubkeyfiledata_len)
+{
+    unsigned char *pubkey = NULL, *sp1, *sp2, *tmp;
+    size_t pubkey_len = pubkeyfiledata_len;
+    unsigned int tmp_len;
+
+    if(pubkeyfiledata_len <= 1) {
+        return _libssh2_error(session, LIBSSH2_ERROR_FILE,
+                              "Invalid data in public key file");
+    }
+
+    pubkey = LIBSSH2_ALLOC(session, pubkeyfiledata_len);
+    if(!pubkey) {
+        return _libssh2_error(session, LIBSSH2_ERROR_ALLOC,
+                              "Unable to allocate memory for public key data");
+    }
+
+    memcpy(pubkey, pubkeyfiledata, pubkeyfiledata_len);
+
+    /*
+     *   Remove trailing whitespace
+     */
+    while(pubkey_len && isspace(pubkey[pubkey_len - 1]))
+        pubkey_len--;
+
+    if(!pubkey_len) {
+        LIBSSH2_FREE(session, pubkey);
+        return _libssh2_error(session, LIBSSH2_ERROR_FILE,
+                              "Missing public key data");
+    }
+
+    sp1 = memchr(pubkey, ' ', pubkey_len);
+    if(sp1 == NULL) {
+        LIBSSH2_FREE(session, pubkey);
+        return _libssh2_error(session, LIBSSH2_ERROR_FILE,
+                              "Invalid public key data");
+    }
+
+    sp1++;
+
+    sp2 = memchr(sp1, ' ', pubkey_len - (sp1 - pubkey));
+    if(sp2 == NULL) {
+        /* Assume that the id string is missing, but that it's okay */
+        sp2 = pubkey + pubkey_len;
+    }
+
+    if(libssh2_base64_decode(session, (char **) &tmp, &tmp_len,
+                              (char *) sp1, sp2 - sp1)) {
+        LIBSSH2_FREE(session, pubkey);
+        return _libssh2_error(session, LIBSSH2_ERROR_FILE,
+                                  "Invalid key data, not base64 encoded");
+    }
+
+    /* Wasting some bytes here (okay, more than some), but since it's likely
+     * to be freed soon anyway, we'll just avoid the extra free/alloc and call
+     * it a wash
+     */
+    *method = pubkey;
+    *method_len = sp1 - pubkey - 1;
+
+    *pubkeydata = tmp;
+    *pubkeydata_len = tmp_len;
+
+    return 0;
+}
+
+/*
+ * file_read_publickey
+ *
+ * Read a public key from an id_???.pub style file
+ *
+ * Returns an allocated string containing the decoded key in *pubkeydata
+ * on success.
+ * Returns an allocated string containing the key method (e.g. "ssh-dss")
+ * in method on success.
+ */
+static int
+file_read_publickey(LIBSSH2_SESSION * session, unsigned char **method,
+                    size_t *method_len,
+                    unsigned char **pubkeydata,
+                    size_t *pubkeydata_len,
+                    const char *pubkeyfile)
+{
+    FILE *fd;
+    char c;
+    unsigned char *pubkey = NULL, *sp1, *sp2, *tmp;
+    size_t pubkey_len = 0, sp_len;
+    unsigned int tmp_len;
+
+    _libssh2_debug(session, LIBSSH2_TRACE_AUTH, "Loading public key file: %s",
+                   pubkeyfile);
+    /* Read Public Key */
+    fd = fopen(pubkeyfile, FOPEN_READTEXT);
+    if(!fd) {
+        return _libssh2_error(session, LIBSSH2_ERROR_FILE,
+                              "Unable to open public key file");
+    }
+    while(!feof(fd) && 1 == fread(&c, 1, 1, fd) && c != '\r' && c != '\n') {
+        pubkey_len++;
+    }
+    rewind(fd);
+
+    if(pubkey_len <= 1) {
+        fclose(fd);
+        return _libssh2_error(session, LIBSSH2_ERROR_FILE,
+                              "Invalid data in public key file");
+    }
+
+    pubkey = LIBSSH2_ALLOC(session, pubkey_len);
+    if(!pubkey) {
+        fclose(fd);
+        return _libssh2_error(session, LIBSSH2_ERROR_ALLOC,
+                              "Unable to allocate memory for public key data");
+    }
+    if(fread(pubkey, 1, pubkey_len, fd) != pubkey_len) {
+        LIBSSH2_FREE(session, pubkey);
+        fclose(fd);
+        return _libssh2_error(session, LIBSSH2_ERROR_FILE,
+                              "Unable to read public key from file");
+    }
+    fclose(fd);
+    /*
+     * Remove trailing whitespace
+     */
+    while(pubkey_len && isspace(pubkey[pubkey_len - 1])) {
+        pubkey_len--;
+    }
+
+    if(!pubkey_len) {
+        LIBSSH2_FREE(session, pubkey);
+        return _libssh2_error(session, LIBSSH2_ERROR_FILE,
+                              "Missing public key data");
+    }
+
+    sp1 = memchr(pubkey, ' ', pubkey_len);
+    if(sp1 == NULL) {
+        LIBSSH2_FREE(session, pubkey);
+        return _libssh2_error(session, LIBSSH2_ERROR_FILE,
+                              "Invalid public key data");
+    }
+
+    sp1++;
+
+    sp_len = sp1 > pubkey ? (sp1 - pubkey) - 1 : 0;
+    sp2 = memchr(sp1, ' ', pubkey_len - sp_len);
+    if(sp2 == NULL) {
+        /* Assume that the id string is missing, but that it's okay */
+        sp2 = pubkey + pubkey_len;
+    }
+
+    if(libssh2_base64_decode(session, (char **) &tmp, &tmp_len,
+                              (char *) sp1, sp2 - sp1)) {
+        LIBSSH2_FREE(session, pubkey);
+        return _libssh2_error(session, LIBSSH2_ERROR_FILE,
+                              "Invalid key data, not base64 encoded");
+    }
+
+    /* Wasting some bytes here (okay, more than some), but since it's likely
+     * to be freed soon anyway, we'll just avoid the extra free/alloc and call
+     * it a wash */
+    *method = pubkey;
+    *method_len = sp1 - pubkey - 1;
+
+    *pubkeydata = tmp;
+    *pubkeydata_len = tmp_len;
+
+    return 0;
+}
+
+static int
+memory_read_privatekey(LIBSSH2_SESSION * session,
+                       const LIBSSH2_HOSTKEY_METHOD ** hostkey_method,
+                       void **hostkey_abstract,
+                       const unsigned char *method, int method_len,
+                       const char *privkeyfiledata, size_t privkeyfiledata_len,
+                       const char *passphrase)
+{
+    const LIBSSH2_HOSTKEY_METHOD **hostkey_methods_avail =
+        libssh2_hostkey_methods();
+
+    *hostkey_method = NULL;
+    *hostkey_abstract = NULL;
+    while(*hostkey_methods_avail && (*hostkey_methods_avail)->name) {
+        if((*hostkey_methods_avail)->initPEMFromMemory
+             && strncmp((*hostkey_methods_avail)->name, (const char *) method,
+                        method_len) == 0) {
+            *hostkey_method = *hostkey_methods_avail;
+            break;
+        }
+        hostkey_methods_avail++;
+    }
+    if(!*hostkey_method) {
+        return _libssh2_error(session, LIBSSH2_ERROR_METHOD_NONE,
+                              "No handler for specified private key");
+    }
+
+    if((*hostkey_method)->
+        initPEMFromMemory(session, privkeyfiledata, privkeyfiledata_len,
+                          (unsigned char *) passphrase,
+                          hostkey_abstract)) {
+        return _libssh2_error(session, LIBSSH2_ERROR_FILE,
+                              "Unable to initialize private key from file");
+    }
+
+    return 0;
+}
+
+/* libssh2_file_read_privatekey
+ * Read a PEM encoded private key from an id_??? style file
+ */
+static int
+file_read_privatekey(LIBSSH2_SESSION * session,
+                     const LIBSSH2_HOSTKEY_METHOD ** hostkey_method,
+                     void **hostkey_abstract,
+                     const unsigned char *method, int method_len,
+                     const char *privkeyfile, const char *passphrase)
+{
+    const LIBSSH2_HOSTKEY_METHOD **hostkey_methods_avail =
+        libssh2_hostkey_methods();
+
+    _libssh2_debug(session, LIBSSH2_TRACE_AUTH, "Loading private key file: %s",
+                   privkeyfile);
+    *hostkey_method = NULL;
+    *hostkey_abstract = NULL;
+    while(*hostkey_methods_avail && (*hostkey_methods_avail)->name) {
+        if((*hostkey_methods_avail)->initPEM
+            && strncmp((*hostkey_methods_avail)->name, (const char *) method,
+                       method_len) == 0) {
+            *hostkey_method = *hostkey_methods_avail;
+            break;
+        }
+        hostkey_methods_avail++;
+    }
+    if(!*hostkey_method) {
+        return _libssh2_error(session, LIBSSH2_ERROR_METHOD_NONE,
+                              "No handler for specified private key");
+    }
+
+    if((*hostkey_method)->
+        initPEM(session, privkeyfile, (unsigned char *) passphrase,
+                hostkey_abstract)) {
+        return _libssh2_error(session, LIBSSH2_ERROR_FILE,
+                              "Unable to initialize private key from file");
+    }
+
+    return 0;
+}
+
+struct privkey_file {
+    const char *filename;
+    const char *passphrase;
+};
+
+static int
+sign_frommemory(LIBSSH2_SESSION *session, unsigned char **sig, size_t *sig_len,
+                const unsigned char *data, size_t data_len, void **abstract)
+{
+    struct privkey_file *pk_file = (struct privkey_file *) (*abstract);
+    const LIBSSH2_HOSTKEY_METHOD *privkeyobj;
+    void *hostkey_abstract;
+    struct iovec datavec;
+    int rc;
+
+    rc = memory_read_privatekey(session, &privkeyobj, &hostkey_abstract,
+                                session->userauth_pblc_method,
+                                session->userauth_pblc_method_len,
+                                pk_file->filename,
+                                strlen(pk_file->filename),
+                                pk_file->passphrase);
+    if(rc)
+        return rc;
+
+    libssh2_prepare_iovec(&datavec, 1);
+    datavec.iov_base = (void *)data;
+    datavec.iov_len  = data_len;
+
+    if(privkeyobj->signv(session, sig, sig_len, 1, &datavec,
+                          &hostkey_abstract)) {
+        if(privkeyobj->dtor) {
+            privkeyobj->dtor(session, &hostkey_abstract);
+        }
+        return -1;
+    }
+
+    if(privkeyobj->dtor) {
+        privkeyobj->dtor(session, &hostkey_abstract);
+    }
+    return 0;
+}
+
+static int
+sign_fromfile(LIBSSH2_SESSION *session, unsigned char **sig, size_t *sig_len,
+              const unsigned char *data, size_t data_len, void **abstract)
+{
+    struct privkey_file *privkey_file = (struct privkey_file *) (*abstract);
+    const LIBSSH2_HOSTKEY_METHOD *privkeyobj;
+    void *hostkey_abstract;
+    struct iovec datavec;
+    int rc;
+
+    rc = file_read_privatekey(session, &privkeyobj, &hostkey_abstract,
+                              session->userauth_pblc_method,
+                              session->userauth_pblc_method_len,
+                              privkey_file->filename,
+                              privkey_file->passphrase);
+    if(rc)
+        return rc;
+
+    libssh2_prepare_iovec(&datavec, 1);
+    datavec.iov_base = (void *)data;
+    datavec.iov_len  = data_len;
+
+    if(privkeyobj->signv(session, sig, sig_len, 1, &datavec,
+                          &hostkey_abstract)) {
+        if(privkeyobj->dtor) {
+            privkeyobj->dtor(session, &hostkey_abstract);
+        }
+        return -1;
+    }
+
+    if(privkeyobj->dtor) {
+        privkeyobj->dtor(session, &hostkey_abstract);
+    }
+    return 0;
+}
+
+
+
+/* userauth_hostbased_fromfile
+ * Authenticate using a keypair found in the named files
+ */
+static int
+userauth_hostbased_fromfile(LIBSSH2_SESSION *session,
+                            const char *username, size_t username_len,
+                            const char *publickey, const char *privatekey,
+                            const char *passphrase, const char *hostname,
+                            size_t hostname_len,
+                            const char *local_username,
+                            size_t local_username_len)
+{
+    int rc;
+
+#if !LIBSSH2_RSA
+    return _libssh2_error(session, LIBSSH2_ERROR_METHOD_NOT_SUPPORTED,
+                          "RSA is not supported by crypto backend");
+#endif
+
+    if(session->userauth_host_state == libssh2_NB_state_idle) {
+        const LIBSSH2_HOSTKEY_METHOD *privkeyobj;
+        unsigned char *pubkeydata = NULL;
+        unsigned char *sig = NULL;
+        size_t pubkeydata_len = 0;
+        size_t sig_len = 0;
+        void *abstract;
+        unsigned char buf[5];
+        struct iovec datavec[4];
+
+        /* Zero the whole thing out */
+        memset(&session->userauth_host_packet_requirev_state, 0,
+               sizeof(session->userauth_host_packet_requirev_state));
+
+        if(publickey) {
+            rc = file_read_publickey(session, &session->userauth_host_method,
+                                     &session->userauth_host_method_len,
+                                     &pubkeydata, &pubkeydata_len, publickey);
+            if(rc)
+                /* Note: file_read_publickey() calls _libssh2_error() */
+                return rc;
+        }
+        else {
+            /* Compute public key from private key. */
+            rc = _libssh2_pub_priv_keyfile(session,
+                                           &session->userauth_host_method,
+                                           &session->userauth_host_method_len,
+                                           &pubkeydata, &pubkeydata_len,
+                                           privatekey, passphrase);
+            if(rc)
+                /* libssh2_pub_priv_keyfile calls _libssh2_error() */
+                return rc;
+        }
+
+        /*
+         * 52 = packet_type(1) + username_len(4) + servicename_len(4) +
+         * service_name(14)"ssh-connection" + authmethod_len(4) +
+         * authmethod(9)"hostbased" + method_len(4) + pubkeydata_len(4) +
+         * hostname_len(4) + local_username_len(4)
+         */
+        session->userauth_host_packet_len =
+            username_len + session->userauth_host_method_len + hostname_len +
+            local_username_len + pubkeydata_len + 52;
+
+        /*
+         * Preallocate space for an overall length,  method name again,
+         * and the signature, which won't be any larger than the size of
+         * the publickeydata itself
+         */
+        session->userauth_host_s = session->userauth_host_packet =
+            LIBSSH2_ALLOC(session,
+                          session->userauth_host_packet_len + 4 +
+                          (4 + session->userauth_host_method_len) +
+                          (4 + pubkeydata_len));
+        if(!session->userauth_host_packet) {
+            LIBSSH2_FREE(session, session->userauth_host_method);
+            session->userauth_host_method = NULL;
+            LIBSSH2_FREE(session, pubkeydata);
+            return _libssh2_error(session, LIBSSH2_ERROR_ALLOC,
+                                  "Out of memory");
+        }
+
+        *(session->userauth_host_s++) = SSH_MSG_USERAUTH_REQUEST;
+        _libssh2_store_str(&session->userauth_host_s, username, username_len);
+        _libssh2_store_str(&session->userauth_host_s, "ssh-connection", 14);
+        _libssh2_store_str(&session->userauth_host_s, "hostbased", 9);
+        _libssh2_store_str(&session->userauth_host_s,
+                           (const char *)session->userauth_host_method,
+                           session->userauth_host_method_len);
+        _libssh2_store_str(&session->userauth_host_s, (const char *)pubkeydata,
+                           pubkeydata_len);
+        LIBSSH2_FREE(session, pubkeydata);
+        _libssh2_store_str(&session->userauth_host_s, hostname, hostname_len);
+        _libssh2_store_str(&session->userauth_host_s, local_username,
+                           local_username_len);
+
+        rc = file_read_privatekey(session, &privkeyobj, &abstract,
+                                  session->userauth_host_method,
+                                  session->userauth_host_method_len,
+                                  privatekey, passphrase);
+        if(rc) {
+            /* Note: file_read_privatekey() calls _libssh2_error() */
+            LIBSSH2_FREE(session, session->userauth_host_method);
+            session->userauth_host_method = NULL;
+            LIBSSH2_FREE(session, session->userauth_host_packet);
+            session->userauth_host_packet = NULL;
+            return rc;
+        }
+
+        _libssh2_htonu32(buf, session->session_id_len);
+        libssh2_prepare_iovec(datavec, 4);
+        datavec[0].iov_base = (void *)buf;
+        datavec[0].iov_len = 4;
+        datavec[1].iov_base = (void *)session->session_id;
+        datavec[1].iov_len = session->session_id_len;
+        datavec[2].iov_base = (void *)session->userauth_host_packet;
+        datavec[2].iov_len = session->userauth_host_packet_len;
+
+        if(privkeyobj && privkeyobj->signv &&
+                          privkeyobj->signv(session, &sig, &sig_len, 3,
+                                            datavec, &abstract)) {
+            LIBSSH2_FREE(session, session->userauth_host_method);
+            session->userauth_host_method = NULL;
+            LIBSSH2_FREE(session, session->userauth_host_packet);
+            session->userauth_host_packet = NULL;
+            if(privkeyobj->dtor) {
+                privkeyobj->dtor(session, &abstract);
+            }
+            return -1;
+        }
+
+        if(privkeyobj && privkeyobj->dtor) {
+            privkeyobj->dtor(session, &abstract);
+        }
+
+        if(sig_len > pubkeydata_len) {
+            unsigned char *newpacket;
+            /* Should *NEVER* happen, but...well.. better safe than sorry */
+            newpacket = LIBSSH2_REALLOC(session, session->userauth_host_packet,
+                                        session->userauth_host_packet_len + 4 +
+                                        (4 + session->userauth_host_method_len)
+                                        + (4 + sig_len)); /* PK sigblob */
+            if(!newpacket) {
+                LIBSSH2_FREE(session, sig);
+                LIBSSH2_FREE(session, session->userauth_host_packet);
+                session->userauth_host_packet = NULL;
+                LIBSSH2_FREE(session, session->userauth_host_method);
+                session->userauth_host_method = NULL;
+                return _libssh2_error(session, LIBSSH2_ERROR_ALLOC,
+                                      "Failed allocating additional space for "
+                                      "userauth-hostbased packet");
+            }
+            session->userauth_host_packet = newpacket;
+        }
+
+        session->userauth_host_s =
+            session->userauth_host_packet + session->userauth_host_packet_len;
+
+        _libssh2_store_u32(&session->userauth_host_s,
+                           4 + session->userauth_host_method_len +
+                           4 + sig_len);
+        _libssh2_store_str(&session->userauth_host_s,
+                           (const char *)session->userauth_host_method,
+                           session->userauth_host_method_len);
+        LIBSSH2_FREE(session, session->userauth_host_method);
+        session->userauth_host_method = NULL;
+
+        _libssh2_store_str(&session->userauth_host_s, (const char *)sig,
+                           sig_len);
+        LIBSSH2_FREE(session, sig);
+
+        _libssh2_debug(session, LIBSSH2_TRACE_AUTH,
+                       "Attempting hostbased authentication");
+
+        session->userauth_host_state = libssh2_NB_state_created;
+    }
+
+    if(session->userauth_host_state == libssh2_NB_state_created) {
+        rc = _libssh2_transport_send(session, session->userauth_host_packet,
+                                     session->userauth_host_s -
+                                     session->userauth_host_packet,
+                                     NULL, 0);
+        if(rc == LIBSSH2_ERROR_EAGAIN) {
+            return _libssh2_error(session, LIBSSH2_ERROR_EAGAIN,
+                                  "Would block");
+        }
+        else if(rc) {
+            LIBSSH2_FREE(session, session->userauth_host_packet);
+            session->userauth_host_packet = NULL;
+            session->userauth_host_state = libssh2_NB_state_idle;
+            return _libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND,
+                                  "Unable to send userauth-hostbased request");
+        }
+        LIBSSH2_FREE(session, session->userauth_host_packet);
+        session->userauth_host_packet = NULL;
+
+        session->userauth_host_state = libssh2_NB_state_sent;
+    }
+
+    if(session->userauth_host_state == libssh2_NB_state_sent) {
+        static const unsigned char reply_codes[3] =
+            { SSH_MSG_USERAUTH_SUCCESS, SSH_MSG_USERAUTH_FAILURE, 0 };
+        size_t data_len;
+        rc = _libssh2_packet_requirev(session, reply_codes,
+                                      &session->userauth_host_data,
+                                      &data_len, 0, NULL, 0,
+                                      &session->
+                                      userauth_host_packet_requirev_state);
+        if(rc == LIBSSH2_ERROR_EAGAIN) {
+            return _libssh2_error(session, LIBSSH2_ERROR_EAGAIN,
+                                  "Would block");
+        }
+
+        session->userauth_host_state = libssh2_NB_state_idle;
+        if(rc || data_len < 1) {
+            return _libssh2_error(session, LIBSSH2_ERROR_PUBLICKEY_UNVERIFIED,
+                                  "Auth failed");
+        }
+
+        if(session->userauth_host_data[0] == SSH_MSG_USERAUTH_SUCCESS) {
+            _libssh2_debug(session, LIBSSH2_TRACE_AUTH,
+                           "Hostbased authentication successful");
+            /* We are us and we've proved it. */
+            LIBSSH2_FREE(session, session->userauth_host_data);
+            session->userauth_host_data = NULL;
+            session->state |= LIBSSH2_STATE_AUTHENTICATED;
+            return 0;
+        }
+    }
+
+    /* This public key is not allowed for this user on this server */
+    LIBSSH2_FREE(session, session->userauth_host_data);
+    session->userauth_host_data = NULL;
+    return _libssh2_error(session, LIBSSH2_ERROR_PUBLICKEY_UNVERIFIED,
+                          "Invalid signature for supplied public key, or bad "
+                          "username/public key combination");
+}
+
+/* libssh2_userauth_hostbased_fromfile_ex
+ * Authenticate using a keypair found in the named files
+ */
+LIBSSH2_API int
+libssh2_userauth_hostbased_fromfile_ex(LIBSSH2_SESSION *session,
+                                       const char *user,
+                                       unsigned int user_len,
+                                       const char *publickey,
+                                       const char *privatekey,
+                                       const char *passphrase,
+                                       const char *host,
+                                       unsigned int host_len,
+                                       const char *localuser,
+                                       unsigned int localuser_len)
+{
+    int rc;
+    BLOCK_ADJUST(rc, session,
+                 userauth_hostbased_fromfile(session, user, user_len,
+                                             publickey, privatekey,
+                                             passphrase, host, host_len,
+                                             localuser, localuser_len));
+    return rc;
+}
+
+
+
+int
+_libssh2_userauth_publickey(LIBSSH2_SESSION *session,
+                            const char *username,
+                            unsigned int username_len,
+                            const unsigned char *pubkeydata,
+                            unsigned long pubkeydata_len,
+                            LIBSSH2_USERAUTH_PUBLICKEY_SIGN_FUNC
+                            ((*sign_callback)),
+                            void *abstract)
+{
+    unsigned char reply_codes[4] =
+        { SSH_MSG_USERAUTH_SUCCESS, SSH_MSG_USERAUTH_FAILURE,
+          SSH_MSG_USERAUTH_PK_OK, 0
+        };
+    int rc;
+    unsigned char *s;
+
+    if(session->userauth_pblc_state == libssh2_NB_state_idle) {
+
+        /*
+         * The call to _libssh2_ntohu32 later relies on pubkeydata having at
+         * least 4 valid bytes containing the length of the method name.
+         */
+        if(pubkeydata_len < 4)
+            return _libssh2_error(session, LIBSSH2_ERROR_PUBLICKEY_UNVERIFIED,
+                                  "Invalid public key, too short");
+
+        /* Zero the whole thing out */
+        memset(&session->userauth_pblc_packet_requirev_state, 0,
+               sizeof(session->userauth_pblc_packet_requirev_state));
+
+        /*
+         * As an optimisation, userauth_publickey_fromfile reuses a
+         * previously allocated copy of the method name to avoid an extra
+         * allocation/free.
+         * For other uses, we allocate and populate it here.
+         */
+        if(!session->userauth_pblc_method) {
+            session->userauth_pblc_method_len = _libssh2_ntohu32(pubkeydata);
+
+            if(session->userauth_pblc_method_len > pubkeydata_len - 4)
+                /* the method length simply cannot be longer than the entire
+                   passed in data, so we use this to detect crazy input
+                   data */
+                return _libssh2_error(session,
+                                      LIBSSH2_ERROR_PUBLICKEY_UNVERIFIED,
+                                      "Invalid public key");
+
+            session->userauth_pblc_method =
+                LIBSSH2_ALLOC(session, session->userauth_pblc_method_len);
+            if(!session->userauth_pblc_method) {
+                return _libssh2_error(session, LIBSSH2_ERROR_ALLOC,
+                                      "Unable to allocate memory "
+                                      "for public key data");
+            }
+            memcpy(session->userauth_pblc_method, pubkeydata + 4,
+                   session->userauth_pblc_method_len);
+        }
+        /*
+         * The length of the method name read from plaintext prefix in the
+         * file must match length embedded in the key.
+         * TODO: The data should match too but we don't check that. Should we?
+         */
+        else if(session->userauth_pblc_method_len !=
+                 _libssh2_ntohu32(pubkeydata))
+            return _libssh2_error(session, LIBSSH2_ERROR_PUBLICKEY_UNVERIFIED,
+                                  "Invalid public key");
+
+        /*
+         * 45 = packet_type(1) + username_len(4) + servicename_len(4) +
+         * service_name(14)"ssh-connection" + authmethod_len(4) +
+         * authmethod(9)"publickey" + sig_included(1)'\0' + algmethod_len(4) +
+         * publickey_len(4)
+         */
+        session->userauth_pblc_packet_len =
+            username_len + session->userauth_pblc_method_len + pubkeydata_len +
+            45;
+
+        /*
+         * Preallocate space for an overall length, method name again, and the
+         * signature, which won't be any larger than the size of the
+         * publickeydata itself.
+         *
+         * Note that the 'pubkeydata_len' extra bytes allocated here will not
+         * be used in this first send, but will be used in the later one where
+         * this same allocation is re-used.
+         */
+        s = session->userauth_pblc_packet =
+            LIBSSH2_ALLOC(session,
+                          session->userauth_pblc_packet_len + 4 +
+                          (4 + session->userauth_pblc_method_len)
+                          + (4 + pubkeydata_len));
+        if(!session->userauth_pblc_packet) {
+            LIBSSH2_FREE(session, session->userauth_pblc_method);
+            session->userauth_pblc_method = NULL;
+            return _libssh2_error(session, LIBSSH2_ERROR_ALLOC,
+                                  "Out of memory");
+        }
+
+        *s++ = SSH_MSG_USERAUTH_REQUEST;
+        _libssh2_store_str(&s, username, username_len);
+        _libssh2_store_str(&s, "ssh-connection", 14);
+        _libssh2_store_str(&s, "publickey", 9);
+
+        session->userauth_pblc_b = s;
+        /* Not sending signature with *this* packet */
+        *s++ = 0;
+
+        _libssh2_store_str(&s, (const char *)session->userauth_pblc_method,
+                           session->userauth_pblc_method_len);
+        _libssh2_store_str(&s, (const char *)pubkeydata, pubkeydata_len);
+
+        _libssh2_debug(session, LIBSSH2_TRACE_AUTH,
+                       "Attempting publickey authentication");
+
+        session->userauth_pblc_state = libssh2_NB_state_created;
+    }
+
+    if(session->userauth_pblc_state == libssh2_NB_state_created) {
+        rc = _libssh2_transport_send(session, session->userauth_pblc_packet,
+                                     session->userauth_pblc_packet_len,
+                                     NULL, 0);
+        if(rc == LIBSSH2_ERROR_EAGAIN)
+            return _libssh2_error(session, LIBSSH2_ERROR_EAGAIN,
+                                  "Would block");
+        else if(rc) {
+            LIBSSH2_FREE(session, session->userauth_pblc_packet);
+            session->userauth_pblc_packet = NULL;
+            LIBSSH2_FREE(session, session->userauth_pblc_method);
+            session->userauth_pblc_method = NULL;
+            session->userauth_pblc_state = libssh2_NB_state_idle;
+            return _libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND,
+                                  "Unable to send userauth-publickey request");
+        }
+
+        session->userauth_pblc_state = libssh2_NB_state_sent;
+    }
+
+    if(session->userauth_pblc_state == libssh2_NB_state_sent) {
+        rc = _libssh2_packet_requirev(session, reply_codes,
+                                      &session->userauth_pblc_data,
+                                      &session->userauth_pblc_data_len, 0,
+                                      NULL, 0,
+                                      &session->
+                                      userauth_pblc_packet_requirev_state);
+        if(rc == LIBSSH2_ERROR_EAGAIN) {
+            return _libssh2_error(session, LIBSSH2_ERROR_EAGAIN,
+                                  "Would block");
+        }
+        else if(rc || (session->userauth_pblc_data_len < 1)) {
+            LIBSSH2_FREE(session, session->userauth_pblc_packet);
+            session->userauth_pblc_packet = NULL;
+            LIBSSH2_FREE(session, session->userauth_pblc_method);
+            session->userauth_pblc_method = NULL;
+            session->userauth_pblc_state = libssh2_NB_state_idle;
+            return _libssh2_error(session, LIBSSH2_ERROR_PUBLICKEY_UNVERIFIED,
+                                  "Waiting for USERAUTH response");
+        }
+
+        if(session->userauth_pblc_data[0] == SSH_MSG_USERAUTH_SUCCESS) {
+            _libssh2_debug(session, LIBSSH2_TRACE_AUTH,
+                           "Pubkey authentication prematurely successful");
+            /*
+             * God help any SSH server that allows an UNVERIFIED
+             * public key to validate the user
+             */
+            LIBSSH2_FREE(session, session->userauth_pblc_data);
+            session->userauth_pblc_data = NULL;
+            LIBSSH2_FREE(session, session->userauth_pblc_packet);
+            session->userauth_pblc_packet = NULL;
+            LIBSSH2_FREE(session, session->userauth_pblc_method);
+            session->userauth_pblc_method = NULL;
+            session->state |= LIBSSH2_STATE_AUTHENTICATED;
+            session->userauth_pblc_state = libssh2_NB_state_idle;
+            return 0;
+        }
+
+        if(session->userauth_pblc_data[0] == SSH_MSG_USERAUTH_FAILURE) {
+            /* This public key is not allowed for this user on this server */
+            LIBSSH2_FREE(session, session->userauth_pblc_data);
+            session->userauth_pblc_data = NULL;
+            LIBSSH2_FREE(session, session->userauth_pblc_packet);
+            session->userauth_pblc_packet = NULL;
+            LIBSSH2_FREE(session, session->userauth_pblc_method);
+            session->userauth_pblc_method = NULL;
+            session->userauth_pblc_state = libssh2_NB_state_idle;
+            return _libssh2_error(session, LIBSSH2_ERROR_AUTHENTICATION_FAILED,
+                                  "Username/PublicKey combination invalid");
+        }
+
+        /* Semi-Success! */
+        LIBSSH2_FREE(session, session->userauth_pblc_data);
+        session->userauth_pblc_data = NULL;
+
+        *session->userauth_pblc_b = 0x01;
+        session->userauth_pblc_state = libssh2_NB_state_sent1;
+    }
+
+    if(session->userauth_pblc_state == libssh2_NB_state_sent1) {
+        unsigned char *buf;
+        unsigned char *sig;
+        size_t sig_len;
+
+        s = buf = LIBSSH2_ALLOC(session, 4 + session->session_id_len
+                                + session->userauth_pblc_packet_len);
+        if(!buf) {
+            return _libssh2_error(session, LIBSSH2_ERROR_ALLOC,
+                                  "Unable to allocate memory for "
+                                  "userauth-publickey signed data");
+        }
+
+        _libssh2_store_str(&s, (const char *)session->session_id,
+                           session->session_id_len);
+
+        memcpy(s, session->userauth_pblc_packet,
+               session->userauth_pblc_packet_len);
+        s += session->userauth_pblc_packet_len;
+
+        rc = sign_callback(session, &sig, &sig_len, buf, s - buf, abstract);
+        LIBSSH2_FREE(session, buf);
+        if(rc == LIBSSH2_ERROR_EAGAIN) {
+            return _libssh2_error(session, LIBSSH2_ERROR_EAGAIN,
+                                  "Would block");
+        }
+        else if(rc) {
+            LIBSSH2_FREE(session, session->userauth_pblc_method);
+            session->userauth_pblc_method = NULL;
+            LIBSSH2_FREE(session, session->userauth_pblc_packet);
+            session->userauth_pblc_packet = NULL;
+            session->userauth_pblc_state = libssh2_NB_state_idle;
+            return _libssh2_error(session, LIBSSH2_ERROR_PUBLICKEY_UNVERIFIED,
+                                  "Callback returned error");
+        }
+
+        /*
+         * If this function was restarted, pubkeydata_len might still be 0
+         * which will cause an unnecessary but harmless realloc here.
+         */
+        if(sig_len > pubkeydata_len) {
+            unsigned char *newpacket;
+            /* Should *NEVER* happen, but...well.. better safe than sorry */
+            newpacket = LIBSSH2_REALLOC(session,
+                                        session->userauth_pblc_packet,
+                                        session->userauth_pblc_packet_len + 4 +
+                                        (4 + session->userauth_pblc_method_len)
+                                        + (4 + sig_len)); /* PK sigblob */
+            if(!newpacket) {
+                LIBSSH2_FREE(session, sig);
+                LIBSSH2_FREE(session, session->userauth_pblc_packet);
+                session->userauth_pblc_packet = NULL;
+                LIBSSH2_FREE(session, session->userauth_pblc_method);
+                session->userauth_pblc_method = NULL;
+                session->userauth_pblc_state = libssh2_NB_state_idle;
+                return _libssh2_error(session, LIBSSH2_ERROR_ALLOC,
+                                      "Failed allocating additional space for "
+                                      "userauth-publickey packet");
+            }
+            session->userauth_pblc_packet = newpacket;
+        }
+
+        s = session->userauth_pblc_packet + session->userauth_pblc_packet_len;
+        session->userauth_pblc_b = NULL;
+
+        _libssh2_store_u32(&s,
+                           4 + session->userauth_pblc_method_len + 4 +
+                           sig_len);
+        _libssh2_store_str(&s, (const char *)session->userauth_pblc_method,
+                           session->userauth_pblc_method_len);
+
+        LIBSSH2_FREE(session, session->userauth_pblc_method);
+        session->userauth_pblc_method = NULL;
+
+        _libssh2_store_str(&s, (const char *)sig, sig_len);
+        LIBSSH2_FREE(session, sig);
+
+        _libssh2_debug(session, LIBSSH2_TRACE_AUTH,
+                       "Attempting publickey authentication -- phase 2");
+
+        session->userauth_pblc_s = s;
+        session->userauth_pblc_state = libssh2_NB_state_sent2;
+    }
+
+    if(session->userauth_pblc_state == libssh2_NB_state_sent2) {
+        rc = _libssh2_transport_send(session, session->userauth_pblc_packet,
+                                     session->userauth_pblc_s -
+                                     session->userauth_pblc_packet,
+                                     NULL, 0);
+        if(rc == LIBSSH2_ERROR_EAGAIN) {
+            return _libssh2_error(session, LIBSSH2_ERROR_EAGAIN,
+                                  "Would block");
+        }
+        else if(rc) {
+            LIBSSH2_FREE(session, session->userauth_pblc_packet);
+            session->userauth_pblc_packet = NULL;
+            session->userauth_pblc_state = libssh2_NB_state_idle;
+            return _libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND,
+                                  "Unable to send userauth-publickey request");
+        }
+        LIBSSH2_FREE(session, session->userauth_pblc_packet);
+        session->userauth_pblc_packet = NULL;
+
+        session->userauth_pblc_state = libssh2_NB_state_sent3;
+    }
+
+    /* PK_OK is no longer valid */
+    reply_codes[2] = 0;
+
+    rc = _libssh2_packet_requirev(session, reply_codes,
+                               &session->userauth_pblc_data,
+                               &session->userauth_pblc_data_len, 0, NULL, 0,
+                               &session->userauth_pblc_packet_requirev_state);
+    if(rc == LIBSSH2_ERROR_EAGAIN) {
+        return _libssh2_error(session, LIBSSH2_ERROR_EAGAIN,
+                              "Would block requesting userauth list");
+    }
+    else if(rc || session->userauth_pblc_data_len < 1) {
+        session->userauth_pblc_state = libssh2_NB_state_idle;
+        return _libssh2_error(session, LIBSSH2_ERROR_PUBLICKEY_UNVERIFIED,
+                              "Waiting for publickey USERAUTH response");
+    }
+
+    if(session->userauth_pblc_data[0] == SSH_MSG_USERAUTH_SUCCESS) {
+        _libssh2_debug(session, LIBSSH2_TRACE_AUTH,
+                       "Publickey authentication successful");
+        /* We are us and we've proved it. */
+        LIBSSH2_FREE(session, session->userauth_pblc_data);
+        session->userauth_pblc_data = NULL;
+        session->state |= LIBSSH2_STATE_AUTHENTICATED;
+        session->userauth_pblc_state = libssh2_NB_state_idle;
+        return 0;
+    }
+
+    /* This public key is not allowed for this user on this server */
+    LIBSSH2_FREE(session, session->userauth_pblc_data);
+    session->userauth_pblc_data = NULL;
+    session->userauth_pblc_state = libssh2_NB_state_idle;
+    return _libssh2_error(session, LIBSSH2_ERROR_PUBLICKEY_UNVERIFIED,
+                          "Invalid signature for supplied public key, or bad "
+                          "username/public key combination");
+}
+
+ /*
+  * userauth_publickey_frommemory
+  * Authenticate using a keypair from memory
+  */
+static int
+userauth_publickey_frommemory(LIBSSH2_SESSION *session,
+                              const char *username,
+                              size_t username_len,
+                              const char *publickeydata,
+                              size_t publickeydata_len,
+                              const char *privatekeydata,
+                              size_t privatekeydata_len,
+                              const char *passphrase)
+{
+    unsigned char *pubkeydata = NULL;
+    size_t pubkeydata_len = 0;
+    struct privkey_file privkey_file;
+    void *abstract = &privkey_file;
+    int rc;
+
+#if !LIBSSH2_RSA
+    return _libssh2_error(session, LIBSSH2_ERROR_METHOD_NOT_SUPPORTED,
+                          "RSA is not supported by crypto backend");
+#endif
+
+    privkey_file.filename = privatekeydata;
+    privkey_file.passphrase = passphrase;
+
+    if(session->userauth_pblc_state == libssh2_NB_state_idle) {
+        if(publickeydata_len && publickeydata) {
+            rc = memory_read_publickey(session, &session->userauth_pblc_method,
+                                       &session->userauth_pblc_method_len,
+                                       &pubkeydata, &pubkeydata_len,
+                                       publickeydata, publickeydata_len);
+            if(rc)
+                return rc;
+        }
+        else if(privatekeydata_len && privatekeydata) {
+            /* Compute public key from private key. */
+            if(_libssh2_pub_priv_keyfilememory(session,
+                                            &session->userauth_pblc_method,
+                                            &session->userauth_pblc_method_len,
+                                            &pubkeydata, &pubkeydata_len,
+                                            privatekeydata, privatekeydata_len,
+                                            passphrase))
+                return _libssh2_error(session, LIBSSH2_ERROR_FILE,
+                                      "Unable to extract public key "
+                                      "from private key.");
+        }
+        else {
+            return _libssh2_error(session, LIBSSH2_ERROR_FILE,
+                                  "Invalid data in public and private key.");
+        }
+    }
+
+    rc = _libssh2_userauth_publickey(session, username, username_len,
+                                     pubkeydata, pubkeydata_len,
+                                     sign_frommemory, &abstract);
+    if(pubkeydata)
+        LIBSSH2_FREE(session, pubkeydata);
+
+    return rc;
+}
+
+/*
+ * userauth_publickey_fromfile
+ * Authenticate using a keypair found in the named files
+ */
+static int
+userauth_publickey_fromfile(LIBSSH2_SESSION *session,
+                            const char *username,
+                            size_t username_len,
+                            const char *publickey,
+                            const char *privatekey,
+                            const char *passphrase)
+{
+    unsigned char *pubkeydata = NULL;
+    size_t pubkeydata_len = 0;
+    struct privkey_file privkey_file;
+    void *abstract = &privkey_file;
+    int rc;
+
+#if !LIBSSH2_RSA
+    return _libssh2_error(session, LIBSSH2_ERROR_METHOD_NOT_SUPPORTED,
+                          "RSA is not supported by crypto backend");
+#endif
+
+    privkey_file.filename = privatekey;
+    privkey_file.passphrase = passphrase;
+
+    if(session->userauth_pblc_state == libssh2_NB_state_idle) {
+        if(publickey) {
+            rc = file_read_publickey(session, &session->userauth_pblc_method,
+                                     &session->userauth_pblc_method_len,
+                                     &pubkeydata, &pubkeydata_len, publickey);
+            if(rc)
+                return rc;
+        }
+        else {
+            /* Compute public key from private key. */
+            rc = _libssh2_pub_priv_keyfile(session,
+                                           &session->userauth_pblc_method,
+                                           &session->userauth_pblc_method_len,
+                                           &pubkeydata, &pubkeydata_len,
+                                           privatekey, passphrase);
+
+            /* _libssh2_pub_priv_keyfile calls _libssh2_error() */
+            if(rc)
+                return rc;
+        }
+    }
+
+    rc = _libssh2_userauth_publickey(session, username, username_len,
+                                     pubkeydata, pubkeydata_len,
+                                     sign_fromfile, &abstract);
+    if(pubkeydata)
+        LIBSSH2_FREE(session, pubkeydata);
+
+    return rc;
+}
+
+/* libssh2_userauth_publickey_frommemory
+ * Authenticate using a keypair from memory
+ */
+LIBSSH2_API int
+libssh2_userauth_publickey_frommemory(LIBSSH2_SESSION *session,
+                                      const char *user,
+                                      size_t user_len,
+                                      const char *publickeyfiledata,
+                                      size_t publickeyfiledata_len,
+                                      const char *privatekeyfiledata,
+                                      size_t privatekeyfiledata_len,
+                                      const char *passphrase)
+{
+    int rc;
+
+    if(NULL == passphrase)
+        /* if given a NULL pointer, make it point to a zero-length
+           string to save us from having to check this all over */
+        passphrase = "";
+
+    BLOCK_ADJUST(rc, session,
+                 userauth_publickey_frommemory(session, user, user_len,
+                                               publickeyfiledata,
+                                               publickeyfiledata_len,
+                                               privatekeyfiledata,
+                                               privatekeyfiledata_len,
+                                               passphrase));
+    return rc;
+}
+
+/* libssh2_userauth_publickey_fromfile_ex
+ * Authenticate using a keypair found in the named files
+ */
+LIBSSH2_API int
+libssh2_userauth_publickey_fromfile_ex(LIBSSH2_SESSION *session,
+                                       const char *user,
+                                       unsigned int user_len,
+                                       const char *publickey,
+                                       const char *privatekey,
+                                       const char *passphrase)
+{
+    int rc;
+
+    if(NULL == passphrase)
+        /* if given a NULL pointer, make it point to a zero-length
+           string to save us from having to check this all over */
+        passphrase = "";
+
+    BLOCK_ADJUST(rc, session,
+                 userauth_publickey_fromfile(session, user, user_len,
+                                             publickey, privatekey,
+                                             passphrase));
+    return rc;
+}
+
+/* libssh2_userauth_publickey_ex
+ * Authenticate using an external callback function
+ */
+LIBSSH2_API int
+libssh2_userauth_publickey(LIBSSH2_SESSION *session,
+                           const char *user,
+                           const unsigned char *pubkeydata,
+                           size_t pubkeydata_len,
+                           LIBSSH2_USERAUTH_PUBLICKEY_SIGN_FUNC
+                           ((*sign_callback)),
+                           void **abstract)
+{
+    int rc;
+
+    if(!session)
+        return LIBSSH2_ERROR_BAD_USE;
+
+    BLOCK_ADJUST(rc, session,
+                 _libssh2_userauth_publickey(session, user, strlen(user),
+                                             pubkeydata, pubkeydata_len,
+                                             sign_callback, abstract));
+    return rc;
+}
+
+
+
+/*
+ * userauth_keyboard_interactive
+ *
+ * Authenticate using a challenge-response authentication
+ */
+static int
+userauth_keyboard_interactive(LIBSSH2_SESSION * session,
+                              const char *username,
+                              unsigned int username_len,
+                              LIBSSH2_USERAUTH_KBDINT_RESPONSE_FUNC
+                              ((*response_callback)))
+{
+    unsigned char *s;
+    int rc;
+
+    static const unsigned char reply_codes[4] = {
+        SSH_MSG_USERAUTH_SUCCESS,
+        SSH_MSG_USERAUTH_FAILURE, SSH_MSG_USERAUTH_INFO_REQUEST, 0
+    };
+    unsigned int language_tag_len;
+    unsigned int i;
+
+    if(session->userauth_kybd_state == libssh2_NB_state_idle) {
+        session->userauth_kybd_auth_name = NULL;
+        session->userauth_kybd_auth_instruction = NULL;
+        session->userauth_kybd_num_prompts = 0;
+        session->userauth_kybd_auth_failure = 1;
+        session->userauth_kybd_prompts = NULL;
+        session->userauth_kybd_responses = NULL;
+
+        /* Zero the whole thing out */
+        memset(&session->userauth_kybd_packet_requirev_state, 0,
+               sizeof(session->userauth_kybd_packet_requirev_state));
+
+        session->userauth_kybd_packet_len =
+            1                   /* byte    SSH_MSG_USERAUTH_REQUEST */
+            + 4 + username_len  /* string  user name (ISO-10646 UTF-8, as
+                                   defined in [RFC-3629]) */
+            + 4 + 14            /* string  service name (US-ASCII) */
+            + 4 + 20            /* string  "keyboard-interactive" (US-ASCII) */
+            + 4 + 0             /* string  language tag (as defined in
+                                   [RFC-3066]) */
+            + 4 + 0             /* string  submethods (ISO-10646 UTF-8) */
+            ;
+
+        session->userauth_kybd_data = s =
+            LIBSSH2_ALLOC(session, session->userauth_kybd_packet_len);
+        if(!s) {
+            return _libssh2_error(session, LIBSSH2_ERROR_ALLOC,
+                                  "Unable to allocate memory for "
+                                  "keyboard-interactive authentication");
+        }
+
+        *s++ = SSH_MSG_USERAUTH_REQUEST;
+
+        /* user name */
+        _libssh2_store_str(&s, username, username_len);
+
+        /* service name */
+        _libssh2_store_str(&s, "ssh-connection", sizeof("ssh-connection") - 1);
+
+        /* "keyboard-interactive" */
+        _libssh2_store_str(&s, "keyboard-interactive",
+                           sizeof("keyboard-interactive") - 1);
+        /* language tag */
+        _libssh2_store_u32(&s, 0);
+
+        /* submethods */
+        _libssh2_store_u32(&s, 0);
+
+        _libssh2_debug(session, LIBSSH2_TRACE_AUTH,
+                       "Attempting keyboard-interactive authentication");
+
+        session->userauth_kybd_state = libssh2_NB_state_created;
+    }
+
+    if(session->userauth_kybd_state == libssh2_NB_state_created) {
+        rc = _libssh2_transport_send(session, session->userauth_kybd_data,
+                                     session->userauth_kybd_packet_len,
+                                     NULL, 0);
+        if(rc == LIBSSH2_ERROR_EAGAIN) {
+            return _libssh2_error(session, LIBSSH2_ERROR_EAGAIN,
+                                  "Would block");
+        }
+        else if(rc) {
+            LIBSSH2_FREE(session, session->userauth_kybd_data);
+            session->userauth_kybd_data = NULL;
+            session->userauth_kybd_state = libssh2_NB_state_idle;
+            return _libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND,
+                                  "Unable to send keyboard-interactive"
+                                  " request");
+        }
+        LIBSSH2_FREE(session, session->userauth_kybd_data);
+        session->userauth_kybd_data = NULL;
+
+        session->userauth_kybd_state = libssh2_NB_state_sent;
+    }
+
+    for(;;) {
+        if(session->userauth_kybd_state == libssh2_NB_state_sent) {
+            rc = _libssh2_packet_requirev(session, reply_codes,
+                                          &session->userauth_kybd_data,
+                                          &session->userauth_kybd_data_len,
+                                          0, NULL, 0,
+                                          &session->
+                                          userauth_kybd_packet_requirev_state);
+            if(rc == LIBSSH2_ERROR_EAGAIN) {
+                return _libssh2_error(session, LIBSSH2_ERROR_EAGAIN,
+                                      "Would block");
+            }
+            else if(rc || session->userauth_kybd_data_len < 1) {
+                session->userauth_kybd_state = libssh2_NB_state_idle;
+                return _libssh2_error(session,
+                                      LIBSSH2_ERROR_AUTHENTICATION_FAILED,
+                                      "Waiting for keyboard "
+                                      "USERAUTH response");
+            }
+
+            if(session->userauth_kybd_data[0] == SSH_MSG_USERAUTH_SUCCESS) {
+                _libssh2_debug(session, LIBSSH2_TRACE_AUTH,
+                               "Keyboard-interactive "
+                               "authentication successful");
+                LIBSSH2_FREE(session, session->userauth_kybd_data);
+                session->userauth_kybd_data = NULL;
+                session->state |= LIBSSH2_STATE_AUTHENTICATED;
+                session->userauth_kybd_state = libssh2_NB_state_idle;
+                return 0;
+            }
+
+            if(session->userauth_kybd_data[0] == SSH_MSG_USERAUTH_FAILURE) {
+                _libssh2_debug(session, LIBSSH2_TRACE_AUTH,
+                               "Keyboard-interactive authentication failed");
+                LIBSSH2_FREE(session, session->userauth_kybd_data);
+                session->userauth_kybd_data = NULL;
+                session->userauth_kybd_state = libssh2_NB_state_idle;
+                return _libssh2_error(session,
+                                      LIBSSH2_ERROR_AUTHENTICATION_FAILED,
+                                      "Authentication failed "
+                                      "(keyboard-interactive)");
+            }
+
+            /* server requested PAM-like conversation */
+            s = session->userauth_kybd_data + 1;
+
+            if(session->userauth_kybd_data_len >= 5) {
+                /* string    name (ISO-10646 UTF-8) */
+                session->userauth_kybd_auth_name_len = _libssh2_ntohu32(s);
+                s += 4;
+            }
+            else {
+                _libssh2_error(session, LIBSSH2_ERROR_BUFFER_TOO_SMALL,
+                               "userauth keyboard data buffer too small"
+                               "to get length");
+                goto cleanup;
+            }
+
+            if(session->userauth_kybd_auth_name_len) {
+                session->userauth_kybd_auth_name =
+                    LIBSSH2_ALLOC(session,
+                                  session->userauth_kybd_auth_name_len);
+                if(!session->userauth_kybd_auth_name) {
+                    _libssh2_error(session, LIBSSH2_ERROR_ALLOC,
+                                   "Unable to allocate memory for "
+                                   "keyboard-interactive 'name' "
+                                   "request field");
+                    goto cleanup;
+                }
+                if(s + session->userauth_list_data_len <=
+                   session->userauth_kybd_data +
+                   session->userauth_kybd_data_len) {
+                    memcpy(session->userauth_kybd_auth_name, s,
+                           session->userauth_kybd_auth_name_len);
+                    s += session->userauth_kybd_auth_name_len;
+                }
+                else {
+                    _libssh2_error(session, LIBSSH2_ERROR_BUFFER_TOO_SMALL,
+                                   "userauth keyboard data buffer too small"
+                                   "for auth name");
+                    goto cleanup;
+                }
+            }
+
+            if(s + 4 <= session->userauth_kybd_data +
+               session->userauth_kybd_data_len) {
+                /* string    instruction (ISO-10646 UTF-8) */
+                session->userauth_kybd_auth_instruction_len =
+                    _libssh2_ntohu32(s);
+                s += 4;
+            }
+            else {
+                _libssh2_error(session, LIBSSH2_ERROR_BUFFER_TOO_SMALL,
+                               "userauth keyboard data buffer too small"
+                               "for auth instruction length");
+                goto cleanup;
+            }
+
+            if(session->userauth_kybd_auth_instruction_len) {
+                session->userauth_kybd_auth_instruction =
+                    LIBSSH2_ALLOC(session,
+                                  session->userauth_kybd_auth_instruction_len);
+                if(!session->userauth_kybd_auth_instruction) {
+                    _libssh2_error(session, LIBSSH2_ERROR_ALLOC,
+                                   "Unable to allocate memory for "
+                                   "keyboard-interactive 'instruction' "
+                                   "request field");
+                    goto cleanup;
+                }
+                if(s + session->userauth_kybd_auth_instruction_len <=
+                   session->userauth_kybd_data +
+                   session->userauth_kybd_data_len) {
+                    memcpy(session->userauth_kybd_auth_instruction, s,
+                           session->userauth_kybd_auth_instruction_len);
+                    s += session->userauth_kybd_auth_instruction_len;
+                }
+                else {
+                    _libssh2_error(session, LIBSSH2_ERROR_BUFFER_TOO_SMALL,
+                                   "userauth keyboard data buffer too small"
+                                   "for auth instruction");
+                    goto cleanup;
+                }
+            }
+
+            if(s + 4 <= session->userauth_kybd_data +
+               session->userauth_kybd_data_len) {
+                /* string    language tag (as defined in [RFC-3066]) */
+                language_tag_len = _libssh2_ntohu32(s);
+                s += 4;
+            }
+            else {
+                _libssh2_error(session, LIBSSH2_ERROR_BUFFER_TOO_SMALL,
+                               "userauth keyboard data buffer too small"
+                               "for auth language tag length");
+                goto cleanup;
+            }
+
+            if(s + language_tag_len <= session->userauth_kybd_data +
+               session->userauth_kybd_data_len) {
+                /* ignoring this field as deprecated */
+                s += language_tag_len;
+            }
+            else {
+                _libssh2_error(session, LIBSSH2_ERROR_BUFFER_TOO_SMALL,
+                               "userauth keyboard data buffer too small"
+                               "for auth language tag");
+                goto cleanup;
+            }
+
+            if(s + 4 <= session->userauth_kybd_data +
+               session->userauth_kybd_data_len) {
+                /* int       num-prompts */
+                session->userauth_kybd_num_prompts = _libssh2_ntohu32(s);
+                s += 4;
+            }
+            else {
+                _libssh2_error(session, LIBSSH2_ERROR_BUFFER_TOO_SMALL,
+                               "userauth keyboard data buffer too small"
+                               "for auth num keyboard prompts");
+                goto cleanup;
+            }
+
+            if(session->userauth_kybd_num_prompts > 100) {
+                _libssh2_error(session, LIBSSH2_ERROR_OUT_OF_BOUNDARY,
+                               "Too many replies for "
+                               "keyboard-interactive prompts");
+                goto cleanup;
+            }
+
+            if(session->userauth_kybd_num_prompts) {
+                session->userauth_kybd_prompts =
+                    LIBSSH2_CALLOC(session,
+                                   sizeof(LIBSSH2_USERAUTH_KBDINT_PROMPT) *
+                                   session->userauth_kybd_num_prompts);
+                if(!session->userauth_kybd_prompts) {
+                    _libssh2_error(session, LIBSSH2_ERROR_ALLOC,
+                                   "Unable to allocate memory for "
+                                   "keyboard-interactive prompts array");
+                    goto cleanup;
+                }
+
+                session->userauth_kybd_responses =
+                    LIBSSH2_CALLOC(session,
+                                   sizeof(LIBSSH2_USERAUTH_KBDINT_RESPONSE) *
+                                   session->userauth_kybd_num_prompts);
+                if(!session->userauth_kybd_responses) {
+                    _libssh2_error(session, LIBSSH2_ERROR_ALLOC,
+                                   "Unable to allocate memory for "
+                                   "keyboard-interactive responses array");
+                    goto cleanup;
+                }
+
+                for(i = 0; i < session->userauth_kybd_num_prompts; i++) {
+                    if(s + 4 <= session->userauth_kybd_data +
+                       session->userauth_kybd_data_len) {
+                        /* string    prompt[1] (ISO-10646 UTF-8) */
+                        session->userauth_kybd_prompts[i].length =
+                            _libssh2_ntohu32(s);
+                        s += 4;
+                    }
+                    else {
+                        _libssh2_error(session, LIBSSH2_ERROR_BUFFER_TOO_SMALL,
+                                       "userauth keyboard data buffer too "
+                                       "small for auth keyboard "
+                                       "prompt length");
+                        goto cleanup;
+                    }
+
+                    session->userauth_kybd_prompts[i].text =
+                        LIBSSH2_CALLOC(session,
+                                       session->userauth_kybd_prompts[i].
+                                       length);
+                    if(!session->userauth_kybd_prompts[i].text) {
+                        _libssh2_error(session, LIBSSH2_ERROR_ALLOC,
+                                       "Unable to allocate memory for "
+                                       "keyboard-interactive prompt message");
+                        goto cleanup;
+                    }
+
+                    if(s + session->userauth_kybd_prompts[i].length <=
+                       session->userauth_kybd_data +
+                       session->userauth_kybd_data_len) {
+                        memcpy(session->userauth_kybd_prompts[i].text, s,
+                               session->userauth_kybd_prompts[i].length);
+                        s += session->userauth_kybd_prompts[i].length;
+                    }
+                    else {
+                        _libssh2_error(session, LIBSSH2_ERROR_BUFFER_TOO_SMALL,
+                                       "userauth keyboard data buffer too "
+                                       "small for auth keyboard prompt");
+                        goto cleanup;
+                    }
+                    if(s < session->userauth_kybd_data +
+                       session->userauth_kybd_data_len) {
+                        /* boolean   echo[1] */
+                        session->userauth_kybd_prompts[i].echo = *s++;
+                    }
+                    else {
+                        _libssh2_error(session, LIBSSH2_ERROR_BUFFER_TOO_SMALL,
+                                       "userauth keyboard data buffer too "
+                                       "small for auth keyboard prompt echo");
+                        goto cleanup;
+                    }
+                }
+            }
+
+            response_callback(session->userauth_kybd_auth_name,
+                              session->userauth_kybd_auth_name_len,
+                              session->userauth_kybd_auth_instruction,
+                              session->userauth_kybd_auth_instruction_len,
+                              session->userauth_kybd_num_prompts,
+                              session->userauth_kybd_prompts,
+                              session->userauth_kybd_responses,
+                              &session->abstract);
+
+            _libssh2_debug(session, LIBSSH2_TRACE_AUTH,
+                           "Keyboard-interactive response callback function"
+                           " invoked");
+
+            session->userauth_kybd_packet_len =
+                1 /* byte      SSH_MSG_USERAUTH_INFO_RESPONSE */
+                + 4             /* int       num-responses */
+                ;
+
+            for(i = 0; i < session->userauth_kybd_num_prompts; i++) {
+                /* string    response[1] (ISO-10646 UTF-8) */
+                if(session->userauth_kybd_responses[i].length <=
+                   (SIZE_MAX - 4 - session->userauth_kybd_packet_len) ) {
+                    session->userauth_kybd_packet_len +=
+                        4 + session->userauth_kybd_responses[i].length;
+                }
+                else {
+                    _libssh2_error(session, LIBSSH2_ERROR_ALLOC,
+                                   "Unable to allocate memory for keyboard-"
+                                   "interactive response packet");
+                    goto cleanup;
+                }
+            }
+
+            /* A new userauth_kybd_data area is to be allocated, free the
+               former one. */
+            LIBSSH2_FREE(session, session->userauth_kybd_data);
+
+            session->userauth_kybd_data = s =
+                LIBSSH2_ALLOC(session, session->userauth_kybd_packet_len);
+            if(!s) {
+                _libssh2_error(session, LIBSSH2_ERROR_ALLOC,
+                               "Unable to allocate memory for keyboard-"
+                               "interactive response packet");
+                goto cleanup;
+            }
+
+            *s = SSH_MSG_USERAUTH_INFO_RESPONSE;
+            s++;
+            _libssh2_store_u32(&s, session->userauth_kybd_num_prompts);
+
+            for(i = 0; i < session->userauth_kybd_num_prompts; i++) {
+                _libssh2_store_str(&s,
+                                   session->userauth_kybd_responses[i].text,
+                                   session->userauth_kybd_responses[i].length);
+            }
+
+            session->userauth_kybd_state = libssh2_NB_state_sent1;
+        }
+
+        if(session->userauth_kybd_state == libssh2_NB_state_sent1) {
+            rc = _libssh2_transport_send(session, session->userauth_kybd_data,
+                                         session->userauth_kybd_packet_len,
+                                         NULL, 0);
+            if(rc == LIBSSH2_ERROR_EAGAIN)
+                return _libssh2_error(session, LIBSSH2_ERROR_EAGAIN,
+                                      "Would block");
+            if(rc) {
+                _libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND,
+                               "Unable to send userauth-keyboard-interactive"
+                               " request");
+                goto cleanup;
+            }
+
+            session->userauth_kybd_auth_failure = 0;
+        }
+
+      cleanup:
+        /*
+         * It's safe to clean all the data here, because unallocated pointers
+         * are filled by zeroes
+         */
+
+        LIBSSH2_FREE(session, session->userauth_kybd_data);
+        session->userauth_kybd_data = NULL;
+
+        if(session->userauth_kybd_prompts) {
+            for(i = 0; i < session->userauth_kybd_num_prompts; i++) {
+                LIBSSH2_FREE(session, session->userauth_kybd_prompts[i].text);
+                session->userauth_kybd_prompts[i].text = NULL;
+            }
+        }
+
+        if(session->userauth_kybd_responses) {
+            for(i = 0; i < session->userauth_kybd_num_prompts; i++) {
+                LIBSSH2_FREE(session,
+                             session->userauth_kybd_responses[i].text);
+                session->userauth_kybd_responses[i].text = NULL;
+            }
+        }
+
+        if(session->userauth_kybd_prompts) {
+            LIBSSH2_FREE(session, session->userauth_kybd_prompts);
+            session->userauth_kybd_prompts = NULL;
+        }
+        if(session->userauth_kybd_responses) {
+            LIBSSH2_FREE(session, session->userauth_kybd_responses);
+            session->userauth_kybd_responses = NULL;
+        }
+        if(session->userauth_kybd_auth_name) {
+            LIBSSH2_FREE(session, session->userauth_kybd_auth_name);
+            session->userauth_kybd_auth_name = NULL;
+        }
+        if(session->userauth_kybd_auth_instruction) {
+            LIBSSH2_FREE(session, session->userauth_kybd_auth_instruction);
+            session->userauth_kybd_auth_instruction = NULL;
+        }
+
+        if(session->userauth_kybd_auth_failure) {
+            session->userauth_kybd_state = libssh2_NB_state_idle;
+            return -1;
+        }
+
+        session->userauth_kybd_state = libssh2_NB_state_sent;
+    }
+}
+
+/*
+ * libssh2_userauth_keyboard_interactive_ex
+ *
+ * Authenticate using a challenge-response authentication
+ */
+LIBSSH2_API int
+libssh2_userauth_keyboard_interactive_ex(LIBSSH2_SESSION *session,
+                                         const char *user,
+                                         unsigned int user_len,
+                                         LIBSSH2_USERAUTH_KBDINT_RESPONSE_FUNC
+                                         ((*response_callback)))
+{
+    int rc;
+    BLOCK_ADJUST(rc, session,
+                 userauth_keyboard_interactive(session, user, user_len,
+                                               response_callback));
+    return rc;
+}

+ 51 - 0
libssh2/libssh2/src/userauth.h

@@ -0,0 +1,51 @@
+#ifndef LIBSSH2_USERAUTH_H
+#define LIBSSH2_USERAUTH_H
+/* Copyright (c) 2004-2007, Sara Golemon <sarag@libssh2.org>
+ * Copyright (c) 2009-2010 by Daniel Stenberg
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms,
+ * with or without modification, are permitted provided
+ * that the following conditions are met:
+ *
+ *   Redistributions of source code must retain the above
+ *   copyright notice, this list of conditions and the
+ *   following disclaimer.
+ *
+ *   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.
+ *
+ *   Neither the name of the copyright holder nor the names
+ *   of any other contributors may be used to endorse or
+ *   promote products derived from this software without
+ *   specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+ * CONTRIBUTORS "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 COPYRIGHT OWNER OR
+ * CONTRIBUTORS 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.
+ */
+
+int
+_libssh2_userauth_publickey(LIBSSH2_SESSION *session,
+                            const char *username,
+                            unsigned int username_len,
+                            const unsigned char *pubkeydata,
+                            unsigned long pubkeydata_len,
+                            LIBSSH2_USERAUTH_PUBLICKEY_SIGN_FUNC
+                            ((*sign_callback)),
+                            void *abstract);
+
+#endif /* LIBSSH2_USERAUTH_H */

+ 54 - 0
libssh2/libssh2/src/version.c

@@ -0,0 +1,54 @@
+/* Copyright (C) 2009 Daniel Stenberg.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms,
+ * with or without modification, are permitted provided
+ * that the following conditions are met:
+ *
+ *   Redistributions of source code must retain the above
+ *   copyright notice, this list of conditions and the
+ *   following disclaimer.
+ *
+ *   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.
+ *
+ *   Neither the name of the copyright holder nor the names
+ *   of any other contributors may be used to endorse or
+ *   promote products derived from this software without
+ *   specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+ * CONTRIBUTORS "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 COPYRIGHT OWNER OR
+ * CONTRIBUTORS 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 "libssh2_priv.h"
+
+/*
+  libssh2_version() can be used like this:
+
+  if (!libssh2_version(LIBSSH2_VERSION_NUM)) {
+    fprintf (stderr, "Runtime libssh2 version too old!\n");
+    exit(1);
+  }
+*/
+LIBSSH2_API
+const char *libssh2_version(int req_version_num)
+{
+    if(req_version_num <= LIBSSH2_VERSION_NUM)
+        return LIBSSH2_VERSION;
+    return NULL; /* this is not a suitable library! */
+}

+ 2168 - 0
libssh2/libssh2/src/wincng.c

@@ -0,0 +1,2168 @@
+/*
+ * Copyright (C) 2013-2015 Marc Hoersken <info@marc-hoersken.de>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms,
+ * with or without modification, are permitted provided
+ * that the following conditions are met:
+ *
+ *   Redistributions of source code must retain the above
+ *   copyright notice, this list of conditions and the
+ *   following disclaimer.
+ *
+ *   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.
+ *
+ *   Neither the name of the copyright holder nor the names
+ *   of any other contributors may be used to endorse or
+ *   promote products derived from this software without
+ *   specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+ * CONTRIBUTORS "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 COPYRIGHT OWNER OR
+ * CONTRIBUTORS 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 "libssh2_priv.h"
+
+#ifdef LIBSSH2_WINCNG /* compile only if we build with wincng */
+
+/* required for cross-compilation against the w64 mingw-runtime package */
+#if defined(_WIN32_WINNT) && (_WIN32_WINNT < 0x0600)
+#undef _WIN32_WINNT
+#endif
+#ifndef _WIN32_WINNT
+#define _WIN32_WINNT 0x0600
+#endif
+
+/* specify the required libraries for dependencies using MSVC */
+#ifdef _MSC_VER
+#pragma comment(lib, "bcrypt.lib")
+#ifdef HAVE_LIBCRYPT32
+#pragma comment(lib, "crypt32.lib")
+#endif
+#endif
+
+#include <windows.h>
+#include <bcrypt.h>
+#include <math.h>
+#include "misc.h"
+
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+#ifdef HAVE_LIBCRYPT32
+#include <wincrypt.h>
+#endif
+
+#define PEM_RSA_HEADER "-----BEGIN RSA PRIVATE KEY-----"
+#define PEM_RSA_FOOTER "-----END RSA PRIVATE KEY-----"
+#define PEM_DSA_HEADER "-----BEGIN DSA PRIVATE KEY-----"
+#define PEM_DSA_FOOTER "-----END DSA PRIVATE KEY-----"
+
+
+/*******************************************************************/
+/*
+ * Windows CNG backend: Missing definitions (for MinGW[-w64])
+ */
+#ifndef BCRYPT_SUCCESS
+#define BCRYPT_SUCCESS(Status) (((NTSTATUS)(Status)) >= 0)
+#endif
+
+#ifndef BCRYPT_RNG_ALGORITHM
+#define BCRYPT_RNG_ALGORITHM L"RNG"
+#endif
+
+#ifndef BCRYPT_MD5_ALGORITHM
+#define BCRYPT_MD5_ALGORITHM L"MD5"
+#endif
+
+#ifndef BCRYPT_SHA1_ALGORITHM
+#define BCRYPT_SHA1_ALGORITHM L"SHA1"
+#endif
+
+#ifndef BCRYPT_SHA256_ALGORITHM
+#define BCRYPT_SHA256_ALGORITHM L"SHA256"
+#endif
+
+#ifndef BCRYPT_SHA512_ALGORITHM
+#define BCRYPT_SHA512_ALGORITHM L"SHA512"
+#endif
+
+#ifndef BCRYPT_RSA_ALGORITHM
+#define BCRYPT_RSA_ALGORITHM L"RSA"
+#endif
+
+#ifndef BCRYPT_DSA_ALGORITHM
+#define BCRYPT_DSA_ALGORITHM L"DSA"
+#endif
+
+#ifndef BCRYPT_AES_ALGORITHM
+#define BCRYPT_AES_ALGORITHM L"AES"
+#endif
+
+#ifndef BCRYPT_RC4_ALGORITHM
+#define BCRYPT_RC4_ALGORITHM L"RC4"
+#endif
+
+#ifndef BCRYPT_3DES_ALGORITHM
+#define BCRYPT_3DES_ALGORITHM L"3DES"
+#endif
+
+#ifndef BCRYPT_ALG_HANDLE_HMAC_FLAG
+#define BCRYPT_ALG_HANDLE_HMAC_FLAG 0x00000008
+#endif
+
+#ifndef BCRYPT_DSA_PUBLIC_BLOB
+#define BCRYPT_DSA_PUBLIC_BLOB L"DSAPUBLICBLOB"
+#endif
+
+#ifndef BCRYPT_DSA_PUBLIC_MAGIC
+#define BCRYPT_DSA_PUBLIC_MAGIC 0x42505344 /* DSPB */
+#endif
+
+#ifndef BCRYPT_DSA_PRIVATE_BLOB
+#define BCRYPT_DSA_PRIVATE_BLOB L"DSAPRIVATEBLOB"
+#endif
+
+#ifndef BCRYPT_DSA_PRIVATE_MAGIC
+#define BCRYPT_DSA_PRIVATE_MAGIC 0x56505344 /* DSPV */
+#endif
+
+#ifndef BCRYPT_RSAPUBLIC_BLOB
+#define BCRYPT_RSAPUBLIC_BLOB L"RSAPUBLICBLOB"
+#endif
+
+#ifndef BCRYPT_RSAPUBLIC_MAGIC
+#define BCRYPT_RSAPUBLIC_MAGIC 0x31415352 /* RSA1 */
+#endif
+
+#ifndef BCRYPT_RSAFULLPRIVATE_BLOB
+#define BCRYPT_RSAFULLPRIVATE_BLOB L"RSAFULLPRIVATEBLOB"
+#endif
+
+#ifndef BCRYPT_RSAFULLPRIVATE_MAGIC
+#define BCRYPT_RSAFULLPRIVATE_MAGIC 0x33415352 /* RSA3 */
+#endif
+
+#ifndef BCRYPT_KEY_DATA_BLOB
+#define BCRYPT_KEY_DATA_BLOB L"KeyDataBlob"
+#endif
+
+#ifndef BCRYPT_MESSAGE_BLOCK_LENGTH
+#define BCRYPT_MESSAGE_BLOCK_LENGTH L"MessageBlockLength"
+#endif
+
+#ifndef BCRYPT_NO_KEY_VALIDATION
+#define BCRYPT_NO_KEY_VALIDATION 0x00000008
+#endif
+
+#ifndef BCRYPT_BLOCK_PADDING
+#define BCRYPT_BLOCK_PADDING 0x00000001
+#endif
+
+#ifndef BCRYPT_PAD_NONE
+#define BCRYPT_PAD_NONE 0x00000001
+#endif
+
+#ifndef BCRYPT_PAD_PKCS1
+#define BCRYPT_PAD_PKCS1 0x00000002
+#endif
+
+#ifndef BCRYPT_PAD_OAEP
+#define BCRYPT_PAD_OAEP 0x00000004
+#endif
+
+#ifndef BCRYPT_PAD_PSS
+#define BCRYPT_PAD_PSS 0x00000008
+#endif
+
+#ifndef CRYPT_STRING_ANY
+#define CRYPT_STRING_ANY 0x00000007
+#endif
+
+#ifndef LEGACY_RSAPRIVATE_BLOB
+#define LEGACY_RSAPRIVATE_BLOB L"CAPIPRIVATEBLOB"
+#endif
+
+#ifndef PKCS_RSA_PRIVATE_KEY
+#define PKCS_RSA_PRIVATE_KEY (LPCSTR)43
+#endif
+
+
+/*******************************************************************/
+/*
+ * Windows CNG backend: Generic functions
+ */
+
+void
+_libssh2_wincng_init(void)
+{
+    int ret;
+
+    (void)BCryptOpenAlgorithmProvider(&_libssh2_wincng.hAlgRNG,
+                                      BCRYPT_RNG_ALGORITHM, NULL, 0);
+
+    (void)BCryptOpenAlgorithmProvider(&_libssh2_wincng.hAlgHashMD5,
+                                      BCRYPT_MD5_ALGORITHM, NULL, 0);
+    (void)BCryptOpenAlgorithmProvider(&_libssh2_wincng.hAlgHashSHA1,
+                                      BCRYPT_SHA1_ALGORITHM, NULL, 0);
+    (void)BCryptOpenAlgorithmProvider(&_libssh2_wincng.hAlgHashSHA256,
+                                      BCRYPT_SHA256_ALGORITHM, NULL, 0);
+    (void)BCryptOpenAlgorithmProvider(&_libssh2_wincng.hAlgHashSHA512,
+                                      BCRYPT_SHA512_ALGORITHM, NULL, 0);
+
+    (void)BCryptOpenAlgorithmProvider(&_libssh2_wincng.hAlgHmacMD5,
+                                      BCRYPT_MD5_ALGORITHM, NULL,
+                                      BCRYPT_ALG_HANDLE_HMAC_FLAG);
+    (void)BCryptOpenAlgorithmProvider(&_libssh2_wincng.hAlgHmacSHA1,
+                                      BCRYPT_SHA1_ALGORITHM, NULL,
+                                      BCRYPT_ALG_HANDLE_HMAC_FLAG);
+    (void)BCryptOpenAlgorithmProvider(&_libssh2_wincng.hAlgHmacSHA256,
+                                      BCRYPT_SHA256_ALGORITHM, NULL,
+                                      BCRYPT_ALG_HANDLE_HMAC_FLAG);
+    (void)BCryptOpenAlgorithmProvider(&_libssh2_wincng.hAlgHmacSHA512,
+                                      BCRYPT_SHA512_ALGORITHM, NULL,
+                                      BCRYPT_ALG_HANDLE_HMAC_FLAG);
+
+    (void)BCryptOpenAlgorithmProvider(&_libssh2_wincng.hAlgRSA,
+                                      BCRYPT_RSA_ALGORITHM, NULL, 0);
+    (void)BCryptOpenAlgorithmProvider(&_libssh2_wincng.hAlgDSA,
+                                      BCRYPT_DSA_ALGORITHM, NULL, 0);
+
+    ret = BCryptOpenAlgorithmProvider(&_libssh2_wincng.hAlgAES_CBC,
+                                      BCRYPT_AES_ALGORITHM, NULL, 0);
+    if(BCRYPT_SUCCESS(ret)) {
+        ret = BCryptSetProperty(_libssh2_wincng.hAlgAES_CBC,
+                                BCRYPT_CHAINING_MODE,
+                                (PBYTE)BCRYPT_CHAIN_MODE_CBC,
+                                sizeof(BCRYPT_CHAIN_MODE_CBC), 0);
+        if(!BCRYPT_SUCCESS(ret)) {
+            (void)BCryptCloseAlgorithmProvider(_libssh2_wincng.hAlgAES_CBC, 0);
+        }
+    }
+
+    ret = BCryptOpenAlgorithmProvider(&_libssh2_wincng.hAlgAES_ECB,
+                                      BCRYPT_AES_ALGORITHM, NULL, 0);
+    if(BCRYPT_SUCCESS(ret)) {
+        ret = BCryptSetProperty(_libssh2_wincng.hAlgAES_ECB,
+                                BCRYPT_CHAINING_MODE,
+                                (PBYTE)BCRYPT_CHAIN_MODE_ECB,
+                                sizeof(BCRYPT_CHAIN_MODE_ECB), 0);
+        if(!BCRYPT_SUCCESS(ret)) {
+            (void)BCryptCloseAlgorithmProvider(_libssh2_wincng.hAlgAES_ECB, 0);
+        }
+    }
+
+    ret = BCryptOpenAlgorithmProvider(&_libssh2_wincng.hAlgRC4_NA,
+                                      BCRYPT_RC4_ALGORITHM, NULL, 0);
+    if(BCRYPT_SUCCESS(ret)) {
+        ret = BCryptSetProperty(_libssh2_wincng.hAlgRC4_NA,
+                                BCRYPT_CHAINING_MODE,
+                                (PBYTE)BCRYPT_CHAIN_MODE_NA,
+                                sizeof(BCRYPT_CHAIN_MODE_NA), 0);
+        if(!BCRYPT_SUCCESS(ret)) {
+            (void)BCryptCloseAlgorithmProvider(_libssh2_wincng.hAlgRC4_NA, 0);
+        }
+    }
+
+    ret = BCryptOpenAlgorithmProvider(&_libssh2_wincng.hAlg3DES_CBC,
+                                      BCRYPT_3DES_ALGORITHM, NULL, 0);
+    if(BCRYPT_SUCCESS(ret)) {
+        ret = BCryptSetProperty(_libssh2_wincng.hAlg3DES_CBC,
+                                BCRYPT_CHAINING_MODE,
+                                (PBYTE)BCRYPT_CHAIN_MODE_CBC,
+                                sizeof(BCRYPT_CHAIN_MODE_CBC), 0);
+        if(!BCRYPT_SUCCESS(ret)) {
+            (void)BCryptCloseAlgorithmProvider(_libssh2_wincng.hAlg3DES_CBC,
+                                               0);
+        }
+    }
+}
+
+void
+_libssh2_wincng_free(void)
+{
+    (void)BCryptCloseAlgorithmProvider(_libssh2_wincng.hAlgRNG, 0);
+    (void)BCryptCloseAlgorithmProvider(_libssh2_wincng.hAlgHashMD5, 0);
+    (void)BCryptCloseAlgorithmProvider(_libssh2_wincng.hAlgHashSHA1, 0);
+    (void)BCryptCloseAlgorithmProvider(_libssh2_wincng.hAlgHashSHA256, 0);
+    (void)BCryptCloseAlgorithmProvider(_libssh2_wincng.hAlgHashSHA512, 0);
+    (void)BCryptCloseAlgorithmProvider(_libssh2_wincng.hAlgHmacMD5, 0);
+    (void)BCryptCloseAlgorithmProvider(_libssh2_wincng.hAlgHmacSHA1, 0);
+    (void)BCryptCloseAlgorithmProvider(_libssh2_wincng.hAlgHmacSHA256, 0);
+    (void)BCryptCloseAlgorithmProvider(_libssh2_wincng.hAlgHmacSHA512, 0);
+    (void)BCryptCloseAlgorithmProvider(_libssh2_wincng.hAlgRSA, 0);
+    (void)BCryptCloseAlgorithmProvider(_libssh2_wincng.hAlgDSA, 0);
+    (void)BCryptCloseAlgorithmProvider(_libssh2_wincng.hAlgAES_CBC, 0);
+    (void)BCryptCloseAlgorithmProvider(_libssh2_wincng.hAlgRC4_NA, 0);
+    (void)BCryptCloseAlgorithmProvider(_libssh2_wincng.hAlg3DES_CBC, 0);
+
+    memset(&_libssh2_wincng, 0, sizeof(_libssh2_wincng));
+}
+
+int
+_libssh2_wincng_random(void *buf, int len)
+{
+    int ret;
+
+    ret = BCryptGenRandom(_libssh2_wincng.hAlgRNG, buf, len, 0);
+
+    return BCRYPT_SUCCESS(ret) ? 0 : -1;
+}
+
+static void
+_libssh2_wincng_safe_free(void *buf, int len)
+{
+#ifndef LIBSSH2_CLEAR_MEMORY
+    (void)len;
+#endif
+
+    if(!buf)
+        return;
+
+#ifdef LIBSSH2_CLEAR_MEMORY
+    if(len > 0)
+        SecureZeroMemory(buf, len);
+#endif
+
+    free(buf);
+}
+
+
+/*******************************************************************/
+/*
+ * Windows CNG backend: Hash functions
+ */
+
+int
+_libssh2_wincng_hash_init(_libssh2_wincng_hash_ctx *ctx,
+                          BCRYPT_ALG_HANDLE hAlg, unsigned long hashlen,
+                          unsigned char *key, unsigned long keylen)
+{
+    BCRYPT_HASH_HANDLE hHash;
+    unsigned char *pbHashObject;
+    unsigned long dwHashObject, dwHash, cbData;
+    int ret;
+
+    ret = BCryptGetProperty(hAlg, BCRYPT_HASH_LENGTH,
+                            (unsigned char *)&dwHash,
+                            sizeof(dwHash),
+                            &cbData, 0);
+    if((!BCRYPT_SUCCESS(ret)) || dwHash != hashlen) {
+        return -1;
+    }
+
+    ret = BCryptGetProperty(hAlg, BCRYPT_OBJECT_LENGTH,
+                            (unsigned char *)&dwHashObject,
+                            sizeof(dwHashObject),
+                            &cbData, 0);
+    if(!BCRYPT_SUCCESS(ret)) {
+        return -1;
+    }
+
+    pbHashObject = malloc(dwHashObject);
+    if(!pbHashObject) {
+        return -1;
+    }
+
+
+    ret = BCryptCreateHash(hAlg, &hHash,
+                           pbHashObject, dwHashObject,
+                           key, keylen, 0);
+    if(!BCRYPT_SUCCESS(ret)) {
+        _libssh2_wincng_safe_free(pbHashObject, dwHashObject);
+        return -1;
+    }
+
+
+    ctx->hHash = hHash;
+    ctx->pbHashObject = pbHashObject;
+    ctx->dwHashObject = dwHashObject;
+    ctx->cbHash = dwHash;
+
+    return 0;
+}
+
+int
+_libssh2_wincng_hash_update(_libssh2_wincng_hash_ctx *ctx,
+                            const unsigned char *data, unsigned long datalen)
+{
+    int ret;
+
+    ret = BCryptHashData(ctx->hHash, (unsigned char *)data, datalen, 0);
+
+    return BCRYPT_SUCCESS(ret) ? 0 : -1;
+}
+
+int
+_libssh2_wincng_hash_final(_libssh2_wincng_hash_ctx *ctx,
+                           unsigned char *hash)
+{
+    int ret;
+
+    ret = BCryptFinishHash(ctx->hHash, hash, ctx->cbHash, 0);
+
+    BCryptDestroyHash(ctx->hHash);
+    ctx->hHash = NULL;
+
+    _libssh2_wincng_safe_free(ctx->pbHashObject, ctx->dwHashObject);
+    ctx->pbHashObject = NULL;
+    ctx->dwHashObject = 0;
+
+    return BCRYPT_SUCCESS(ret) ? 0 : -1;
+}
+
+int
+_libssh2_wincng_hash(unsigned char *data, unsigned long datalen,
+                     BCRYPT_ALG_HANDLE hAlg,
+                     unsigned char *hash, unsigned long hashlen)
+{
+    _libssh2_wincng_hash_ctx ctx;
+    int ret;
+
+    ret = _libssh2_wincng_hash_init(&ctx, hAlg, hashlen, NULL, 0);
+    if(!ret) {
+        ret = _libssh2_wincng_hash_update(&ctx, data, datalen);
+        ret |= _libssh2_wincng_hash_final(&ctx, hash);
+    }
+
+    return ret;
+}
+
+
+/*******************************************************************/
+/*
+ * Windows CNG backend: HMAC functions
+ */
+
+int
+_libssh2_wincng_hmac_final(_libssh2_wincng_hash_ctx *ctx,
+                           unsigned char *hash)
+{
+    int ret;
+
+    ret = BCryptFinishHash(ctx->hHash, hash, ctx->cbHash, 0);
+
+    return BCRYPT_SUCCESS(ret) ? 0 : -1;
+}
+
+void
+_libssh2_wincng_hmac_cleanup(_libssh2_wincng_hash_ctx *ctx)
+{
+    BCryptDestroyHash(ctx->hHash);
+    ctx->hHash = NULL;
+
+    _libssh2_wincng_safe_free(ctx->pbHashObject, ctx->dwHashObject);
+    ctx->pbHashObject = NULL;
+    ctx->dwHashObject = 0;
+}
+
+
+/*******************************************************************/
+/*
+ * Windows CNG backend: Key functions
+ */
+
+int
+_libssh2_wincng_key_sha1_verify(_libssh2_wincng_key_ctx *ctx,
+                                const unsigned char *sig,
+                                unsigned long sig_len,
+                                const unsigned char *m,
+                                unsigned long m_len,
+                                unsigned long flags)
+{
+    BCRYPT_PKCS1_PADDING_INFO paddingInfoPKCS1;
+    void *pPaddingInfo;
+    unsigned char *data, *hash;
+    unsigned long datalen, hashlen;
+    int ret;
+
+    datalen = m_len;
+    data = malloc(datalen);
+    if(!data) {
+        return -1;
+    }
+
+    hashlen = SHA_DIGEST_LENGTH;
+    hash = malloc(hashlen);
+    if(!hash) {
+        free(data);
+        return -1;
+    }
+
+    memcpy(data, m, datalen);
+
+    ret = _libssh2_wincng_hash(data, datalen,
+                               _libssh2_wincng.hAlgHashSHA1,
+                               hash, hashlen);
+
+    _libssh2_wincng_safe_free(data, datalen);
+
+    if(ret) {
+        _libssh2_wincng_safe_free(hash, hashlen);
+        return -1;
+    }
+
+    datalen = sig_len;
+    data = malloc(datalen);
+    if(!data) {
+        _libssh2_wincng_safe_free(hash, hashlen);
+        return -1;
+    }
+
+    if(flags & BCRYPT_PAD_PKCS1) {
+        paddingInfoPKCS1.pszAlgId = BCRYPT_SHA1_ALGORITHM;
+        pPaddingInfo = &paddingInfoPKCS1;
+    }
+    else
+        pPaddingInfo = NULL;
+
+    memcpy(data, sig, datalen);
+
+    ret = BCryptVerifySignature(ctx->hKey, pPaddingInfo,
+                                hash, hashlen, data, datalen, flags);
+
+    _libssh2_wincng_safe_free(hash, hashlen);
+    _libssh2_wincng_safe_free(data, datalen);
+
+    return BCRYPT_SUCCESS(ret) ? 0 : -1;
+}
+
+#ifdef HAVE_LIBCRYPT32
+static int
+_libssh2_wincng_load_pem(LIBSSH2_SESSION *session,
+                         const char *filename,
+                         const char *passphrase,
+                         const char *headerbegin,
+                         const char *headerend,
+                         unsigned char **data,
+                         unsigned int *datalen)
+{
+    FILE *fp;
+    int ret;
+
+    fp = fopen(filename, FOPEN_READTEXT);
+    if(!fp) {
+        return -1;
+    }
+
+    ret = _libssh2_pem_parse(session, headerbegin, headerend,
+                             passphrase,
+                             fp, data, datalen);
+
+    fclose(fp);
+
+    return ret;
+}
+
+static int
+_libssh2_wincng_load_private(LIBSSH2_SESSION *session,
+                             const char *filename,
+                             const char *passphrase,
+                             unsigned char **ppbEncoded,
+                             unsigned long *pcbEncoded,
+                             int tryLoadRSA, int tryLoadDSA)
+{
+    unsigned char *data = NULL;
+    unsigned int datalen = 0;
+    int ret = -1;
+
+    if(ret && tryLoadRSA) {
+        ret = _libssh2_wincng_load_pem(session, filename, passphrase,
+                                       PEM_RSA_HEADER, PEM_RSA_FOOTER,
+                                       &data, &datalen);
+    }
+
+    if(ret && tryLoadDSA) {
+        ret = _libssh2_wincng_load_pem(session, filename, passphrase,
+                                       PEM_DSA_HEADER, PEM_DSA_FOOTER,
+                                       &data, &datalen);
+    }
+
+    if(!ret) {
+        *ppbEncoded = data;
+        *pcbEncoded = datalen;
+    }
+
+    return ret;
+}
+
+static int
+_libssh2_wincng_load_private_memory(LIBSSH2_SESSION *session,
+                                    const char *privatekeydata,
+                                    size_t privatekeydata_len,
+                                    const char *passphrase,
+                                    unsigned char **ppbEncoded,
+                                    unsigned long *pcbEncoded,
+                                    int tryLoadRSA, int tryLoadDSA)
+{
+    unsigned char *data = NULL;
+    unsigned int datalen = 0;
+    int ret = -1;
+
+    (void)passphrase;
+
+    if(ret && tryLoadRSA) {
+        ret = _libssh2_pem_parse_memory(session,
+                                        PEM_RSA_HEADER, PEM_RSA_FOOTER,
+                                        privatekeydata, privatekeydata_len,
+                                        &data, &datalen);
+    }
+
+    if(ret && tryLoadDSA) {
+        ret = _libssh2_pem_parse_memory(session,
+                                        PEM_DSA_HEADER, PEM_DSA_FOOTER,
+                                        privatekeydata, privatekeydata_len,
+                                        &data, &datalen);
+    }
+
+    if(!ret) {
+        *ppbEncoded = data;
+        *pcbEncoded = datalen;
+    }
+
+    return ret;
+}
+
+static int
+_libssh2_wincng_asn_decode(unsigned char *pbEncoded,
+                           unsigned long cbEncoded,
+                           LPCSTR lpszStructType,
+                           unsigned char **ppbDecoded,
+                           unsigned long *pcbDecoded)
+{
+    unsigned char *pbDecoded = NULL;
+    unsigned long cbDecoded = 0;
+    int ret;
+
+    ret = CryptDecodeObjectEx(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
+                              lpszStructType,
+                              pbEncoded, cbEncoded, 0, NULL,
+                              NULL, &cbDecoded);
+    if(!ret) {
+        return -1;
+    }
+
+    pbDecoded = malloc(cbDecoded);
+    if(!pbDecoded) {
+        return -1;
+    }
+
+    ret = CryptDecodeObjectEx(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
+                              lpszStructType,
+                              pbEncoded, cbEncoded, 0, NULL,
+                              pbDecoded, &cbDecoded);
+    if(!ret) {
+        _libssh2_wincng_safe_free(pbDecoded, cbDecoded);
+        return -1;
+    }
+
+
+    *ppbDecoded = pbDecoded;
+    *pcbDecoded = cbDecoded;
+
+    return 0;
+}
+
+static int
+_libssh2_wincng_bn_ltob(unsigned char *pbInput,
+                        unsigned long cbInput,
+                        unsigned char **ppbOutput,
+                        unsigned long *pcbOutput)
+{
+    unsigned char *pbOutput;
+    unsigned long cbOutput, index, offset, length;
+
+    if(cbInput < 1) {
+        return 0;
+    }
+
+    offset = 0;
+    length = cbInput - 1;
+    cbOutput = cbInput;
+    if(pbInput[length] & (1 << 7)) {
+        offset++;
+        cbOutput += offset;
+    }
+
+    pbOutput = (unsigned char *)malloc(cbOutput);
+    if(!pbOutput) {
+        return -1;
+    }
+
+    pbOutput[0] = 0;
+    for(index = 0; ((index + offset) < cbOutput)
+                    && (index < cbInput); index++) {
+        pbOutput[index + offset] = pbInput[length - index];
+    }
+
+
+    *ppbOutput = pbOutput;
+    *pcbOutput = cbOutput;
+
+    return 0;
+}
+
+static int
+_libssh2_wincng_asn_decode_bn(unsigned char *pbEncoded,
+                              unsigned long cbEncoded,
+                              unsigned char **ppbDecoded,
+                              unsigned long *pcbDecoded)
+{
+    unsigned char *pbDecoded = NULL, *pbInteger;
+    unsigned long cbDecoded = 0, cbInteger;
+    int ret;
+
+    ret = _libssh2_wincng_asn_decode(pbEncoded, cbEncoded,
+                                     X509_MULTI_BYTE_UINT,
+                                     &pbInteger, &cbInteger);
+    if(!ret) {
+        ret = _libssh2_wincng_bn_ltob(((PCRYPT_DATA_BLOB)pbInteger)->pbData,
+                                      ((PCRYPT_DATA_BLOB)pbInteger)->cbData,
+                                      &pbDecoded, &cbDecoded);
+        if(!ret) {
+            *ppbDecoded = pbDecoded;
+            *pcbDecoded = cbDecoded;
+        }
+        _libssh2_wincng_safe_free(pbInteger, cbInteger);
+    }
+
+    return ret;
+}
+
+static int
+_libssh2_wincng_asn_decode_bns(unsigned char *pbEncoded,
+                               unsigned long cbEncoded,
+                               unsigned char ***prpbDecoded,
+                               unsigned long **prcbDecoded,
+                               unsigned long *pcbCount)
+{
+    PCRYPT_DER_BLOB pBlob;
+    unsigned char *pbDecoded, **rpbDecoded;
+    unsigned long cbDecoded, *rcbDecoded, index, length;
+    int ret;
+
+    ret = _libssh2_wincng_asn_decode(pbEncoded, cbEncoded,
+                                     X509_SEQUENCE_OF_ANY,
+                                     &pbDecoded, &cbDecoded);
+    if(!ret) {
+        length = ((PCRYPT_DATA_BLOB)pbDecoded)->cbData;
+
+        rpbDecoded = malloc(sizeof(PBYTE) * length);
+        if(rpbDecoded) {
+            rcbDecoded = malloc(sizeof(DWORD) * length);
+            if(rcbDecoded) {
+                for(index = 0; index < length; index++) {
+                    pBlob = &((PCRYPT_DER_BLOB)
+                              ((PCRYPT_DATA_BLOB)pbDecoded)->pbData)[index];
+                    ret = _libssh2_wincng_asn_decode_bn(pBlob->pbData,
+                                                        pBlob->cbData,
+                                                        &rpbDecoded[index],
+                                                        &rcbDecoded[index]);
+                    if(ret)
+                        break;
+                }
+
+                if(!ret) {
+                    *prpbDecoded = rpbDecoded;
+                    *prcbDecoded = rcbDecoded;
+                    *pcbCount = length;
+                }
+                else {
+                    for(length = 0; length < index; length++) {
+                        _libssh2_wincng_safe_free(rpbDecoded[length],
+                                                  rcbDecoded[length]);
+                        rpbDecoded[length] = NULL;
+                        rcbDecoded[length] = 0;
+                    }
+                    free(rpbDecoded);
+                    free(rcbDecoded);
+                }
+            }
+            else {
+                free(rpbDecoded);
+                ret = -1;
+            }
+        }
+        else {
+            ret = -1;
+        }
+
+        _libssh2_wincng_safe_free(pbDecoded, cbDecoded);
+    }
+
+    return ret;
+}
+#endif /* HAVE_LIBCRYPT32 */
+
+static unsigned long
+_libssh2_wincng_bn_size(const unsigned char *bignum,
+                        unsigned long length)
+{
+    unsigned long offset;
+
+    if(!bignum)
+        return 0;
+
+    length--;
+
+    offset = 0;
+    while(!(*(bignum + offset)) && (offset < length))
+        offset++;
+
+    length++;
+
+    return length - offset;
+}
+
+
+/*******************************************************************/
+/*
+ * Windows CNG backend: RSA functions
+ */
+
+int
+_libssh2_wincng_rsa_new(libssh2_rsa_ctx **rsa,
+                        const unsigned char *edata,
+                        unsigned long elen,
+                        const unsigned char *ndata,
+                        unsigned long nlen,
+                        const unsigned char *ddata,
+                        unsigned long dlen,
+                        const unsigned char *pdata,
+                        unsigned long plen,
+                        const unsigned char *qdata,
+                        unsigned long qlen,
+                        const unsigned char *e1data,
+                        unsigned long e1len,
+                        const unsigned char *e2data,
+                        unsigned long e2len,
+                        const unsigned char *coeffdata,
+                        unsigned long coefflen)
+{
+    BCRYPT_KEY_HANDLE hKey;
+    BCRYPT_RSAKEY_BLOB *rsakey;
+    LPCWSTR lpszBlobType;
+    unsigned char *key;
+    unsigned long keylen, offset, mlen, p1len = 0, p2len = 0;
+    int ret;
+
+    mlen = max(_libssh2_wincng_bn_size(ndata, nlen),
+               _libssh2_wincng_bn_size(ddata, dlen));
+    offset = sizeof(BCRYPT_RSAKEY_BLOB);
+    keylen = offset + elen + mlen;
+    if(ddata && dlen > 0) {
+        p1len = max(_libssh2_wincng_bn_size(pdata, plen),
+                    _libssh2_wincng_bn_size(e1data, e1len));
+        p2len = max(_libssh2_wincng_bn_size(qdata, qlen),
+                    _libssh2_wincng_bn_size(e2data, e2len));
+        keylen += p1len * 3 + p2len * 2 + mlen;
+    }
+
+    key = malloc(keylen);
+    if(!key) {
+        return -1;
+    }
+
+    memset(key, 0, keylen);
+
+
+    /* https://msdn.microsoft.com/library/windows/desktop/aa375531.aspx */
+    rsakey = (BCRYPT_RSAKEY_BLOB *)key;
+    rsakey->BitLength = mlen * 8;
+    rsakey->cbPublicExp = elen;
+    rsakey->cbModulus = mlen;
+
+    memcpy(key + offset, edata, elen);
+    offset += elen;
+
+    if(nlen < mlen)
+        memcpy(key + offset + mlen - nlen, ndata, nlen);
+    else
+        memcpy(key + offset, ndata + nlen - mlen, mlen);
+
+    if(ddata && dlen > 0) {
+        offset += mlen;
+
+        if(plen < p1len)
+            memcpy(key + offset + p1len - plen, pdata, plen);
+        else
+            memcpy(key + offset, pdata + plen - p1len, p1len);
+        offset += p1len;
+
+        if(qlen < p2len)
+            memcpy(key + offset + p2len - qlen, qdata, qlen);
+        else
+            memcpy(key + offset, qdata + qlen - p2len, p2len);
+        offset += p2len;
+
+        if(e1len < p1len)
+            memcpy(key + offset + p1len - e1len, e1data, e1len);
+        else
+            memcpy(key + offset, e1data + e1len - p1len, p1len);
+        offset += p1len;
+
+        if(e2len < p2len)
+            memcpy(key + offset + p2len - e2len, e2data, e2len);
+        else
+            memcpy(key + offset, e2data + e2len - p2len, p2len);
+        offset += p2len;
+
+        if(coefflen < p1len)
+            memcpy(key + offset + p1len - coefflen, coeffdata, coefflen);
+        else
+            memcpy(key + offset, coeffdata + coefflen - p1len, p1len);
+        offset += p1len;
+
+        if(dlen < mlen)
+            memcpy(key + offset + mlen - dlen, ddata, dlen);
+        else
+            memcpy(key + offset, ddata + dlen - mlen, mlen);
+
+        lpszBlobType = BCRYPT_RSAFULLPRIVATE_BLOB;
+        rsakey->Magic = BCRYPT_RSAFULLPRIVATE_MAGIC;
+        rsakey->cbPrime1 = p1len;
+        rsakey->cbPrime2 = p2len;
+    }
+    else {
+        lpszBlobType = BCRYPT_RSAPUBLIC_BLOB;
+        rsakey->Magic = BCRYPT_RSAPUBLIC_MAGIC;
+        rsakey->cbPrime1 = 0;
+        rsakey->cbPrime2 = 0;
+    }
+
+
+    ret = BCryptImportKeyPair(_libssh2_wincng.hAlgRSA, NULL, lpszBlobType,
+                              &hKey, key, keylen, 0);
+    if(!BCRYPT_SUCCESS(ret)) {
+        _libssh2_wincng_safe_free(key, keylen);
+        return -1;
+    }
+
+
+    *rsa = malloc(sizeof(libssh2_rsa_ctx));
+    if(!(*rsa)) {
+        BCryptDestroyKey(hKey);
+        _libssh2_wincng_safe_free(key, keylen);
+        return -1;
+    }
+
+    (*rsa)->hKey = hKey;
+    (*rsa)->pbKeyObject = key;
+    (*rsa)->cbKeyObject = keylen;
+
+    return 0;
+}
+
+#ifdef HAVE_LIBCRYPT32
+static int
+_libssh2_wincng_rsa_new_private_parse(libssh2_rsa_ctx **rsa,
+                                      LIBSSH2_SESSION *session,
+                                      unsigned char *pbEncoded,
+                                      unsigned long cbEncoded)
+{
+    BCRYPT_KEY_HANDLE hKey;
+    unsigned char *pbStructInfo;
+    unsigned long cbStructInfo;
+    int ret;
+
+    (void)session;
+
+    ret = _libssh2_wincng_asn_decode(pbEncoded, cbEncoded,
+                                     PKCS_RSA_PRIVATE_KEY,
+                                     &pbStructInfo, &cbStructInfo);
+
+    _libssh2_wincng_safe_free(pbEncoded, cbEncoded);
+
+    if(ret) {
+        return -1;
+    }
+
+
+    ret = BCryptImportKeyPair(_libssh2_wincng.hAlgRSA, NULL,
+                              LEGACY_RSAPRIVATE_BLOB, &hKey,
+                              pbStructInfo, cbStructInfo, 0);
+    if(!BCRYPT_SUCCESS(ret)) {
+        _libssh2_wincng_safe_free(pbStructInfo, cbStructInfo);
+        return -1;
+    }
+
+
+    *rsa = malloc(sizeof(libssh2_rsa_ctx));
+    if(!(*rsa)) {
+        BCryptDestroyKey(hKey);
+        _libssh2_wincng_safe_free(pbStructInfo, cbStructInfo);
+        return -1;
+    }
+
+    (*rsa)->hKey = hKey;
+    (*rsa)->pbKeyObject = pbStructInfo;
+    (*rsa)->cbKeyObject = cbStructInfo;
+
+    return 0;
+}
+#endif /* HAVE_LIBCRYPT32 */
+
+int
+_libssh2_wincng_rsa_new_private(libssh2_rsa_ctx **rsa,
+                                LIBSSH2_SESSION *session,
+                                const char *filename,
+                                const unsigned char *passphrase)
+{
+#ifdef HAVE_LIBCRYPT32
+    unsigned char *pbEncoded;
+    unsigned long cbEncoded;
+    int ret;
+
+    (void)session;
+
+    ret = _libssh2_wincng_load_private(session, filename,
+                                       (const char *)passphrase,
+                                       &pbEncoded, &cbEncoded, 1, 0);
+    if(ret) {
+        return -1;
+    }
+
+    return _libssh2_wincng_rsa_new_private_parse(rsa, session,
+                                                 pbEncoded, cbEncoded);
+#else
+    (void)rsa;
+    (void)filename;
+    (void)passphrase;
+
+    return _libssh2_error(session, LIBSSH2_ERROR_FILE,
+                          "Unable to load RSA key from private key file: "
+                          "Method unsupported in Windows CNG backend");
+#endif /* HAVE_LIBCRYPT32 */
+}
+
+int
+_libssh2_wincng_rsa_new_private_frommemory(libssh2_rsa_ctx **rsa,
+                                           LIBSSH2_SESSION *session,
+                                           const char *filedata,
+                                           size_t filedata_len,
+                                           unsigned const char *passphrase)
+{
+#ifdef HAVE_LIBCRYPT32
+    unsigned char *pbEncoded;
+    unsigned long cbEncoded;
+    int ret;
+
+    (void)session;
+
+    ret = _libssh2_wincng_load_private_memory(session, filedata, filedata_len,
+                                              (const char *)passphrase,
+                                              &pbEncoded, &cbEncoded, 1, 0);
+    if(ret) {
+        return -1;
+    }
+
+    return _libssh2_wincng_rsa_new_private_parse(rsa, session,
+                                                 pbEncoded, cbEncoded);
+#else
+    (void)rsa;
+    (void)filedata;
+    (void)filedata_len;
+    (void)passphrase;
+
+    return _libssh2_error(session, LIBSSH2_ERROR_METHOD_NOT_SUPPORTED,
+                          "Unable to extract private key from memory: "
+                          "Method unsupported in Windows CNG backend");
+#endif /* HAVE_LIBCRYPT32 */
+}
+
+int
+_libssh2_wincng_rsa_sha1_verify(libssh2_rsa_ctx *rsa,
+                                const unsigned char *sig,
+                                unsigned long sig_len,
+                                const unsigned char *m,
+                                unsigned long m_len)
+{
+    return _libssh2_wincng_key_sha1_verify(rsa, sig, sig_len, m, m_len,
+                                           BCRYPT_PAD_PKCS1);
+}
+
+int
+_libssh2_wincng_rsa_sha1_sign(LIBSSH2_SESSION *session,
+                              libssh2_rsa_ctx *rsa,
+                              const unsigned char *hash,
+                              size_t hash_len,
+                              unsigned char **signature,
+                              size_t *signature_len)
+{
+    BCRYPT_PKCS1_PADDING_INFO paddingInfo;
+    unsigned char *data, *sig;
+    unsigned long cbData, datalen, siglen;
+    int ret;
+
+    datalen = (unsigned long)hash_len;
+    data = malloc(datalen);
+    if(!data) {
+        return -1;
+    }
+
+    paddingInfo.pszAlgId = BCRYPT_SHA1_ALGORITHM;
+
+    memcpy(data, hash, datalen);
+
+    ret = BCryptSignHash(rsa->hKey, &paddingInfo,
+                         data, datalen, NULL, 0,
+                         &cbData, BCRYPT_PAD_PKCS1);
+    if(BCRYPT_SUCCESS(ret)) {
+        siglen = cbData;
+        sig = LIBSSH2_ALLOC(session, siglen);
+        if(sig) {
+            ret = BCryptSignHash(rsa->hKey, &paddingInfo,
+                                 data, datalen, sig, siglen,
+                                 &cbData, BCRYPT_PAD_PKCS1);
+            if(BCRYPT_SUCCESS(ret)) {
+                *signature_len = siglen;
+                *signature = sig;
+            }
+            else {
+                LIBSSH2_FREE(session, sig);
+            }
+        }
+        else
+            ret = STATUS_NO_MEMORY;
+    }
+
+    _libssh2_wincng_safe_free(data, datalen);
+
+    return BCRYPT_SUCCESS(ret) ? 0 : -1;
+}
+
+void
+_libssh2_wincng_rsa_free(libssh2_rsa_ctx *rsa)
+{
+    if(!rsa)
+        return;
+
+    BCryptDestroyKey(rsa->hKey);
+    rsa->hKey = NULL;
+
+    _libssh2_wincng_safe_free(rsa->pbKeyObject, rsa->cbKeyObject);
+    _libssh2_wincng_safe_free(rsa, sizeof(libssh2_rsa_ctx));
+}
+
+
+/*******************************************************************/
+/*
+ * Windows CNG backend: DSA functions
+ */
+
+#if LIBSSH2_DSA
+int
+_libssh2_wincng_dsa_new(libssh2_dsa_ctx **dsa,
+                        const unsigned char *pdata,
+                        unsigned long plen,
+                        const unsigned char *qdata,
+                        unsigned long qlen,
+                        const unsigned char *gdata,
+                        unsigned long glen,
+                        const unsigned char *ydata,
+                        unsigned long ylen,
+                        const unsigned char *xdata,
+                        unsigned long xlen)
+{
+    BCRYPT_KEY_HANDLE hKey;
+    BCRYPT_DSA_KEY_BLOB *dsakey;
+    LPCWSTR lpszBlobType;
+    unsigned char *key;
+    unsigned long keylen, offset, length;
+    int ret;
+
+    length = max(max(_libssh2_wincng_bn_size(pdata, plen),
+                     _libssh2_wincng_bn_size(gdata, glen)),
+                 _libssh2_wincng_bn_size(ydata, ylen));
+    offset = sizeof(BCRYPT_DSA_KEY_BLOB);
+    keylen = offset + length * 3;
+    if(xdata && xlen > 0)
+        keylen += 20;
+
+    key = malloc(keylen);
+    if(!key) {
+        return -1;
+    }
+
+    memset(key, 0, keylen);
+
+
+    /* https://msdn.microsoft.com/library/windows/desktop/aa833126.aspx */
+    dsakey = (BCRYPT_DSA_KEY_BLOB *)key;
+    dsakey->cbKey = length;
+
+    memset(dsakey->Count, -1, sizeof(dsakey->Count));
+    memset(dsakey->Seed, -1, sizeof(dsakey->Seed));
+
+    if(qlen < 20)
+        memcpy(dsakey->q + 20 - qlen, qdata, qlen);
+    else
+        memcpy(dsakey->q, qdata + qlen - 20, 20);
+
+    if(plen < length)
+        memcpy(key + offset + length - plen, pdata, plen);
+    else
+        memcpy(key + offset, pdata + plen - length, length);
+    offset += length;
+
+    if(glen < length)
+        memcpy(key + offset + length - glen, gdata, glen);
+    else
+        memcpy(key + offset, gdata + glen - length, length);
+    offset += length;
+
+    if(ylen < length)
+        memcpy(key + offset + length - ylen, ydata, ylen);
+    else
+        memcpy(key + offset, ydata + ylen - length, length);
+
+    if(xdata && xlen > 0) {
+        offset += length;
+
+        if(xlen < 20)
+            memcpy(key + offset + 20 - xlen, xdata, xlen);
+        else
+            memcpy(key + offset, xdata + xlen - 20, 20);
+
+        lpszBlobType = BCRYPT_DSA_PRIVATE_BLOB;
+        dsakey->dwMagic = BCRYPT_DSA_PRIVATE_MAGIC;
+    }
+    else {
+        lpszBlobType = BCRYPT_DSA_PUBLIC_BLOB;
+        dsakey->dwMagic = BCRYPT_DSA_PUBLIC_MAGIC;
+    }
+
+
+    ret = BCryptImportKeyPair(_libssh2_wincng.hAlgDSA, NULL, lpszBlobType,
+                              &hKey, key, keylen, 0);
+    if(!BCRYPT_SUCCESS(ret)) {
+        _libssh2_wincng_safe_free(key, keylen);
+        return -1;
+    }
+
+
+    *dsa = malloc(sizeof(libssh2_dsa_ctx));
+    if(!(*dsa)) {
+        BCryptDestroyKey(hKey);
+        _libssh2_wincng_safe_free(key, keylen);
+        return -1;
+    }
+
+    (*dsa)->hKey = hKey;
+    (*dsa)->pbKeyObject = key;
+    (*dsa)->cbKeyObject = keylen;
+
+    return 0;
+}
+
+#ifdef HAVE_LIBCRYPT32
+static int
+_libssh2_wincng_dsa_new_private_parse(libssh2_dsa_ctx **dsa,
+                                      LIBSSH2_SESSION *session,
+                                      unsigned char *pbEncoded,
+                                      unsigned long cbEncoded)
+{
+    unsigned char **rpbDecoded;
+    unsigned long *rcbDecoded, index, length;
+    int ret;
+
+    (void)session;
+
+    ret = _libssh2_wincng_asn_decode_bns(pbEncoded, cbEncoded,
+                                         &rpbDecoded, &rcbDecoded, &length);
+
+    _libssh2_wincng_safe_free(pbEncoded, cbEncoded);
+
+    if(ret) {
+        return -1;
+    }
+
+
+    if(length == 6) {
+        ret = _libssh2_wincng_dsa_new(dsa,
+                                      rpbDecoded[1], rcbDecoded[1],
+                                      rpbDecoded[2], rcbDecoded[2],
+                                      rpbDecoded[3], rcbDecoded[3],
+                                      rpbDecoded[4], rcbDecoded[4],
+                                      rpbDecoded[5], rcbDecoded[5]);
+    }
+    else {
+        ret = -1;
+    }
+
+    for(index = 0; index < length; index++) {
+        _libssh2_wincng_safe_free(rpbDecoded[index], rcbDecoded[index]);
+        rpbDecoded[index] = NULL;
+        rcbDecoded[index] = 0;
+    }
+
+    free(rpbDecoded);
+    free(rcbDecoded);
+
+    return ret;
+}
+#endif /* HAVE_LIBCRYPT32 */
+
+int
+_libssh2_wincng_dsa_new_private(libssh2_dsa_ctx **dsa,
+                                LIBSSH2_SESSION *session,
+                                const char *filename,
+                                const unsigned char *passphrase)
+{
+#ifdef HAVE_LIBCRYPT32
+    unsigned char *pbEncoded;
+    unsigned long cbEncoded;
+    int ret;
+
+    ret = _libssh2_wincng_load_private(session, filename,
+                                       (const char *)passphrase,
+                                       &pbEncoded, &cbEncoded, 0, 1);
+    if(ret) {
+        return -1;
+    }
+
+    return _libssh2_wincng_dsa_new_private_parse(dsa, session,
+                                                 pbEncoded, cbEncoded);
+#else
+    (void)dsa;
+    (void)filename;
+    (void)passphrase;
+
+    return _libssh2_error(session, LIBSSH2_ERROR_FILE,
+                          "Unable to load DSA key from private key file: "
+                          "Method unsupported in Windows CNG backend");
+#endif /* HAVE_LIBCRYPT32 */
+}
+
+int
+_libssh2_wincng_dsa_new_private_frommemory(libssh2_dsa_ctx **dsa,
+                                           LIBSSH2_SESSION *session,
+                                           const char *filedata,
+                                           size_t filedata_len,
+                                           unsigned const char *passphrase)
+{
+#ifdef HAVE_LIBCRYPT32
+    unsigned char *pbEncoded;
+    unsigned long cbEncoded;
+    int ret;
+
+    ret = _libssh2_wincng_load_private_memory(session, filedata, filedata_len,
+                                              (const char *)passphrase,
+                                              &pbEncoded, &cbEncoded, 0, 1);
+    if(ret) {
+        return -1;
+    }
+
+    return _libssh2_wincng_dsa_new_private_parse(dsa, session,
+                                                 pbEncoded, cbEncoded);
+#else
+    (void)dsa;
+    (void)filedata;
+    (void)filedata_len;
+    (void)passphrase;
+
+    return _libssh2_error(session, LIBSSH2_ERROR_METHOD_NOT_SUPPORTED,
+                          "Unable to extract private key from memory: "
+                          "Method unsupported in Windows CNG backend");
+#endif /* HAVE_LIBCRYPT32 */
+}
+
+int
+_libssh2_wincng_dsa_sha1_verify(libssh2_dsa_ctx *dsa,
+                                const unsigned char *sig_fixed,
+                                const unsigned char *m,
+                                unsigned long m_len)
+{
+    return _libssh2_wincng_key_sha1_verify(dsa, sig_fixed, 40, m, m_len, 0);
+}
+
+int
+_libssh2_wincng_dsa_sha1_sign(libssh2_dsa_ctx *dsa,
+                              const unsigned char *hash,
+                              unsigned long hash_len,
+                              unsigned char *sig_fixed)
+{
+    unsigned char *data, *sig;
+    unsigned long cbData, datalen, siglen;
+    int ret;
+
+    datalen = hash_len;
+    data = malloc(datalen);
+    if(!data) {
+        return -1;
+    }
+
+    memcpy(data, hash, datalen);
+
+    ret = BCryptSignHash(dsa->hKey, NULL, data, datalen,
+                         NULL, 0, &cbData, 0);
+    if(BCRYPT_SUCCESS(ret)) {
+        siglen = cbData;
+        if(siglen == 40) {
+            sig = malloc(siglen);
+            if(sig) {
+                ret = BCryptSignHash(dsa->hKey, NULL, data, datalen,
+                                     sig, siglen, &cbData, 0);
+                if(BCRYPT_SUCCESS(ret)) {
+                    memcpy(sig_fixed, sig, siglen);
+                }
+
+                _libssh2_wincng_safe_free(sig, siglen);
+            }
+            else
+                ret = STATUS_NO_MEMORY;
+        }
+        else
+            ret = STATUS_NO_MEMORY;
+    }
+
+    _libssh2_wincng_safe_free(data, datalen);
+
+    return BCRYPT_SUCCESS(ret) ? 0 : -1;
+}
+
+void
+_libssh2_wincng_dsa_free(libssh2_dsa_ctx *dsa)
+{
+    if(!dsa)
+        return;
+
+    BCryptDestroyKey(dsa->hKey);
+    dsa->hKey = NULL;
+
+    _libssh2_wincng_safe_free(dsa->pbKeyObject, dsa->cbKeyObject);
+    _libssh2_wincng_safe_free(dsa, sizeof(libssh2_dsa_ctx));
+}
+#endif
+
+
+/*******************************************************************/
+/*
+ * Windows CNG backend: Key functions
+ */
+
+#ifdef HAVE_LIBCRYPT32
+static unsigned long
+_libssh2_wincng_pub_priv_write(unsigned char *key,
+                               unsigned long offset,
+                               const unsigned char *bignum,
+                               const unsigned long length)
+{
+    _libssh2_htonu32(key + offset, length);
+    offset += 4;
+
+    memcpy(key + offset, bignum, length);
+    offset += length;
+
+    return offset;
+}
+
+static int
+_libssh2_wincng_pub_priv_keyfile_parse(LIBSSH2_SESSION *session,
+                                       unsigned char **method,
+                                       size_t *method_len,
+                                       unsigned char **pubkeydata,
+                                       size_t *pubkeydata_len,
+                                       unsigned char *pbEncoded,
+                                       unsigned long cbEncoded)
+{
+    unsigned char **rpbDecoded;
+    unsigned long *rcbDecoded;
+    unsigned char *key = NULL, *mth = NULL;
+    unsigned long keylen = 0, mthlen = 0;
+    unsigned long index, offset, length;
+    int ret;
+
+    ret = _libssh2_wincng_asn_decode_bns(pbEncoded, cbEncoded,
+                                         &rpbDecoded, &rcbDecoded, &length);
+
+    _libssh2_wincng_safe_free(pbEncoded, cbEncoded);
+
+    if(ret) {
+        return -1;
+    }
+
+
+    if(length == 9) { /* private RSA key */
+        mthlen = 7;
+        mth = LIBSSH2_ALLOC(session, mthlen);
+        if(mth) {
+            memcpy(mth, "ssh-rsa", mthlen);
+        }
+        else {
+            ret = -1;
+        }
+
+
+        keylen = 4 + mthlen + 4 + rcbDecoded[2] + 4 + rcbDecoded[1];
+        key = LIBSSH2_ALLOC(session, keylen);
+        if(key) {
+            offset = _libssh2_wincng_pub_priv_write(key, 0, mth, mthlen);
+
+            offset = _libssh2_wincng_pub_priv_write(key, offset,
+                                                    rpbDecoded[2],
+                                                    rcbDecoded[2]);
+
+            _libssh2_wincng_pub_priv_write(key, offset,
+                                           rpbDecoded[1],
+                                           rcbDecoded[1]);
+        }
+        else {
+            ret = -1;
+        }
+
+    }
+    else if(length == 6) { /* private DSA key */
+        mthlen = 7;
+        mth = LIBSSH2_ALLOC(session, mthlen);
+        if(mth) {
+            memcpy(mth, "ssh-dss", mthlen);
+        }
+        else {
+            ret = -1;
+        }
+
+        keylen = 4 + mthlen + 4 + rcbDecoded[1] + 4 + rcbDecoded[2]
+                            + 4 + rcbDecoded[3] + 4 + rcbDecoded[4];
+        key = LIBSSH2_ALLOC(session, keylen);
+        if(key) {
+            offset = _libssh2_wincng_pub_priv_write(key, 0, mth, mthlen);
+
+            offset = _libssh2_wincng_pub_priv_write(key, offset,
+                                                    rpbDecoded[1],
+                                                    rcbDecoded[1]);
+
+            offset = _libssh2_wincng_pub_priv_write(key, offset,
+                                                    rpbDecoded[2],
+                                                    rcbDecoded[2]);
+
+            offset = _libssh2_wincng_pub_priv_write(key, offset,
+                                                    rpbDecoded[3],
+                                                    rcbDecoded[3]);
+
+            _libssh2_wincng_pub_priv_write(key, offset,
+                                           rpbDecoded[4],
+                                           rcbDecoded[4]);
+        }
+        else {
+            ret = -1;
+        }
+
+    }
+    else {
+        ret = -1;
+    }
+
+
+    for(index = 0; index < length; index++) {
+        _libssh2_wincng_safe_free(rpbDecoded[index], rcbDecoded[index]);
+        rpbDecoded[index] = NULL;
+        rcbDecoded[index] = 0;
+    }
+
+    free(rpbDecoded);
+    free(rcbDecoded);
+
+
+    if(ret) {
+        if(mth)
+            LIBSSH2_FREE(session, mth);
+        if(key)
+            LIBSSH2_FREE(session, key);
+    }
+    else {
+        *method = mth;
+        *method_len = mthlen;
+        *pubkeydata = key;
+        *pubkeydata_len = keylen;
+    }
+
+    return ret;
+}
+#endif /* HAVE_LIBCRYPT32 */
+
+int
+_libssh2_wincng_pub_priv_keyfile(LIBSSH2_SESSION *session,
+                                 unsigned char **method,
+                                 size_t *method_len,
+                                 unsigned char **pubkeydata,
+                                 size_t *pubkeydata_len,
+                                 const char *privatekey,
+                                 const char *passphrase)
+{
+#ifdef HAVE_LIBCRYPT32
+    unsigned char *pbEncoded;
+    unsigned long cbEncoded;
+    int ret;
+
+    ret = _libssh2_wincng_load_private(session, privatekey, passphrase,
+                                       &pbEncoded, &cbEncoded, 1, 1);
+    if(ret) {
+        return -1;
+    }
+
+    return _libssh2_wincng_pub_priv_keyfile_parse(session, method, method_len,
+                                                  pubkeydata, pubkeydata_len,
+                                                  pbEncoded, cbEncoded);
+#else
+    (void)method;
+    (void)method_len;
+    (void)pubkeydata;
+    (void)pubkeydata_len;
+    (void)privatekey;
+    (void)passphrase;
+
+    return _libssh2_error(session, LIBSSH2_ERROR_FILE,
+                          "Unable to load public key from private key file: "
+                          "Method unsupported in Windows CNG backend");
+#endif /* HAVE_LIBCRYPT32 */
+}
+
+int
+_libssh2_wincng_pub_priv_keyfilememory(LIBSSH2_SESSION *session,
+                                       unsigned char **method,
+                                       size_t *method_len,
+                                       unsigned char **pubkeydata,
+                                       size_t *pubkeydata_len,
+                                       const char *privatekeydata,
+                                       size_t privatekeydata_len,
+                                       const char *passphrase)
+{
+#ifdef HAVE_LIBCRYPT32
+    unsigned char *pbEncoded;
+    unsigned long cbEncoded;
+    int ret;
+
+    ret = _libssh2_wincng_load_private_memory(session, privatekeydata,
+                                              privatekeydata_len, passphrase,
+                                              &pbEncoded, &cbEncoded, 1, 1);
+    if(ret) {
+        return -1;
+    }
+
+    return _libssh2_wincng_pub_priv_keyfile_parse(session, method, method_len,
+                                                  pubkeydata, pubkeydata_len,
+                                                  pbEncoded, cbEncoded);
+#else
+    (void)method;
+    (void)method_len;
+    (void)pubkeydata_len;
+    (void)pubkeydata;
+    (void)privatekeydata;
+    (void)privatekeydata_len;
+    (void)passphrase;
+
+    return _libssh2_error(session, LIBSSH2_ERROR_METHOD_NOT_SUPPORTED,
+               "Unable to extract public key from private key in memory: "
+               "Method unsupported in Windows CNG backend");
+#endif /* HAVE_LIBCRYPT32 */
+}
+
+/*******************************************************************/
+/*
+ * Windows CNG backend: Cipher functions
+ */
+
+int
+_libssh2_wincng_cipher_init(_libssh2_cipher_ctx *ctx,
+                            _libssh2_cipher_type(type),
+                            unsigned char *iv,
+                            unsigned char *secret,
+                            int encrypt)
+{
+    BCRYPT_KEY_HANDLE hKey;
+    BCRYPT_KEY_DATA_BLOB_HEADER *header;
+    unsigned char *pbKeyObject, *pbIV, *key, *pbCtr, *pbIVCopy;
+    unsigned long dwKeyObject, dwIV, dwCtrLength, dwBlockLength,
+                  cbData, keylen;
+    int ret;
+
+    (void)encrypt;
+
+    ret = BCryptGetProperty(*type.phAlg, BCRYPT_OBJECT_LENGTH,
+                            (unsigned char *)&dwKeyObject,
+                            sizeof(dwKeyObject),
+                            &cbData, 0);
+    if(!BCRYPT_SUCCESS(ret)) {
+        return -1;
+    }
+
+    ret = BCryptGetProperty(*type.phAlg, BCRYPT_BLOCK_LENGTH,
+                            (unsigned char *)&dwBlockLength,
+                            sizeof(dwBlockLength),
+                            &cbData, 0);
+    if(!BCRYPT_SUCCESS(ret)) {
+        return -1;
+    }
+
+    pbKeyObject = malloc(dwKeyObject);
+    if(!pbKeyObject) {
+        return -1;
+    }
+
+
+    keylen = sizeof(BCRYPT_KEY_DATA_BLOB_HEADER) + type.dwKeyLength;
+    key = malloc(keylen);
+    if(!key) {
+        free(pbKeyObject);
+        return -1;
+    }
+
+
+    header = (BCRYPT_KEY_DATA_BLOB_HEADER *)key;
+    header->dwMagic = BCRYPT_KEY_DATA_BLOB_MAGIC;
+    header->dwVersion = BCRYPT_KEY_DATA_BLOB_VERSION1;
+    header->cbKeyData = type.dwKeyLength;
+
+    memcpy(key + sizeof(BCRYPT_KEY_DATA_BLOB_HEADER),
+           secret, type.dwKeyLength);
+
+    ret = BCryptImportKey(*type.phAlg, NULL, BCRYPT_KEY_DATA_BLOB, &hKey,
+                          pbKeyObject, dwKeyObject, key, keylen, 0);
+
+    _libssh2_wincng_safe_free(key, keylen);
+
+    if(!BCRYPT_SUCCESS(ret)) {
+        _libssh2_wincng_safe_free(pbKeyObject, dwKeyObject);
+        return -1;
+    }
+
+    pbIV = NULL;
+    pbCtr = NULL;
+    dwIV = 0;
+    dwCtrLength = 0;
+
+    if(type.useIV || type.ctrMode) {
+        pbIVCopy = malloc(dwBlockLength);
+        if(!pbIVCopy) {
+            BCryptDestroyKey(hKey);
+            _libssh2_wincng_safe_free(pbKeyObject, dwKeyObject);
+            return -1;
+        }
+        memcpy(pbIVCopy, iv, dwBlockLength);
+
+        if(type.ctrMode) {
+            pbCtr = pbIVCopy;
+            dwCtrLength = dwBlockLength;
+        }
+        else if(type.useIV) {
+            pbIV = pbIVCopy;
+            dwIV = dwBlockLength;
+        }
+    }
+
+    ctx->hKey = hKey;
+    ctx->pbKeyObject = pbKeyObject;
+    ctx->pbIV = pbIV;
+    ctx->pbCtr = pbCtr;
+    ctx->dwKeyObject = dwKeyObject;
+    ctx->dwIV = dwIV;
+    ctx->dwBlockLength = dwBlockLength;
+    ctx->dwCtrLength = dwCtrLength;
+
+    return 0;
+}
+int
+_libssh2_wincng_cipher_crypt(_libssh2_cipher_ctx *ctx,
+                             _libssh2_cipher_type(type),
+                             int encrypt,
+                             unsigned char *block,
+                             size_t blocklen)
+{
+    unsigned char *pbOutput, *pbInput;
+    unsigned long cbOutput, cbInput;
+    int ret;
+
+    (void)type;
+
+    cbInput = (unsigned long)blocklen;
+
+    if(type.ctrMode) {
+        pbInput = ctx->pbCtr;
+    }
+    else {
+        pbInput = block;
+    }
+
+    if(encrypt || type.ctrMode) {
+        ret = BCryptEncrypt(ctx->hKey, pbInput, cbInput, NULL,
+                            ctx->pbIV, ctx->dwIV, NULL, 0, &cbOutput, 0);
+    }
+    else {
+        ret = BCryptDecrypt(ctx->hKey, pbInput, cbInput, NULL,
+                            ctx->pbIV, ctx->dwIV, NULL, 0, &cbOutput, 0);
+    }
+    if(BCRYPT_SUCCESS(ret)) {
+        pbOutput = malloc(cbOutput);
+        if(pbOutput) {
+            if(encrypt || type.ctrMode) {
+                ret = BCryptEncrypt(ctx->hKey, pbInput, cbInput, NULL,
+                                    ctx->pbIV, ctx->dwIV,
+                                    pbOutput, cbOutput, &cbOutput, 0);
+            }
+            else {
+                ret = BCryptDecrypt(ctx->hKey, pbInput, cbInput, NULL,
+                                    ctx->pbIV, ctx->dwIV,
+                                    pbOutput, cbOutput, &cbOutput, 0);
+            }
+            if(BCRYPT_SUCCESS(ret)) {
+                if(type.ctrMode) {
+                    _libssh2_xor_data(block, block, pbOutput, blocklen);
+                    _libssh2_aes_ctr_increment(ctx->pbCtr, ctx->dwCtrLength);
+                }
+                else {
+                    memcpy(block, pbOutput, cbOutput);
+                }
+            }
+
+            _libssh2_wincng_safe_free(pbOutput, cbOutput);
+        }
+        else
+            ret = STATUS_NO_MEMORY;
+    }
+
+    return BCRYPT_SUCCESS(ret) ? 0 : -1;
+}
+
+void
+_libssh2_wincng_cipher_dtor(_libssh2_cipher_ctx *ctx)
+{
+    BCryptDestroyKey(ctx->hKey);
+    ctx->hKey = NULL;
+
+    _libssh2_wincng_safe_free(ctx->pbKeyObject, ctx->dwKeyObject);
+    ctx->pbKeyObject = NULL;
+    ctx->dwKeyObject = 0;
+
+    _libssh2_wincng_safe_free(ctx->pbIV, ctx->dwBlockLength);
+    ctx->pbIV = NULL;
+    ctx->dwBlockLength = 0;
+
+    _libssh2_wincng_safe_free(ctx->pbCtr, ctx->dwCtrLength);
+    ctx->pbCtr = NULL;
+    ctx->dwCtrLength = 0;
+}
+
+
+/*******************************************************************/
+/*
+ * Windows CNG backend: BigNumber functions
+ */
+
+_libssh2_bn *
+_libssh2_wincng_bignum_init(void)
+{
+    _libssh2_bn *bignum;
+
+    bignum = (_libssh2_bn *)malloc(sizeof(_libssh2_bn));
+    if(bignum) {
+        bignum->bignum = NULL;
+        bignum->length = 0;
+    }
+
+    return bignum;
+}
+
+static int
+_libssh2_wincng_bignum_resize(_libssh2_bn *bn, unsigned long length)
+{
+    unsigned char *bignum;
+
+    if(!bn)
+        return -1;
+
+    if(length == bn->length)
+        return 0;
+
+#ifdef LIBSSH2_CLEAR_MEMORY
+    if(bn->bignum && bn->length > 0 && length < bn->length) {
+        SecureZeroMemory(bn->bignum + length, bn->length - length);
+    }
+#endif
+
+    bignum = realloc(bn->bignum, length);
+    if(!bignum)
+        return -1;
+
+    bn->bignum = bignum;
+    bn->length = length;
+
+    return 0;
+}
+
+static int
+_libssh2_wincng_bignum_rand(_libssh2_bn *rnd, int bits, int top, int bottom)
+{
+    unsigned char *bignum;
+    unsigned long length;
+
+    if(!rnd)
+        return -1;
+
+    length = (unsigned long)(ceil((float)bits / 8) * sizeof(unsigned char));
+    if(_libssh2_wincng_bignum_resize(rnd, length))
+        return -1;
+
+    bignum = rnd->bignum;
+
+    if(_libssh2_wincng_random(bignum, length))
+        return -1;
+
+    /* calculate significant bits in most significant byte */
+    bits %= 8;
+
+    /* fill most significant byte with zero padding */
+    bignum[0] &= (1 << (8 - bits)) - 1;
+
+    /* set some special last bits in most significant byte */
+    if(top == 0)
+        bignum[0] |= (1 << (7 - bits));
+    else if(top == 1)
+        bignum[0] |= (3 << (6 - bits));
+
+    /* make odd by setting first bit in least significant byte */
+    if(bottom)
+        bignum[length - 1] |= 1;
+
+    return 0;
+}
+
+static int
+_libssh2_wincng_bignum_mod_exp(_libssh2_bn *r,
+                               _libssh2_bn *a,
+                               _libssh2_bn *p,
+                               _libssh2_bn *m)
+{
+    BCRYPT_KEY_HANDLE hKey;
+    BCRYPT_RSAKEY_BLOB *rsakey;
+    unsigned char *key, *bignum;
+    unsigned long keylen, offset, length;
+    int ret;
+
+    if(!r || !a || !p || !m)
+        return -1;
+
+    offset = sizeof(BCRYPT_RSAKEY_BLOB);
+    keylen = offset + p->length + m->length;
+
+    key = malloc(keylen);
+    if(!key)
+        return -1;
+
+
+    /* https://msdn.microsoft.com/library/windows/desktop/aa375531.aspx */
+    rsakey = (BCRYPT_RSAKEY_BLOB *)key;
+    rsakey->Magic = BCRYPT_RSAPUBLIC_MAGIC;
+    rsakey->BitLength = m->length * 8;
+    rsakey->cbPublicExp = p->length;
+    rsakey->cbModulus = m->length;
+    rsakey->cbPrime1 = 0;
+    rsakey->cbPrime2 = 0;
+
+    memcpy(key + offset, p->bignum, p->length);
+    offset += p->length;
+
+    memcpy(key + offset, m->bignum, m->length);
+
+    ret = BCryptImportKeyPair(_libssh2_wincng.hAlgRSA, NULL,
+                              BCRYPT_RSAPUBLIC_BLOB, &hKey, key, keylen,
+                              BCRYPT_NO_KEY_VALIDATION);
+
+    if(BCRYPT_SUCCESS(ret)) {
+        ret = BCryptEncrypt(hKey, a->bignum, a->length, NULL, NULL, 0,
+                            NULL, 0, &length, BCRYPT_PAD_NONE);
+        if(BCRYPT_SUCCESS(ret)) {
+            if(!_libssh2_wincng_bignum_resize(r, length)) {
+                length = max(a->length, length);
+                bignum = malloc(length);
+                if(bignum) {
+                    offset = length - a->length;
+                    memset(bignum, 0, offset);
+                    memcpy(bignum + offset, a->bignum, a->length);
+
+                    ret = BCryptEncrypt(hKey, bignum, length, NULL, NULL, 0,
+                                        r->bignum, r->length, &offset,
+                                        BCRYPT_PAD_NONE);
+
+                    _libssh2_wincng_safe_free(bignum, length);
+
+                    if(BCRYPT_SUCCESS(ret)) {
+                        _libssh2_wincng_bignum_resize(r, offset);
+                    }
+                }
+                else
+                    ret = STATUS_NO_MEMORY;
+            }
+            else
+                ret = STATUS_NO_MEMORY;
+        }
+
+        BCryptDestroyKey(hKey);
+    }
+
+    _libssh2_wincng_safe_free(key, keylen);
+
+    return BCRYPT_SUCCESS(ret) ? 0 : -1;
+}
+
+int
+_libssh2_wincng_bignum_set_word(_libssh2_bn *bn, unsigned long word)
+{
+    unsigned long offset, number, bits, length;
+
+    if(!bn)
+        return -1;
+
+    bits = 0;
+    number = word;
+    while(number >>= 1)
+        bits++;
+
+    length = (unsigned long) (ceil(((double)(bits + 1)) / 8.0) *
+                              sizeof(unsigned char));
+    if(_libssh2_wincng_bignum_resize(bn, length))
+        return -1;
+
+    for(offset = 0; offset < length; offset++)
+        bn->bignum[offset] = (word >> (offset * 8)) & 0xff;
+
+    return 0;
+}
+
+unsigned long
+_libssh2_wincng_bignum_bits(const _libssh2_bn *bn)
+{
+    unsigned char number;
+    unsigned long offset, length, bits;
+
+    if(!bn)
+        return 0;
+
+    length = bn->length - 1;
+
+    offset = 0;
+    while(!(*(bn->bignum + offset)) && (offset < length))
+        offset++;
+
+    bits = (length - offset) * 8;
+    number = bn->bignum[offset];
+
+    while(number >>= 1)
+        bits++;
+
+    bits++;
+
+    return bits;
+}
+
+void
+_libssh2_wincng_bignum_from_bin(_libssh2_bn *bn, unsigned long len,
+                                const unsigned char *bin)
+{
+    unsigned char *bignum;
+    unsigned long offset, length, bits;
+
+    if(!bn || !bin || !len)
+        return;
+
+    if(_libssh2_wincng_bignum_resize(bn, len))
+        return;
+
+    memcpy(bn->bignum, bin, len);
+
+    bits = _libssh2_wincng_bignum_bits(bn);
+    length = (unsigned long) (ceil(((double)bits) / 8.0) *
+                              sizeof(unsigned char));
+
+    offset = bn->length - length;
+    if(offset > 0) {
+        memmove(bn->bignum, bn->bignum + offset, length);
+
+#ifdef LIBSSH2_CLEAR_MEMORY
+        SecureZeroMemory(bn->bignum + length, offset);
+#endif
+
+        bignum = realloc(bn->bignum, length);
+        if(bignum) {
+            bn->bignum = bignum;
+            bn->length = length;
+        }
+    }
+}
+
+void
+_libssh2_wincng_bignum_to_bin(const _libssh2_bn *bn, unsigned char *bin)
+{
+    if(bin && bn && bn->bignum && bn->length > 0) {
+        memcpy(bin, bn->bignum, bn->length);
+    }
+}
+
+void
+_libssh2_wincng_bignum_free(_libssh2_bn *bn)
+{
+    if(bn) {
+        if(bn->bignum) {
+            _libssh2_wincng_safe_free(bn->bignum, bn->length);
+            bn->bignum = NULL;
+        }
+        bn->length = 0;
+        _libssh2_wincng_safe_free(bn, sizeof(_libssh2_bn));
+    }
+}
+
+
+/*
+ * Windows CNG backend: Diffie-Hellman support.
+ */
+
+void
+_libssh2_dh_init(_libssh2_dh_ctx *dhctx)
+{
+    *dhctx = _libssh2_wincng_bignum_init();     /* Random from client */
+}
+
+int
+_libssh2_dh_key_pair(_libssh2_dh_ctx *dhctx, _libssh2_bn *public,
+                     _libssh2_bn *g, _libssh2_bn *p, int group_order)
+{
+    /* Generate x and e */
+    if(_libssh2_wincng_bignum_rand(*dhctx, group_order * 8 - 1, 0, -1))
+        return -1;
+    if(_libssh2_wincng_bignum_mod_exp(public, g, *dhctx, p))
+        return -1;
+    return 0;
+}
+
+int
+_libssh2_dh_secret(_libssh2_dh_ctx *dhctx, _libssh2_bn *secret,
+                   _libssh2_bn *f, _libssh2_bn *p)
+{
+    /* Compute the shared secret */
+    _libssh2_wincng_bignum_mod_exp(secret, f, *dhctx, p);
+    return 0;
+}
+
+void
+_libssh2_dh_dtor(_libssh2_dh_ctx *dhctx)
+{
+    _libssh2_wincng_bignum_free(*dhctx);
+    *dhctx = NULL;
+}
+
+#endif /* LIBSSH2_WINCNG */

+ 571 - 0
libssh2/libssh2/src/wincng.h

@@ -0,0 +1,571 @@
+/*
+ * Copyright (C) 2013-2015 Marc Hoersken <info@marc-hoersken.de>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms,
+ * with or without modification, are permitted provided
+ * that the following conditions are met:
+ *
+ *   Redistributions of source code must retain the above
+ *   copyright notice, this list of conditions and the
+ *   following disclaimer.
+ *
+ *   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.
+ *
+ *   Neither the name of the copyright holder nor the names
+ *   of any other contributors may be used to endorse or
+ *   promote products derived from this software without
+ *   specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+ * CONTRIBUTORS "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 COPYRIGHT OWNER OR
+ * CONTRIBUTORS 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.
+ */
+
+/* required for cross-compilation against the w64 mingw-runtime package */
+#if defined(_WIN32_WINNT) && (_WIN32_WINNT < 0x0600)
+#undef _WIN32_WINNT
+#endif
+#ifndef _WIN32_WINNT
+#define _WIN32_WINNT 0x0600
+#endif
+
+#include <windows.h>
+#include <bcrypt.h>
+
+
+#define LIBSSH2_MD5 1
+
+#define LIBSSH2_HMAC_RIPEMD 0
+#define LIBSSH2_HMAC_SHA256 1
+#define LIBSSH2_HMAC_SHA512 1
+
+#define LIBSSH2_AES 1
+#define LIBSSH2_AES_CTR 1
+#define LIBSSH2_BLOWFISH 0
+#define LIBSSH2_RC4 1
+#define LIBSSH2_CAST 0
+#define LIBSSH2_3DES 1
+
+#define LIBSSH2_RSA 1
+#define LIBSSH2_DSA 1
+#define LIBSSH2_ECDSA 0
+#define LIBSSH2_ED25519 0
+
+#define MD5_DIGEST_LENGTH 16
+#define SHA_DIGEST_LENGTH 20
+#define SHA256_DIGEST_LENGTH 32
+#define SHA512_DIGEST_LENGTH 64
+
+#define EC_MAX_POINT_LEN ((528 * 2 / 8) + 1)
+
+#if LIBSSH2_ECDSA
+#else
+#define _libssh2_ec_key void
+#endif
+
+/*******************************************************************/
+/*
+ * Windows CNG backend: Global context handles
+ */
+
+struct _libssh2_wincng_ctx {
+    BCRYPT_ALG_HANDLE hAlgRNG;
+    BCRYPT_ALG_HANDLE hAlgHashMD5;
+    BCRYPT_ALG_HANDLE hAlgHashSHA1;
+    BCRYPT_ALG_HANDLE hAlgHashSHA256;
+    BCRYPT_ALG_HANDLE hAlgHashSHA512;
+    BCRYPT_ALG_HANDLE hAlgHmacMD5;
+    BCRYPT_ALG_HANDLE hAlgHmacSHA1;
+    BCRYPT_ALG_HANDLE hAlgHmacSHA256;
+    BCRYPT_ALG_HANDLE hAlgHmacSHA512;
+    BCRYPT_ALG_HANDLE hAlgRSA;
+    BCRYPT_ALG_HANDLE hAlgDSA;
+    BCRYPT_ALG_HANDLE hAlgAES_CBC;
+    BCRYPT_ALG_HANDLE hAlgAES_ECB;
+    BCRYPT_ALG_HANDLE hAlgRC4_NA;
+    BCRYPT_ALG_HANDLE hAlg3DES_CBC;
+};
+
+struct _libssh2_wincng_ctx _libssh2_wincng;
+
+
+/*******************************************************************/
+/*
+ * Windows CNG backend: Generic functions
+ */
+
+void _libssh2_wincng_init(void);
+void _libssh2_wincng_free(void);
+
+#define libssh2_crypto_init() \
+  _libssh2_wincng_init()
+#define libssh2_crypto_exit() \
+  _libssh2_wincng_free()
+
+#define _libssh2_random(buf, len) \
+  _libssh2_wincng_random(buf, len)
+
+#define libssh2_prepare_iovec(vec, len)  /* Empty. */
+
+
+/*******************************************************************/
+/*
+ * Windows CNG backend: Hash structure
+ */
+
+typedef struct __libssh2_wincng_hash_ctx {
+    BCRYPT_HASH_HANDLE hHash;
+    unsigned char *pbHashObject;
+    unsigned long dwHashObject;
+    unsigned long cbHash;
+} _libssh2_wincng_hash_ctx;
+
+/*
+ * Windows CNG backend: Hash functions
+ */
+
+#define libssh2_sha1_ctx _libssh2_wincng_hash_ctx
+#define libssh2_sha1_init(ctx) \
+  (_libssh2_wincng_hash_init(ctx, _libssh2_wincng.hAlgHashSHA1, \
+                            SHA_DIGEST_LENGTH, NULL, 0) == 0)
+#define libssh2_sha1_update(ctx, data, datalen) \
+  _libssh2_wincng_hash_update(&ctx, (unsigned char *) data, datalen)
+#define libssh2_sha1_final(ctx, hash) \
+  _libssh2_wincng_hash_final(&ctx, hash)
+#define libssh2_sha1(data, datalen, hash) \
+  _libssh2_wincng_hash(data, datalen, _libssh2_wincng.hAlgHashSHA1, \
+                       hash, SHA_DIGEST_LENGTH)
+
+#define libssh2_sha256_ctx _libssh2_wincng_hash_ctx
+#define libssh2_sha256_init(ctx) \
+  (_libssh2_wincng_hash_init(ctx, _libssh2_wincng.hAlgHashSHA256, \
+                            SHA256_DIGEST_LENGTH, NULL, 0) == 0)
+#define libssh2_sha256_update(ctx, data, datalen) \
+  _libssh2_wincng_hash_update(&ctx, (unsigned char *) data, datalen)
+#define libssh2_sha256_final(ctx, hash) \
+  _libssh2_wincng_hash_final(&ctx, hash)
+#define libssh2_sha256(data, datalen, hash) \
+  _libssh2_wincng_hash(data, datalen, _libssh2_wincng.hAlgHashSHA256, \
+                       hash, SHA256_DIGEST_LENGTH)
+
+#define libssh2_sha512_ctx _libssh2_wincng_hash_ctx
+#define libssh2_sha512_init(ctx) \
+  (_libssh2_wincng_hash_init(ctx, _libssh2_wincng.hAlgHashSHA512, \
+                            SHA512_DIGEST_LENGTH, NULL, 0) == 0)
+#define libssh2_sha512_update(ctx, data, datalen) \
+  _libssh2_wincng_hash_update(&ctx, (unsigned char *) data, datalen)
+#define libssh2_sha512_final(ctx, hash) \
+  _libssh2_wincng_hash_final(&ctx, hash)
+#define libssh2_sha512(data, datalen, hash) \
+  _libssh2_wincng_hash(data, datalen, _libssh2_wincng.hAlgHashSHA512, \
+                       hash, SHA512_DIGEST_LENGTH)
+
+#define libssh2_md5_ctx _libssh2_wincng_hash_ctx
+#define libssh2_md5_init(ctx) \
+  (_libssh2_wincng_hash_init(ctx, _libssh2_wincng.hAlgHashMD5, \
+                            MD5_DIGEST_LENGTH, NULL, 0) == 0)
+#define libssh2_md5_update(ctx, data, datalen) \
+  _libssh2_wincng_hash_update(&ctx, (unsigned char *) data, datalen)
+#define libssh2_md5_final(ctx, hash) \
+  _libssh2_wincng_hash_final(&ctx, hash)
+#define libssh2_md5(data, datalen, hash) \
+  _libssh2_wincng_hash(data, datalen, _libssh2_wincng.hAlgHashMD5, \
+                       hash, MD5_DIGEST_LENGTH)
+
+/*
+ * Windows CNG backend: HMAC functions
+ */
+
+#define libssh2_hmac_ctx _libssh2_wincng_hash_ctx
+#define libssh2_hmac_ctx_init(ctx)
+#define libssh2_hmac_sha1_init(ctx, key, keylen) \
+  _libssh2_wincng_hash_init(ctx, _libssh2_wincng.hAlgHmacSHA1, \
+                            SHA_DIGEST_LENGTH, key, keylen)
+#define libssh2_hmac_md5_init(ctx, key, keylen) \
+  _libssh2_wincng_hash_init(ctx, _libssh2_wincng.hAlgHmacMD5, \
+                            MD5_DIGEST_LENGTH, key, keylen)
+#define libssh2_hmac_ripemd160_init(ctx, key, keylen)
+  /* not implemented */
+#define libssh2_hmac_sha256_init(ctx, key, keylen) \
+  _libssh2_wincng_hash_init(ctx, _libssh2_wincng.hAlgHmacSHA256, \
+                            SHA256_DIGEST_LENGTH, key, keylen)
+#define libssh2_hmac_sha512_init(ctx, key, keylen) \
+  _libssh2_wincng_hash_init(ctx, _libssh2_wincng.hAlgHmacSHA512, \
+                            SHA512_DIGEST_LENGTH, key, keylen)
+#define libssh2_hmac_update(ctx, data, datalen) \
+  _libssh2_wincng_hash_update(&ctx, (unsigned char *) data, datalen)
+#define libssh2_hmac_final(ctx, hash) \
+  _libssh2_wincng_hmac_final(&ctx, hash)
+#define libssh2_hmac_cleanup(ctx) \
+  _libssh2_wincng_hmac_cleanup(ctx)
+
+
+/*******************************************************************/
+/*
+ * Windows CNG backend: Key Context structure
+ */
+
+typedef struct __libssh2_wincng_key_ctx {
+    BCRYPT_KEY_HANDLE hKey;
+    unsigned char *pbKeyObject;
+    unsigned long cbKeyObject;
+} _libssh2_wincng_key_ctx;
+
+
+/*
+ * Windows CNG backend: RSA functions
+ */
+
+#define libssh2_rsa_ctx _libssh2_wincng_key_ctx
+#define _libssh2_rsa_new(rsactx, e, e_len, n, n_len, \
+                         d, d_len, p, p_len, q, q_len, \
+                         e1, e1_len, e2, e2_len, c, c_len) \
+  _libssh2_wincng_rsa_new(rsactx, e, e_len, n, n_len, \
+                          d, d_len, p, p_len, q, q_len, \
+                          e1, e1_len, e2, e2_len, c, c_len)
+#define _libssh2_rsa_new_private(rsactx, s, filename, passphrase) \
+  _libssh2_wincng_rsa_new_private(rsactx, s, filename, passphrase)
+#define _libssh2_rsa_new_private_frommemory(rsactx, s, filedata, \
+                                            filedata_len, passphrase) \
+  _libssh2_wincng_rsa_new_private_frommemory(rsactx, s, filedata, \
+                                             filedata_len, passphrase)
+#define _libssh2_rsa_sha1_sign(s, rsactx, hash, hash_len, sig, sig_len) \
+  _libssh2_wincng_rsa_sha1_sign(s, rsactx, hash, hash_len, sig, sig_len)
+#define _libssh2_rsa_sha1_verify(rsactx, sig, sig_len, m, m_len) \
+  _libssh2_wincng_rsa_sha1_verify(rsactx, sig, sig_len, m, m_len)
+#define _libssh2_rsa_free(rsactx) \
+  _libssh2_wincng_rsa_free(rsactx)
+
+/*
+ * Windows CNG backend: DSA functions
+ */
+
+#define libssh2_dsa_ctx _libssh2_wincng_key_ctx
+#define _libssh2_dsa_new(dsactx, p, p_len, q, q_len, \
+                         g, g_len, y, y_len, x, x_len) \
+  _libssh2_wincng_dsa_new(dsactx, p, p_len, q, q_len, \
+                          g, g_len, y, y_len, x, x_len)
+#define _libssh2_dsa_new_private(dsactx, s, filename, passphrase) \
+  _libssh2_wincng_dsa_new_private(dsactx, s, filename, passphrase)
+#define _libssh2_dsa_new_private_frommemory(dsactx, s, filedata, \
+                                            filedata_len, passphrase) \
+  _libssh2_wincng_dsa_new_private_frommemory(dsactx, s, filedata, \
+                                             filedata_len, passphrase)
+#define _libssh2_dsa_sha1_sign(dsactx, hash, hash_len, sig) \
+  _libssh2_wincng_dsa_sha1_sign(dsactx, hash, hash_len, sig)
+#define _libssh2_dsa_sha1_verify(dsactx, sig, m, m_len) \
+  _libssh2_wincng_dsa_sha1_verify(dsactx, sig, m, m_len)
+#define _libssh2_dsa_free(dsactx) \
+  _libssh2_wincng_dsa_free(dsactx)
+
+/*
+ * Windows CNG backend: Key functions
+ */
+
+#define _libssh2_pub_priv_keyfile(s, m, m_len, p, p_len, pk, pw) \
+  _libssh2_wincng_pub_priv_keyfile(s, m, m_len, p, p_len, pk, pw)
+#define _libssh2_pub_priv_keyfilememory(s, m, m_len, p, p_len, \
+                                                     pk, pk_len, pw) \
+  _libssh2_wincng_pub_priv_keyfilememory(s, m, m_len, p, p_len, \
+                                                      pk, pk_len, pw)
+
+
+/*******************************************************************/
+/*
+ * Windows CNG backend: Cipher Context structure
+ */
+
+struct _libssh2_wincng_cipher_ctx {
+    BCRYPT_KEY_HANDLE hKey;
+    unsigned char *pbKeyObject;
+    unsigned char *pbIV;
+    unsigned char *pbCtr;
+    unsigned long dwKeyObject;
+    unsigned long dwIV;
+    unsigned long dwBlockLength;
+    unsigned long dwCtrLength;
+};
+
+#define _libssh2_cipher_ctx struct _libssh2_wincng_cipher_ctx
+
+/*
+ * Windows CNG backend: Cipher Type structure
+ */
+
+struct _libssh2_wincng_cipher_type {
+    BCRYPT_ALG_HANDLE *phAlg;
+    unsigned long dwKeyLength;
+    int useIV;      /* TODO: Convert to bool when a C89 compatible bool type
+                       is defined */
+    int ctrMode;
+};
+
+#define _libssh2_cipher_type(type) struct _libssh2_wincng_cipher_type type
+
+#define _libssh2_cipher_aes256ctr { &_libssh2_wincng.hAlgAES_ECB, 32, 0, 1 }
+#define _libssh2_cipher_aes192ctr { &_libssh2_wincng.hAlgAES_ECB, 24, 0, 1 }
+#define _libssh2_cipher_aes128ctr { &_libssh2_wincng.hAlgAES_ECB, 16, 0, 1 }
+#define _libssh2_cipher_aes256 { &_libssh2_wincng.hAlgAES_CBC, 32, 1, 0 }
+#define _libssh2_cipher_aes192 { &_libssh2_wincng.hAlgAES_CBC, 24, 1, 0 }
+#define _libssh2_cipher_aes128 { &_libssh2_wincng.hAlgAES_CBC, 16, 1, 0 }
+#define _libssh2_cipher_arcfour { &_libssh2_wincng.hAlgRC4_NA, 16, 0, 0 }
+#define _libssh2_cipher_3des { &_libssh2_wincng.hAlg3DES_CBC, 24, 1, 0 }
+
+/*
+ * Windows CNG backend: Cipher functions
+ */
+
+#define _libssh2_cipher_init(ctx, type, iv, secret, encrypt) \
+  _libssh2_wincng_cipher_init(ctx, type, iv, secret, encrypt)
+#define _libssh2_cipher_crypt(ctx, type, encrypt, block, blocklen) \
+  _libssh2_wincng_cipher_crypt(ctx, type, encrypt, block, blocklen)
+#define _libssh2_cipher_dtor(ctx) \
+  _libssh2_wincng_cipher_dtor(ctx)
+
+/*******************************************************************/
+/*
+ * Windows CNG backend: BigNumber Context
+ */
+
+#define _libssh2_bn_ctx int /* not used */
+#define _libssh2_bn_ctx_new() 0 /* not used */
+#define _libssh2_bn_ctx_free(bnctx) ((void)0) /* not used */
+
+
+/*******************************************************************/
+/*
+ * Windows CNG backend: BigNumber structure
+ */
+
+struct _libssh2_wincng_bignum {
+    unsigned char *bignum;
+    unsigned long length;
+};
+
+#define _libssh2_bn struct _libssh2_wincng_bignum
+
+/*
+ * Windows CNG backend: BigNumber functions
+ */
+
+_libssh2_bn *_libssh2_wincng_bignum_init(void);
+
+#define _libssh2_bn_init() \
+  _libssh2_wincng_bignum_init()
+#define _libssh2_bn_init_from_bin() \
+  _libssh2_bn_init()
+#define _libssh2_bn_set_word(bn, word) \
+  _libssh2_wincng_bignum_set_word(bn, word)
+#define _libssh2_bn_from_bin(bn, len, bin) \
+  _libssh2_wincng_bignum_from_bin(bn, len, bin)
+#define _libssh2_bn_to_bin(bn, bin) \
+  _libssh2_wincng_bignum_to_bin(bn, bin)
+#define _libssh2_bn_bytes(bn) bn->length
+#define _libssh2_bn_bits(bn) \
+  _libssh2_wincng_bignum_bits(bn)
+#define _libssh2_bn_free(bn) \
+  _libssh2_wincng_bignum_free(bn)
+
+/*
+ * Windows CNG backend: Diffie-Hellman support
+ */
+
+#define _libssh2_dh_ctx struct _libssh2_wincng_bignum *
+#define libssh2_dh_init(dhctx) _libssh2_dh_init(dhctx)
+#define libssh2_dh_key_pair(dhctx, public, g, p, group_order, bnctx) \
+        _libssh2_dh_key_pair(dhctx, public, g, p, group_order)
+#define libssh2_dh_secret(dhctx, secret, f, p, bnctx) \
+        _libssh2_dh_secret(dhctx, secret, f, p)
+#define libssh2_dh_dtor(dhctx) _libssh2_dh_dtor(dhctx)
+
+/*******************************************************************/
+/*
+ * Windows CNG backend: forward declarations
+ */
+void _libssh2_wincng_init(void);
+void _libssh2_wincng_free(void);
+int _libssh2_wincng_random(void *buf, int len);
+
+int
+_libssh2_wincng_hash_init(_libssh2_wincng_hash_ctx *ctx,
+                          BCRYPT_ALG_HANDLE hAlg, unsigned long hashlen,
+                          unsigned char *key, unsigned long keylen);
+int
+_libssh2_wincng_hash_update(_libssh2_wincng_hash_ctx *ctx,
+                            const unsigned char *data, unsigned long datalen);
+int
+_libssh2_wincng_hash_final(_libssh2_wincng_hash_ctx *ctx,
+                           unsigned char *hash);
+int
+_libssh2_wincng_hash(unsigned char *data, unsigned long datalen,
+                     BCRYPT_ALG_HANDLE hAlg,
+                     unsigned char *hash, unsigned long hashlen);
+
+int
+_libssh2_wincng_hmac_final(_libssh2_wincng_hash_ctx *ctx,
+                           unsigned char *hash);
+void
+_libssh2_wincng_hmac_cleanup(_libssh2_wincng_hash_ctx *ctx);
+
+int
+_libssh2_wincng_key_sha1_verify(_libssh2_wincng_key_ctx *ctx,
+                                const unsigned char *sig,
+                                unsigned long sig_len,
+                                const unsigned char *m,
+                                unsigned long m_len,
+                                unsigned long flags);
+
+int
+_libssh2_wincng_rsa_new(libssh2_rsa_ctx **rsa,
+                        const unsigned char *edata,
+                        unsigned long elen,
+                        const unsigned char *ndata,
+                        unsigned long nlen,
+                        const unsigned char *ddata,
+                        unsigned long dlen,
+                        const unsigned char *pdata,
+                        unsigned long plen,
+                        const unsigned char *qdata,
+                        unsigned long qlen,
+                        const unsigned char *e1data,
+                        unsigned long e1len,
+                        const unsigned char *e2data,
+                        unsigned long e2len,
+                        const unsigned char *coeffdata,
+                        unsigned long coefflen);
+int
+_libssh2_wincng_rsa_new_private(libssh2_rsa_ctx **rsa,
+                                LIBSSH2_SESSION *session,
+                                const char *filename,
+                                const unsigned char *passphrase);
+int
+_libssh2_wincng_rsa_new_private_frommemory(libssh2_rsa_ctx **rsa,
+                                           LIBSSH2_SESSION *session,
+                                           const char *filedata,
+                                           size_t filedata_len,
+                                           unsigned const char *passphrase);
+int
+_libssh2_wincng_rsa_sha1_verify(libssh2_rsa_ctx *rsa,
+                                const unsigned char *sig,
+                                unsigned long sig_len,
+                                const unsigned char *m,
+                                unsigned long m_len);
+int
+_libssh2_wincng_rsa_sha1_sign(LIBSSH2_SESSION *session,
+                              libssh2_rsa_ctx *rsa,
+                              const unsigned char *hash,
+                              size_t hash_len,
+                              unsigned char **signature,
+                              size_t *signature_len);
+void
+_libssh2_wincng_rsa_free(libssh2_rsa_ctx *rsa);
+
+#if LIBSSH2_DSA
+int
+_libssh2_wincng_dsa_new(libssh2_dsa_ctx **dsa,
+                        const unsigned char *pdata,
+                        unsigned long plen,
+                        const unsigned char *qdata,
+                        unsigned long qlen,
+                        const unsigned char *gdata,
+                        unsigned long glen,
+                        const unsigned char *ydata,
+                        unsigned long ylen,
+                        const unsigned char *xdata,
+                        unsigned long xlen);
+int
+_libssh2_wincng_dsa_new_private(libssh2_dsa_ctx **dsa,
+                                LIBSSH2_SESSION *session,
+                                const char *filename,
+                                const unsigned char *passphrase);
+int
+_libssh2_wincng_dsa_new_private_frommemory(libssh2_dsa_ctx **dsa,
+                                           LIBSSH2_SESSION *session,
+                                           const char *filedata,
+                                           size_t filedata_len,
+                                           unsigned const char *passphrase);
+int
+_libssh2_wincng_dsa_sha1_verify(libssh2_dsa_ctx *dsa,
+                                const unsigned char *sig_fixed,
+                                const unsigned char *m,
+                                unsigned long m_len);
+int
+_libssh2_wincng_dsa_sha1_sign(libssh2_dsa_ctx *dsa,
+                              const unsigned char *hash,
+                              unsigned long hash_len,
+                              unsigned char *sig_fixed);
+void
+_libssh2_wincng_dsa_free(libssh2_dsa_ctx *dsa);
+#endif
+
+int
+_libssh2_wincng_pub_priv_keyfile(LIBSSH2_SESSION *session,
+                                 unsigned char **method,
+                                 size_t *method_len,
+                                 unsigned char **pubkeydata,
+                                 size_t *pubkeydata_len,
+                                 const char *privatekey,
+                                 const char *passphrase);
+int
+_libssh2_wincng_pub_priv_keyfilememory(LIBSSH2_SESSION *session,
+                                       unsigned char **method,
+                                       size_t *method_len,
+                                       unsigned char **pubkeydata,
+                                       size_t *pubkeydata_len,
+                                       const char *privatekeydata,
+                                       size_t privatekeydata_len,
+                                       const char *passphrase);
+
+int
+_libssh2_wincng_cipher_init(_libssh2_cipher_ctx *ctx,
+                            _libssh2_cipher_type(type),
+                            unsigned char *iv,
+                            unsigned char *secret,
+                            int encrypt);
+int
+_libssh2_wincng_cipher_crypt(_libssh2_cipher_ctx *ctx,
+                             _libssh2_cipher_type(type),
+                             int encrypt,
+                             unsigned char *block,
+                             size_t blocklen);
+void
+_libssh2_wincng_cipher_dtor(_libssh2_cipher_ctx *ctx);
+
+_libssh2_bn *
+_libssh2_wincng_bignum_init(void);
+int
+_libssh2_wincng_bignum_set_word(_libssh2_bn *bn, unsigned long word);
+unsigned long
+_libssh2_wincng_bignum_bits(const _libssh2_bn *bn);
+void
+_libssh2_wincng_bignum_from_bin(_libssh2_bn *bn, unsigned long len,
+                                const unsigned char *bin);
+void
+_libssh2_wincng_bignum_to_bin(const _libssh2_bn *bn, unsigned char *bin);
+void
+_libssh2_wincng_bignum_free(_libssh2_bn *bn);
+extern void
+_libssh2_dh_init(_libssh2_dh_ctx *dhctx);
+extern int
+_libssh2_dh_key_pair(_libssh2_dh_ctx *dhctx, _libssh2_bn *public,
+                     _libssh2_bn *g, _libssh2_bn *p, int group_order);
+extern int
+_libssh2_dh_secret(_libssh2_dh_ctx *dhctx, _libssh2_bn *secret,
+                   _libssh2_bn *f, _libssh2_bn *p);
+extern void
+_libssh2_dh_dtor(_libssh2_dh_ctx *dhctx);

TEMPAT SAMPAH
libssh2/openssl/bin/libeay32.dll


TEMPAT SAMPAH
libssh2/openssl/bin/openssl.exe


TEMPAT SAMPAH
libssh2/openssl/bin/ssleay32.dll


+ 149 - 0
libssh2/openssl/include/openssl/aes.h

@@ -0,0 +1,149 @@
+/* crypto/aes/aes.h */
+/* ====================================================================
+ * Copyright (c) 1998-2002 The OpenSSL 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. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    openssl-core@openssl.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED 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 OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS 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 HEADER_AES_H
+# define HEADER_AES_H
+
+# include <openssl/opensslconf.h>
+
+# ifdef OPENSSL_NO_AES
+#  error AES is disabled.
+# endif
+
+# include <stddef.h>
+
+# define AES_ENCRYPT     1
+# define AES_DECRYPT     0
+
+/*
+ * Because array size can't be a const in C, the following two are macros.
+ * Both sizes are in bytes.
+ */
+# define AES_MAXNR 14
+# define AES_BLOCK_SIZE 16
+
+#ifdef  __cplusplus
+extern "C" {
+#endif
+
+/* This should be a hidden type, but EVP requires that the size be known */
+struct aes_key_st {
+# ifdef AES_LONG
+    unsigned long rd_key[4 * (AES_MAXNR + 1)];
+# else
+    unsigned int rd_key[4 * (AES_MAXNR + 1)];
+# endif
+    int rounds;
+};
+typedef struct aes_key_st AES_KEY;
+
+const char *AES_options(void);
+
+int AES_set_encrypt_key(const unsigned char *userKey, const int bits,
+                        AES_KEY *key);
+int AES_set_decrypt_key(const unsigned char *userKey, const int bits,
+                        AES_KEY *key);
+
+int private_AES_set_encrypt_key(const unsigned char *userKey, const int bits,
+                                AES_KEY *key);
+int private_AES_set_decrypt_key(const unsigned char *userKey, const int bits,
+                                AES_KEY *key);
+
+void AES_encrypt(const unsigned char *in, unsigned char *out,
+                 const AES_KEY *key);
+void AES_decrypt(const unsigned char *in, unsigned char *out,
+                 const AES_KEY *key);
+
+void AES_ecb_encrypt(const unsigned char *in, unsigned char *out,
+                     const AES_KEY *key, const int enc);
+void AES_cbc_encrypt(const unsigned char *in, unsigned char *out,
+                     size_t length, const AES_KEY *key,
+                     unsigned char *ivec, const int enc);
+void AES_cfb128_encrypt(const unsigned char *in, unsigned char *out,
+                        size_t length, const AES_KEY *key,
+                        unsigned char *ivec, int *num, const int enc);
+void AES_cfb1_encrypt(const unsigned char *in, unsigned char *out,
+                      size_t length, const AES_KEY *key,
+                      unsigned char *ivec, int *num, const int enc);
+void AES_cfb8_encrypt(const unsigned char *in, unsigned char *out,
+                      size_t length, const AES_KEY *key,
+                      unsigned char *ivec, int *num, const int enc);
+void AES_ofb128_encrypt(const unsigned char *in, unsigned char *out,
+                        size_t length, const AES_KEY *key,
+                        unsigned char *ivec, int *num);
+void AES_ctr128_encrypt(const unsigned char *in, unsigned char *out,
+                        size_t length, const AES_KEY *key,
+                        unsigned char ivec[AES_BLOCK_SIZE],
+                        unsigned char ecount_buf[AES_BLOCK_SIZE],
+                        unsigned int *num);
+/* NB: the IV is _two_ blocks long */
+void AES_ige_encrypt(const unsigned char *in, unsigned char *out,
+                     size_t length, const AES_KEY *key,
+                     unsigned char *ivec, const int enc);
+/* NB: the IV is _four_ blocks long */
+void AES_bi_ige_encrypt(const unsigned char *in, unsigned char *out,
+                        size_t length, const AES_KEY *key,
+                        const AES_KEY *key2, const unsigned char *ivec,
+                        const int enc);
+
+int AES_wrap_key(AES_KEY *key, const unsigned char *iv,
+                 unsigned char *out,
+                 const unsigned char *in, unsigned int inlen);
+int AES_unwrap_key(AES_KEY *key, const unsigned char *iv,
+                   unsigned char *out,
+                   const unsigned char *in, unsigned int inlen);
+
+
+#ifdef  __cplusplus
+}
+#endif
+
+#endif                          /* !HEADER_AES_H */

+ 129 - 0
libssh2/openssl/include/openssl/applink.c

@@ -0,0 +1,129 @@
+#define APPLINK_STDIN   1
+#define APPLINK_STDOUT  2
+#define APPLINK_STDERR  3
+#define APPLINK_FPRINTF 4
+#define APPLINK_FGETS   5
+#define APPLINK_FREAD   6
+#define APPLINK_FWRITE  7
+#define APPLINK_FSETMOD 8
+#define APPLINK_FEOF    9
+#define APPLINK_FCLOSE  10      /* should not be used */
+
+#define APPLINK_FOPEN   11      /* solely for completeness */
+#define APPLINK_FSEEK   12
+#define APPLINK_FTELL   13
+#define APPLINK_FFLUSH  14
+#define APPLINK_FERROR  15
+#define APPLINK_CLEARERR 16
+#define APPLINK_FILENO  17      /* to be used with below */
+
+#define APPLINK_OPEN    18      /* formally can't be used, as flags can vary */
+#define APPLINK_READ    19
+#define APPLINK_WRITE   20
+#define APPLINK_LSEEK   21
+#define APPLINK_CLOSE   22
+#define APPLINK_MAX     22      /* always same as last macro */
+
+#ifndef APPMACROS_ONLY
+# include <stdio.h>
+# include <io.h>
+# include <fcntl.h>
+
+static void *app_stdin(void)
+{
+    return stdin;
+}
+
+static void *app_stdout(void)
+{
+    return stdout;
+}
+
+static void *app_stderr(void)
+{
+    return stderr;
+}
+
+static int app_feof(FILE *fp)
+{
+    return feof(fp);
+}
+
+static int app_ferror(FILE *fp)
+{
+    return ferror(fp);
+}
+
+static void app_clearerr(FILE *fp)
+{
+    clearerr(fp);
+}
+
+static int app_fileno(FILE *fp)
+{
+    return _fileno(fp);
+}
+
+static int app_fsetmod(FILE *fp, char mod)
+{
+    return _setmode(_fileno(fp), mod == 'b' ? _O_BINARY : _O_TEXT);
+}
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+__declspec(dllexport)
+void **
+# if defined(__BORLANDC__)
+/*
+ * __stdcall appears to be the only way to get the name
+ * decoration right with Borland C. Otherwise it works
+ * purely incidentally, as we pass no parameters.
+ */
+ __stdcall
+# else
+ __cdecl
+# endif
+OPENSSL_Applink(void)
+{
+    static int once = 1;
+    static void *OPENSSL_ApplinkTable[APPLINK_MAX + 1] =
+        { (void *)APPLINK_MAX };
+
+    if (once) {
+        OPENSSL_ApplinkTable[APPLINK_STDIN] = app_stdin;
+        OPENSSL_ApplinkTable[APPLINK_STDOUT] = app_stdout;
+        OPENSSL_ApplinkTable[APPLINK_STDERR] = app_stderr;
+        OPENSSL_ApplinkTable[APPLINK_FPRINTF] = fprintf;
+        OPENSSL_ApplinkTable[APPLINK_FGETS] = fgets;
+        OPENSSL_ApplinkTable[APPLINK_FREAD] = fread;
+        OPENSSL_ApplinkTable[APPLINK_FWRITE] = fwrite;
+        OPENSSL_ApplinkTable[APPLINK_FSETMOD] = app_fsetmod;
+        OPENSSL_ApplinkTable[APPLINK_FEOF] = app_feof;
+        OPENSSL_ApplinkTable[APPLINK_FCLOSE] = fclose;
+
+        OPENSSL_ApplinkTable[APPLINK_FOPEN] = fopen;
+        OPENSSL_ApplinkTable[APPLINK_FSEEK] = fseek;
+        OPENSSL_ApplinkTable[APPLINK_FTELL] = ftell;
+        OPENSSL_ApplinkTable[APPLINK_FFLUSH] = fflush;
+        OPENSSL_ApplinkTable[APPLINK_FERROR] = app_ferror;
+        OPENSSL_ApplinkTable[APPLINK_CLEARERR] = app_clearerr;
+        OPENSSL_ApplinkTable[APPLINK_FILENO] = app_fileno;
+
+        OPENSSL_ApplinkTable[APPLINK_OPEN] = _open;
+        OPENSSL_ApplinkTable[APPLINK_READ] = _read;
+        OPENSSL_ApplinkTable[APPLINK_WRITE] = _write;
+        OPENSSL_ApplinkTable[APPLINK_LSEEK] = _lseek;
+        OPENSSL_ApplinkTable[APPLINK_CLOSE] = _close;
+
+        once = 0;
+    }
+
+    return OPENSSL_ApplinkTable;
+}
+
+#ifdef __cplusplus
+}
+#endif
+#endif

+ 1424 - 0
libssh2/openssl/include/openssl/asn1.h

@@ -0,0 +1,1424 @@
+/* crypto/asn1/asn1.h */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * 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 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. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    "This product includes cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``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 AUTHOR OR CONTRIBUTORS 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.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+#ifndef HEADER_ASN1_H
+# define HEADER_ASN1_H
+
+# include <time.h>
+# include <openssl/e_os2.h>
+# ifndef OPENSSL_NO_BIO
+#  include <openssl/bio.h>
+# endif
+# include <openssl/stack.h>
+# include <openssl/safestack.h>
+
+# include <openssl/symhacks.h>
+
+# include <openssl/ossl_typ.h>
+# ifndef OPENSSL_NO_DEPRECATED
+#  include <openssl/bn.h>
+# endif
+
+# ifdef OPENSSL_BUILD_SHLIBCRYPTO
+#  undef OPENSSL_EXTERN
+#  define OPENSSL_EXTERN OPENSSL_EXPORT
+# endif
+
+#ifdef  __cplusplus
+extern "C" {
+#endif
+
+# define V_ASN1_UNIVERSAL                0x00
+# define V_ASN1_APPLICATION              0x40
+# define V_ASN1_CONTEXT_SPECIFIC         0x80
+# define V_ASN1_PRIVATE                  0xc0
+
+# define V_ASN1_CONSTRUCTED              0x20
+# define V_ASN1_PRIMITIVE_TAG            0x1f
+# define V_ASN1_PRIMATIVE_TAG            0x1f
+
+# define V_ASN1_APP_CHOOSE               -2/* let the recipient choose */
+# define V_ASN1_OTHER                    -3/* used in ASN1_TYPE */
+# define V_ASN1_ANY                      -4/* used in ASN1 template code */
+
+# define V_ASN1_NEG                      0x100/* negative flag */
+
+# define V_ASN1_UNDEF                    -1
+# define V_ASN1_EOC                      0
+# define V_ASN1_BOOLEAN                  1 /**/
+# define V_ASN1_INTEGER                  2
+# define V_ASN1_NEG_INTEGER              (2 | V_ASN1_NEG)
+# define V_ASN1_BIT_STRING               3
+# define V_ASN1_OCTET_STRING             4
+# define V_ASN1_NULL                     5
+# define V_ASN1_OBJECT                   6
+# define V_ASN1_OBJECT_DESCRIPTOR        7
+# define V_ASN1_EXTERNAL                 8
+# define V_ASN1_REAL                     9
+# define V_ASN1_ENUMERATED               10
+# define V_ASN1_NEG_ENUMERATED           (10 | V_ASN1_NEG)
+# define V_ASN1_UTF8STRING               12
+# define V_ASN1_SEQUENCE                 16
+# define V_ASN1_SET                      17
+# define V_ASN1_NUMERICSTRING            18 /**/
+# define V_ASN1_PRINTABLESTRING          19
+# define V_ASN1_T61STRING                20
+# define V_ASN1_TELETEXSTRING            20/* alias */
+# define V_ASN1_VIDEOTEXSTRING           21 /**/
+# define V_ASN1_IA5STRING                22
+# define V_ASN1_UTCTIME                  23
+# define V_ASN1_GENERALIZEDTIME          24 /**/
+# define V_ASN1_GRAPHICSTRING            25 /**/
+# define V_ASN1_ISO64STRING              26 /**/
+# define V_ASN1_VISIBLESTRING            26/* alias */
+# define V_ASN1_GENERALSTRING            27 /**/
+# define V_ASN1_UNIVERSALSTRING          28 /**/
+# define V_ASN1_BMPSTRING                30
+/* For use with d2i_ASN1_type_bytes() */
+# define B_ASN1_NUMERICSTRING    0x0001
+# define B_ASN1_PRINTABLESTRING  0x0002
+# define B_ASN1_T61STRING        0x0004
+# define B_ASN1_TELETEXSTRING    0x0004
+# define B_ASN1_VIDEOTEXSTRING   0x0008
+# define B_ASN1_IA5STRING        0x0010
+# define B_ASN1_GRAPHICSTRING    0x0020
+# define B_ASN1_ISO64STRING      0x0040
+# define B_ASN1_VISIBLESTRING    0x0040
+# define B_ASN1_GENERALSTRING    0x0080
+# define B_ASN1_UNIVERSALSTRING  0x0100
+# define B_ASN1_OCTET_STRING     0x0200
+# define B_ASN1_BIT_STRING       0x0400
+# define B_ASN1_BMPSTRING        0x0800
+# define B_ASN1_UNKNOWN          0x1000
+# define B_ASN1_UTF8STRING       0x2000
+# define B_ASN1_UTCTIME          0x4000
+# define B_ASN1_GENERALIZEDTIME  0x8000
+# define B_ASN1_SEQUENCE         0x10000
+/* For use with ASN1_mbstring_copy() */
+# define MBSTRING_FLAG           0x1000
+# define MBSTRING_UTF8           (MBSTRING_FLAG)
+# define MBSTRING_ASC            (MBSTRING_FLAG|1)
+# define MBSTRING_BMP            (MBSTRING_FLAG|2)
+# define MBSTRING_UNIV           (MBSTRING_FLAG|4)
+# define SMIME_OLDMIME           0x400
+# define SMIME_CRLFEOL           0x800
+# define SMIME_STREAM            0x1000
+    struct X509_algor_st;
+DECLARE_STACK_OF(X509_ALGOR)
+
+# define DECLARE_ASN1_SET_OF(type)/* filled in by mkstack.pl */
+# define IMPLEMENT_ASN1_SET_OF(type)/* nothing, no longer needed */
+
+/*
+ * We MUST make sure that, except for constness, asn1_ctx_st and
+ * asn1_const_ctx are exactly the same.  Fortunately, as soon as the old ASN1
+ * parsing macros are gone, we can throw this away as well...
+ */
+typedef struct asn1_ctx_st {
+    unsigned char *p;           /* work char pointer */
+    int eos;                    /* end of sequence read for indefinite
+                                 * encoding */
+    int error;                  /* error code to use when returning an error */
+    int inf;                    /* constructed if 0x20, indefinite is 0x21 */
+    int tag;                    /* tag from last 'get object' */
+    int xclass;                 /* class from last 'get object' */
+    long slen;                  /* length of last 'get object' */
+    unsigned char *max;         /* largest value of p allowed */
+    unsigned char *q;           /* temporary variable */
+    unsigned char **pp;         /* variable */
+    int line;                   /* used in error processing */
+} ASN1_CTX;
+
+typedef struct asn1_const_ctx_st {
+    const unsigned char *p;     /* work char pointer */
+    int eos;                    /* end of sequence read for indefinite
+                                 * encoding */
+    int error;                  /* error code to use when returning an error */
+    int inf;                    /* constructed if 0x20, indefinite is 0x21 */
+    int tag;                    /* tag from last 'get object' */
+    int xclass;                 /* class from last 'get object' */
+    long slen;                  /* length of last 'get object' */
+    const unsigned char *max;   /* largest value of p allowed */
+    const unsigned char *q;     /* temporary variable */
+    const unsigned char **pp;   /* variable */
+    int line;                   /* used in error processing */
+} ASN1_const_CTX;
+
+/*
+ * These are used internally in the ASN1_OBJECT to keep track of whether the
+ * names and data need to be free()ed
+ */
+# define ASN1_OBJECT_FLAG_DYNAMIC         0x01/* internal use */
+# define ASN1_OBJECT_FLAG_CRITICAL        0x02/* critical x509v3 object id */
+# define ASN1_OBJECT_FLAG_DYNAMIC_STRINGS 0x04/* internal use */
+# define ASN1_OBJECT_FLAG_DYNAMIC_DATA    0x08/* internal use */
+struct asn1_object_st {
+    const char *sn, *ln;
+    int nid;
+    int length;
+    const unsigned char *data;  /* data remains const after init */
+    int flags;                  /* Should we free this one */
+};
+
+# define ASN1_STRING_FLAG_BITS_LEFT 0x08/* Set if 0x07 has bits left value */
+/*
+ * This indicates that the ASN1_STRING is not a real value but just a place
+ * holder for the location where indefinite length constructed data should be
+ * inserted in the memory buffer
+ */
+# define ASN1_STRING_FLAG_NDEF 0x010
+
+/*
+ * This flag is used by the CMS code to indicate that a string is not
+ * complete and is a place holder for content when it had all been accessed.
+ * The flag will be reset when content has been written to it.
+ */
+
+# define ASN1_STRING_FLAG_CONT 0x020
+/*
+ * This flag is used by ASN1 code to indicate an ASN1_STRING is an MSTRING
+ * type.
+ */
+# define ASN1_STRING_FLAG_MSTRING 0x040
+/* This is the base type that holds just about everything :-) */
+struct asn1_string_st {
+    int length;
+    int type;
+    unsigned char *data;
+    /*
+     * The value of the following field depends on the type being held.  It
+     * is mostly being used for BIT_STRING so if the input data has a
+     * non-zero 'unused bits' value, it will be handled correctly
+     */
+    long flags;
+};
+
+/*
+ * ASN1_ENCODING structure: this is used to save the received encoding of an
+ * ASN1 type. This is useful to get round problems with invalid encodings
+ * which can break signatures.
+ */
+
+typedef struct ASN1_ENCODING_st {
+    unsigned char *enc;         /* DER encoding */
+    long len;                   /* Length of encoding */
+    int modified;               /* set to 1 if 'enc' is invalid */
+} ASN1_ENCODING;
+
+/* Used with ASN1 LONG type: if a long is set to this it is omitted */
+# define ASN1_LONG_UNDEF 0x7fffffffL
+
+# define STABLE_FLAGS_MALLOC     0x01
+# define STABLE_NO_MASK          0x02
+# define DIRSTRING_TYPE  \
+ (B_ASN1_PRINTABLESTRING|B_ASN1_T61STRING|B_ASN1_BMPSTRING|B_ASN1_UTF8STRING)
+# define PKCS9STRING_TYPE (DIRSTRING_TYPE|B_ASN1_IA5STRING)
+
+typedef struct asn1_string_table_st {
+    int nid;
+    long minsize;
+    long maxsize;
+    unsigned long mask;
+    unsigned long flags;
+} ASN1_STRING_TABLE;
+
+DECLARE_STACK_OF(ASN1_STRING_TABLE)
+
+/* size limits: this stuff is taken straight from RFC2459 */
+
+# define ub_name                         32768
+# define ub_common_name                  64
+# define ub_locality_name                128
+# define ub_state_name                   128
+# define ub_organization_name            64
+# define ub_organization_unit_name       64
+# define ub_title                        64
+# define ub_email_address                128
+
+/*
+ * Declarations for template structures: for full definitions see asn1t.h
+ */
+typedef struct ASN1_TEMPLATE_st ASN1_TEMPLATE;
+typedef struct ASN1_TLC_st ASN1_TLC;
+/* This is just an opaque pointer */
+typedef struct ASN1_VALUE_st ASN1_VALUE;
+
+/* Declare ASN1 functions: the implement macro in in asn1t.h */
+
+# define DECLARE_ASN1_FUNCTIONS(type) DECLARE_ASN1_FUNCTIONS_name(type, type)
+
+# define DECLARE_ASN1_ALLOC_FUNCTIONS(type) \
+        DECLARE_ASN1_ALLOC_FUNCTIONS_name(type, type)
+
+# define DECLARE_ASN1_FUNCTIONS_name(type, name) \
+        DECLARE_ASN1_ALLOC_FUNCTIONS_name(type, name) \
+        DECLARE_ASN1_ENCODE_FUNCTIONS(type, name, name)
+
+# define DECLARE_ASN1_FUNCTIONS_fname(type, itname, name) \
+        DECLARE_ASN1_ALLOC_FUNCTIONS_name(type, name) \
+        DECLARE_ASN1_ENCODE_FUNCTIONS(type, itname, name)
+
+# define DECLARE_ASN1_ENCODE_FUNCTIONS(type, itname, name) \
+        type *d2i_##name(type **a, const unsigned char **in, long len); \
+        int i2d_##name(type *a, unsigned char **out); \
+        DECLARE_ASN1_ITEM(itname)
+
+# define DECLARE_ASN1_ENCODE_FUNCTIONS_const(type, name) \
+        type *d2i_##name(type **a, const unsigned char **in, long len); \
+        int i2d_##name(const type *a, unsigned char **out); \
+        DECLARE_ASN1_ITEM(name)
+
+# define DECLARE_ASN1_NDEF_FUNCTION(name) \
+        int i2d_##name##_NDEF(name *a, unsigned char **out);
+
+# define DECLARE_ASN1_FUNCTIONS_const(name) \
+        DECLARE_ASN1_ALLOC_FUNCTIONS(name) \
+        DECLARE_ASN1_ENCODE_FUNCTIONS_const(name, name)
+
+# define DECLARE_ASN1_ALLOC_FUNCTIONS_name(type, name) \
+        type *name##_new(void); \
+        void name##_free(type *a);
+
+# define DECLARE_ASN1_PRINT_FUNCTION(stname) \
+        DECLARE_ASN1_PRINT_FUNCTION_fname(stname, stname)
+
+# define DECLARE_ASN1_PRINT_FUNCTION_fname(stname, fname) \
+        int fname##_print_ctx(BIO *out, stname *x, int indent, \
+                                         const ASN1_PCTX *pctx);
+
+# define D2I_OF(type) type *(*)(type **,const unsigned char **,long)
+# define I2D_OF(type) int (*)(type *,unsigned char **)
+# define I2D_OF_const(type) int (*)(const type *,unsigned char **)
+
+# define CHECKED_D2I_OF(type, d2i) \
+    ((d2i_of_void*) (1 ? d2i : ((D2I_OF(type))0)))
+# define CHECKED_I2D_OF(type, i2d) \
+    ((i2d_of_void*) (1 ? i2d : ((I2D_OF(type))0)))
+# define CHECKED_NEW_OF(type, xnew) \
+    ((void *(*)(void)) (1 ? xnew : ((type *(*)(void))0)))
+# define CHECKED_PTR_OF(type, p) \
+    ((void*) (1 ? p : (type*)0))
+# define CHECKED_PPTR_OF(type, p) \
+    ((void**) (1 ? p : (type**)0))
+
+# define TYPEDEF_D2I_OF(type) typedef type *d2i_of_##type(type **,const unsigned char **,long)
+# define TYPEDEF_I2D_OF(type) typedef int i2d_of_##type(type *,unsigned char **)
+# define TYPEDEF_D2I2D_OF(type) TYPEDEF_D2I_OF(type); TYPEDEF_I2D_OF(type)
+
+TYPEDEF_D2I2D_OF(void);
+
+/*-
+ * The following macros and typedefs allow an ASN1_ITEM
+ * to be embedded in a structure and referenced. Since
+ * the ASN1_ITEM pointers need to be globally accessible
+ * (possibly from shared libraries) they may exist in
+ * different forms. On platforms that support it the
+ * ASN1_ITEM structure itself will be globally exported.
+ * Other platforms will export a function that returns
+ * an ASN1_ITEM pointer.
+ *
+ * To handle both cases transparently the macros below
+ * should be used instead of hard coding an ASN1_ITEM
+ * pointer in a structure.
+ *
+ * The structure will look like this:
+ *
+ * typedef struct SOMETHING_st {
+ *      ...
+ *      ASN1_ITEM_EXP *iptr;
+ *      ...
+ * } SOMETHING;
+ *
+ * It would be initialised as e.g.:
+ *
+ * SOMETHING somevar = {...,ASN1_ITEM_ref(X509),...};
+ *
+ * and the actual pointer extracted with:
+ *
+ * const ASN1_ITEM *it = ASN1_ITEM_ptr(somevar.iptr);
+ *
+ * Finally an ASN1_ITEM pointer can be extracted from an
+ * appropriate reference with: ASN1_ITEM_rptr(X509). This
+ * would be used when a function takes an ASN1_ITEM * argument.
+ *
+ */
+
+# ifndef OPENSSL_EXPORT_VAR_AS_FUNCTION
+
+/* ASN1_ITEM pointer exported type */
+typedef const ASN1_ITEM ASN1_ITEM_EXP;
+
+/* Macro to obtain ASN1_ITEM pointer from exported type */
+#  define ASN1_ITEM_ptr(iptr) (iptr)
+
+/* Macro to include ASN1_ITEM pointer from base type */
+#  define ASN1_ITEM_ref(iptr) (&(iptr##_it))
+
+#  define ASN1_ITEM_rptr(ref) (&(ref##_it))
+
+#  define DECLARE_ASN1_ITEM(name) \
+        OPENSSL_EXTERN const ASN1_ITEM name##_it;
+
+# else
+
+/*
+ * Platforms that can't easily handle shared global variables are declared as
+ * functions returning ASN1_ITEM pointers.
+ */
+
+/* ASN1_ITEM pointer exported type */
+typedef const ASN1_ITEM *ASN1_ITEM_EXP (void);
+
+/* Macro to obtain ASN1_ITEM pointer from exported type */
+#  define ASN1_ITEM_ptr(iptr) (iptr())
+
+/* Macro to include ASN1_ITEM pointer from base type */
+#  define ASN1_ITEM_ref(iptr) (iptr##_it)
+
+#  define ASN1_ITEM_rptr(ref) (ref##_it())
+
+#  define DECLARE_ASN1_ITEM(name) \
+        const ASN1_ITEM * name##_it(void);
+
+# endif
+
+/* Parameters used by ASN1_STRING_print_ex() */
+
+/*
+ * These determine which characters to escape: RFC2253 special characters,
+ * control characters and MSB set characters
+ */
+
+# define ASN1_STRFLGS_ESC_2253           1
+# define ASN1_STRFLGS_ESC_CTRL           2
+# define ASN1_STRFLGS_ESC_MSB            4
+
+/*
+ * This flag determines how we do escaping: normally RC2253 backslash only,
+ * set this to use backslash and quote.
+ */
+
+# define ASN1_STRFLGS_ESC_QUOTE          8
+
+/* These three flags are internal use only. */
+
+/* Character is a valid PrintableString character */
+# define CHARTYPE_PRINTABLESTRING        0x10
+/* Character needs escaping if it is the first character */
+# define CHARTYPE_FIRST_ESC_2253         0x20
+/* Character needs escaping if it is the last character */
+# define CHARTYPE_LAST_ESC_2253          0x40
+
+/*
+ * NB the internal flags are safely reused below by flags handled at the top
+ * level.
+ */
+
+/*
+ * If this is set we convert all character strings to UTF8 first
+ */
+
+# define ASN1_STRFLGS_UTF8_CONVERT       0x10
+
+/*
+ * If this is set we don't attempt to interpret content: just assume all
+ * strings are 1 byte per character. This will produce some pretty odd
+ * looking output!
+ */
+
+# define ASN1_STRFLGS_IGNORE_TYPE        0x20
+
+/* If this is set we include the string type in the output */
+# define ASN1_STRFLGS_SHOW_TYPE          0x40
+
+/*
+ * This determines which strings to display and which to 'dump' (hex dump of
+ * content octets or DER encoding). We can only dump non character strings or
+ * everything. If we don't dump 'unknown' they are interpreted as character
+ * strings with 1 octet per character and are subject to the usual escaping
+ * options.
+ */
+
+# define ASN1_STRFLGS_DUMP_ALL           0x80
+# define ASN1_STRFLGS_DUMP_UNKNOWN       0x100
+
+/*
+ * These determine what 'dumping' does, we can dump the content octets or the
+ * DER encoding: both use the RFC2253 #XXXXX notation.
+ */
+
+# define ASN1_STRFLGS_DUMP_DER           0x200
+
+/*
+ * All the string flags consistent with RFC2253, escaping control characters
+ * isn't essential in RFC2253 but it is advisable anyway.
+ */
+
+# define ASN1_STRFLGS_RFC2253    (ASN1_STRFLGS_ESC_2253 | \
+                                ASN1_STRFLGS_ESC_CTRL | \
+                                ASN1_STRFLGS_ESC_MSB | \
+                                ASN1_STRFLGS_UTF8_CONVERT | \
+                                ASN1_STRFLGS_DUMP_UNKNOWN | \
+                                ASN1_STRFLGS_DUMP_DER)
+
+DECLARE_STACK_OF(ASN1_INTEGER)
+DECLARE_ASN1_SET_OF(ASN1_INTEGER)
+
+DECLARE_STACK_OF(ASN1_GENERALSTRING)
+
+typedef struct asn1_type_st {
+    int type;
+    union {
+        char *ptr;
+        ASN1_BOOLEAN boolean;
+        ASN1_STRING *asn1_string;
+        ASN1_OBJECT *object;
+        ASN1_INTEGER *integer;
+        ASN1_ENUMERATED *enumerated;
+        ASN1_BIT_STRING *bit_string;
+        ASN1_OCTET_STRING *octet_string;
+        ASN1_PRINTABLESTRING *printablestring;
+        ASN1_T61STRING *t61string;
+        ASN1_IA5STRING *ia5string;
+        ASN1_GENERALSTRING *generalstring;
+        ASN1_BMPSTRING *bmpstring;
+        ASN1_UNIVERSALSTRING *universalstring;
+        ASN1_UTCTIME *utctime;
+        ASN1_GENERALIZEDTIME *generalizedtime;
+        ASN1_VISIBLESTRING *visiblestring;
+        ASN1_UTF8STRING *utf8string;
+        /*
+         * set and sequence are left complete and still contain the set or
+         * sequence bytes
+         */
+        ASN1_STRING *set;
+        ASN1_STRING *sequence;
+        ASN1_VALUE *asn1_value;
+    } value;
+} ASN1_TYPE;
+
+DECLARE_STACK_OF(ASN1_TYPE)
+DECLARE_ASN1_SET_OF(ASN1_TYPE)
+
+typedef STACK_OF(ASN1_TYPE) ASN1_SEQUENCE_ANY;
+
+DECLARE_ASN1_ENCODE_FUNCTIONS_const(ASN1_SEQUENCE_ANY, ASN1_SEQUENCE_ANY)
+DECLARE_ASN1_ENCODE_FUNCTIONS_const(ASN1_SEQUENCE_ANY, ASN1_SET_ANY)
+
+typedef struct NETSCAPE_X509_st {
+    ASN1_OCTET_STRING *header;
+    X509 *cert;
+} NETSCAPE_X509;
+
+/* This is used to contain a list of bit names */
+typedef struct BIT_STRING_BITNAME_st {
+    int bitnum;
+    const char *lname;
+    const char *sname;
+} BIT_STRING_BITNAME;
+
+# define M_ASN1_STRING_length(x) ((x)->length)
+# define M_ASN1_STRING_length_set(x, n)  ((x)->length = (n))
+# define M_ASN1_STRING_type(x)   ((x)->type)
+# define M_ASN1_STRING_data(x)   ((x)->data)
+
+/* Macros for string operations */
+# define M_ASN1_BIT_STRING_new() (ASN1_BIT_STRING *)\
+                ASN1_STRING_type_new(V_ASN1_BIT_STRING)
+# define M_ASN1_BIT_STRING_free(a)       ASN1_STRING_free((ASN1_STRING *)a)
+# define M_ASN1_BIT_STRING_dup(a) (ASN1_BIT_STRING *)\
+                ASN1_STRING_dup((const ASN1_STRING *)a)
+# define M_ASN1_BIT_STRING_cmp(a,b) ASN1_STRING_cmp(\
+                (const ASN1_STRING *)a,(const ASN1_STRING *)b)
+# define M_ASN1_BIT_STRING_set(a,b,c) ASN1_STRING_set((ASN1_STRING *)a,b,c)
+
+# define M_ASN1_INTEGER_new()    (ASN1_INTEGER *)\
+                ASN1_STRING_type_new(V_ASN1_INTEGER)
+# define M_ASN1_INTEGER_free(a)          ASN1_STRING_free((ASN1_STRING *)a)
+# define M_ASN1_INTEGER_dup(a) (ASN1_INTEGER *)\
+                ASN1_STRING_dup((const ASN1_STRING *)a)
+# define M_ASN1_INTEGER_cmp(a,b) ASN1_STRING_cmp(\
+                (const ASN1_STRING *)a,(const ASN1_STRING *)b)
+
+# define M_ASN1_ENUMERATED_new() (ASN1_ENUMERATED *)\
+                ASN1_STRING_type_new(V_ASN1_ENUMERATED)
+# define M_ASN1_ENUMERATED_free(a)       ASN1_STRING_free((ASN1_STRING *)a)
+# define M_ASN1_ENUMERATED_dup(a) (ASN1_ENUMERATED *)\
+                ASN1_STRING_dup((const ASN1_STRING *)a)
+# define M_ASN1_ENUMERATED_cmp(a,b)      ASN1_STRING_cmp(\
+                (const ASN1_STRING *)a,(const ASN1_STRING *)b)
+
+# define M_ASN1_OCTET_STRING_new()       (ASN1_OCTET_STRING *)\
+                ASN1_STRING_type_new(V_ASN1_OCTET_STRING)
+# define M_ASN1_OCTET_STRING_free(a)     ASN1_STRING_free((ASN1_STRING *)a)
+# define M_ASN1_OCTET_STRING_dup(a) (ASN1_OCTET_STRING *)\
+                ASN1_STRING_dup((const ASN1_STRING *)a)
+# define M_ASN1_OCTET_STRING_cmp(a,b) ASN1_STRING_cmp(\
+                (const ASN1_STRING *)a,(const ASN1_STRING *)b)
+# define M_ASN1_OCTET_STRING_set(a,b,c)  ASN1_STRING_set((ASN1_STRING *)a,b,c)
+# define M_ASN1_OCTET_STRING_print(a,b)  ASN1_STRING_print(a,(ASN1_STRING *)b)
+# define M_i2d_ASN1_OCTET_STRING(a,pp) \
+                i2d_ASN1_bytes((ASN1_STRING *)a,pp,V_ASN1_OCTET_STRING,\
+                V_ASN1_UNIVERSAL)
+
+# define B_ASN1_TIME \
+                        B_ASN1_UTCTIME | \
+                        B_ASN1_GENERALIZEDTIME
+
+# define B_ASN1_PRINTABLE \
+                        B_ASN1_NUMERICSTRING| \
+                        B_ASN1_PRINTABLESTRING| \
+                        B_ASN1_T61STRING| \
+                        B_ASN1_IA5STRING| \
+                        B_ASN1_BIT_STRING| \
+                        B_ASN1_UNIVERSALSTRING|\
+                        B_ASN1_BMPSTRING|\
+                        B_ASN1_UTF8STRING|\
+                        B_ASN1_SEQUENCE|\
+                        B_ASN1_UNKNOWN
+
+# define B_ASN1_DIRECTORYSTRING \
+                        B_ASN1_PRINTABLESTRING| \
+                        B_ASN1_TELETEXSTRING|\
+                        B_ASN1_BMPSTRING|\
+                        B_ASN1_UNIVERSALSTRING|\
+                        B_ASN1_UTF8STRING
+
+# define B_ASN1_DISPLAYTEXT \
+                        B_ASN1_IA5STRING| \
+                        B_ASN1_VISIBLESTRING| \
+                        B_ASN1_BMPSTRING|\
+                        B_ASN1_UTF8STRING
+
+# define M_ASN1_PRINTABLE_new()  ASN1_STRING_type_new(V_ASN1_T61STRING)
+# define M_ASN1_PRINTABLE_free(a)        ASN1_STRING_free((ASN1_STRING *)a)
+# define M_i2d_ASN1_PRINTABLE(a,pp) i2d_ASN1_bytes((ASN1_STRING *)a,\
+                pp,a->type,V_ASN1_UNIVERSAL)
+# define M_d2i_ASN1_PRINTABLE(a,pp,l) \
+                d2i_ASN1_type_bytes((ASN1_STRING **)a,pp,l, \
+                        B_ASN1_PRINTABLE)
+
+# define M_DIRECTORYSTRING_new() ASN1_STRING_type_new(V_ASN1_PRINTABLESTRING)
+# define M_DIRECTORYSTRING_free(a)       ASN1_STRING_free((ASN1_STRING *)a)
+# define M_i2d_DIRECTORYSTRING(a,pp) i2d_ASN1_bytes((ASN1_STRING *)a,\
+                                                pp,a->type,V_ASN1_UNIVERSAL)
+# define M_d2i_DIRECTORYSTRING(a,pp,l) \
+                d2i_ASN1_type_bytes((ASN1_STRING **)a,pp,l, \
+                        B_ASN1_DIRECTORYSTRING)
+
+# define M_DISPLAYTEXT_new() ASN1_STRING_type_new(V_ASN1_VISIBLESTRING)
+# define M_DISPLAYTEXT_free(a) ASN1_STRING_free((ASN1_STRING *)a)
+# define M_i2d_DISPLAYTEXT(a,pp) i2d_ASN1_bytes((ASN1_STRING *)a,\
+                                                pp,a->type,V_ASN1_UNIVERSAL)
+# define M_d2i_DISPLAYTEXT(a,pp,l) \
+                d2i_ASN1_type_bytes((ASN1_STRING **)a,pp,l, \
+                        B_ASN1_DISPLAYTEXT)
+
+# define M_ASN1_PRINTABLESTRING_new() (ASN1_PRINTABLESTRING *)\
+                ASN1_STRING_type_new(V_ASN1_PRINTABLESTRING)
+# define M_ASN1_PRINTABLESTRING_free(a)  ASN1_STRING_free((ASN1_STRING *)a)
+# define M_i2d_ASN1_PRINTABLESTRING(a,pp) \
+                i2d_ASN1_bytes((ASN1_STRING *)a,pp,V_ASN1_PRINTABLESTRING,\
+                V_ASN1_UNIVERSAL)
+# define M_d2i_ASN1_PRINTABLESTRING(a,pp,l) \
+                (ASN1_PRINTABLESTRING *)d2i_ASN1_type_bytes\
+                ((ASN1_STRING **)a,pp,l,B_ASN1_PRINTABLESTRING)
+
+# define M_ASN1_T61STRING_new()  (ASN1_T61STRING *)\
+                ASN1_STRING_type_new(V_ASN1_T61STRING)
+# define M_ASN1_T61STRING_free(a)        ASN1_STRING_free((ASN1_STRING *)a)
+# define M_i2d_ASN1_T61STRING(a,pp) \
+                i2d_ASN1_bytes((ASN1_STRING *)a,pp,V_ASN1_T61STRING,\
+                V_ASN1_UNIVERSAL)
+# define M_d2i_ASN1_T61STRING(a,pp,l) \
+                (ASN1_T61STRING *)d2i_ASN1_type_bytes\
+                ((ASN1_STRING **)a,pp,l,B_ASN1_T61STRING)
+
+# define M_ASN1_IA5STRING_new()  (ASN1_IA5STRING *)\
+                ASN1_STRING_type_new(V_ASN1_IA5STRING)
+# define M_ASN1_IA5STRING_free(a)        ASN1_STRING_free((ASN1_STRING *)a)
+# define M_ASN1_IA5STRING_dup(a) \
+                (ASN1_IA5STRING *)ASN1_STRING_dup((const ASN1_STRING *)a)
+# define M_i2d_ASN1_IA5STRING(a,pp) \
+                i2d_ASN1_bytes((ASN1_STRING *)a,pp,V_ASN1_IA5STRING,\
+                        V_ASN1_UNIVERSAL)
+# define M_d2i_ASN1_IA5STRING(a,pp,l) \
+                (ASN1_IA5STRING *)d2i_ASN1_type_bytes((ASN1_STRING **)a,pp,l,\
+                        B_ASN1_IA5STRING)
+
+# define M_ASN1_UTCTIME_new()    (ASN1_UTCTIME *)\
+                ASN1_STRING_type_new(V_ASN1_UTCTIME)
+# define M_ASN1_UTCTIME_free(a)  ASN1_STRING_free((ASN1_STRING *)a)
+# define M_ASN1_UTCTIME_dup(a) (ASN1_UTCTIME *)\
+                ASN1_STRING_dup((const ASN1_STRING *)a)
+
+# define M_ASN1_GENERALIZEDTIME_new()    (ASN1_GENERALIZEDTIME *)\
+                ASN1_STRING_type_new(V_ASN1_GENERALIZEDTIME)
+# define M_ASN1_GENERALIZEDTIME_free(a)  ASN1_STRING_free((ASN1_STRING *)a)
+# define M_ASN1_GENERALIZEDTIME_dup(a) (ASN1_GENERALIZEDTIME *)ASN1_STRING_dup(\
+        (const ASN1_STRING *)a)
+
+# define M_ASN1_TIME_new()       (ASN1_TIME *)\
+                ASN1_STRING_type_new(V_ASN1_UTCTIME)
+# define M_ASN1_TIME_free(a)     ASN1_STRING_free((ASN1_STRING *)a)
+# define M_ASN1_TIME_dup(a) (ASN1_TIME *)\
+        ASN1_STRING_dup((const ASN1_STRING *)a)
+
+# define M_ASN1_GENERALSTRING_new()      (ASN1_GENERALSTRING *)\
+                ASN1_STRING_type_new(V_ASN1_GENERALSTRING)
+# define M_ASN1_GENERALSTRING_free(a)    ASN1_STRING_free((ASN1_STRING *)a)
+# define M_i2d_ASN1_GENERALSTRING(a,pp) \
+                i2d_ASN1_bytes((ASN1_STRING *)a,pp,V_ASN1_GENERALSTRING,\
+                        V_ASN1_UNIVERSAL)
+# define M_d2i_ASN1_GENERALSTRING(a,pp,l) \
+                (ASN1_GENERALSTRING *)d2i_ASN1_type_bytes\
+                ((ASN1_STRING **)a,pp,l,B_ASN1_GENERALSTRING)
+
+# define M_ASN1_UNIVERSALSTRING_new()    (ASN1_UNIVERSALSTRING *)\
+                ASN1_STRING_type_new(V_ASN1_UNIVERSALSTRING)
+# define M_ASN1_UNIVERSALSTRING_free(a)  ASN1_STRING_free((ASN1_STRING *)a)
+# define M_i2d_ASN1_UNIVERSALSTRING(a,pp) \
+                i2d_ASN1_bytes((ASN1_STRING *)a,pp,V_ASN1_UNIVERSALSTRING,\
+                        V_ASN1_UNIVERSAL)
+# define M_d2i_ASN1_UNIVERSALSTRING(a,pp,l) \
+                (ASN1_UNIVERSALSTRING *)d2i_ASN1_type_bytes\
+                ((ASN1_STRING **)a,pp,l,B_ASN1_UNIVERSALSTRING)
+
+# define M_ASN1_BMPSTRING_new()  (ASN1_BMPSTRING *)\
+                ASN1_STRING_type_new(V_ASN1_BMPSTRING)
+# define M_ASN1_BMPSTRING_free(a)        ASN1_STRING_free((ASN1_STRING *)a)
+# define M_i2d_ASN1_BMPSTRING(a,pp) \
+                i2d_ASN1_bytes((ASN1_STRING *)a,pp,V_ASN1_BMPSTRING,\
+                        V_ASN1_UNIVERSAL)
+# define M_d2i_ASN1_BMPSTRING(a,pp,l) \
+                (ASN1_BMPSTRING *)d2i_ASN1_type_bytes\
+                ((ASN1_STRING **)a,pp,l,B_ASN1_BMPSTRING)
+
+# define M_ASN1_VISIBLESTRING_new()      (ASN1_VISIBLESTRING *)\
+                ASN1_STRING_type_new(V_ASN1_VISIBLESTRING)
+# define M_ASN1_VISIBLESTRING_free(a)    ASN1_STRING_free((ASN1_STRING *)a)
+# define M_i2d_ASN1_VISIBLESTRING(a,pp) \
+                i2d_ASN1_bytes((ASN1_STRING *)a,pp,V_ASN1_VISIBLESTRING,\
+                        V_ASN1_UNIVERSAL)
+# define M_d2i_ASN1_VISIBLESTRING(a,pp,l) \
+                (ASN1_VISIBLESTRING *)d2i_ASN1_type_bytes\
+                ((ASN1_STRING **)a,pp,l,B_ASN1_VISIBLESTRING)
+
+# define M_ASN1_UTF8STRING_new() (ASN1_UTF8STRING *)\
+                ASN1_STRING_type_new(V_ASN1_UTF8STRING)
+# define M_ASN1_UTF8STRING_free(a)       ASN1_STRING_free((ASN1_STRING *)a)
+# define M_i2d_ASN1_UTF8STRING(a,pp) \
+                i2d_ASN1_bytes((ASN1_STRING *)a,pp,V_ASN1_UTF8STRING,\
+                        V_ASN1_UNIVERSAL)
+# define M_d2i_ASN1_UTF8STRING(a,pp,l) \
+                (ASN1_UTF8STRING *)d2i_ASN1_type_bytes\
+                ((ASN1_STRING **)a,pp,l,B_ASN1_UTF8STRING)
+
+  /* for the is_set parameter to i2d_ASN1_SET */
+# define IS_SEQUENCE     0
+# define IS_SET          1
+
+DECLARE_ASN1_FUNCTIONS_fname(ASN1_TYPE, ASN1_ANY, ASN1_TYPE)
+
+int ASN1_TYPE_get(ASN1_TYPE *a);
+void ASN1_TYPE_set(ASN1_TYPE *a, int type, void *value);
+int ASN1_TYPE_set1(ASN1_TYPE *a, int type, const void *value);
+int ASN1_TYPE_cmp(const ASN1_TYPE *a, const ASN1_TYPE *b);
+
+ASN1_OBJECT *ASN1_OBJECT_new(void);
+void ASN1_OBJECT_free(ASN1_OBJECT *a);
+int i2d_ASN1_OBJECT(ASN1_OBJECT *a, unsigned char **pp);
+ASN1_OBJECT *c2i_ASN1_OBJECT(ASN1_OBJECT **a, const unsigned char **pp,
+                             long length);
+ASN1_OBJECT *d2i_ASN1_OBJECT(ASN1_OBJECT **a, const unsigned char **pp,
+                             long length);
+
+DECLARE_ASN1_ITEM(ASN1_OBJECT)
+
+DECLARE_STACK_OF(ASN1_OBJECT)
+DECLARE_ASN1_SET_OF(ASN1_OBJECT)
+
+ASN1_STRING *ASN1_STRING_new(void);
+void ASN1_STRING_free(ASN1_STRING *a);
+void ASN1_STRING_clear_free(ASN1_STRING *a);
+int ASN1_STRING_copy(ASN1_STRING *dst, const ASN1_STRING *str);
+ASN1_STRING *ASN1_STRING_dup(const ASN1_STRING *a);
+ASN1_STRING *ASN1_STRING_type_new(int type);
+int ASN1_STRING_cmp(const ASN1_STRING *a, const ASN1_STRING *b);
+  /*
+   * Since this is used to store all sorts of things, via macros, for now,
+   * make its data void *
+   */
+int ASN1_STRING_set(ASN1_STRING *str, const void *data, int len);
+void ASN1_STRING_set0(ASN1_STRING *str, void *data, int len);
+int ASN1_STRING_length(const ASN1_STRING *x);
+void ASN1_STRING_length_set(ASN1_STRING *x, int n);
+int ASN1_STRING_type(ASN1_STRING *x);
+unsigned char *ASN1_STRING_data(ASN1_STRING *x);
+
+DECLARE_ASN1_FUNCTIONS(ASN1_BIT_STRING)
+int i2c_ASN1_BIT_STRING(ASN1_BIT_STRING *a, unsigned char **pp);
+ASN1_BIT_STRING *c2i_ASN1_BIT_STRING(ASN1_BIT_STRING **a,
+                                     const unsigned char **pp, long length);
+int ASN1_BIT_STRING_set(ASN1_BIT_STRING *a, unsigned char *d, int length);
+int ASN1_BIT_STRING_set_bit(ASN1_BIT_STRING *a, int n, int value);
+int ASN1_BIT_STRING_get_bit(ASN1_BIT_STRING *a, int n);
+int ASN1_BIT_STRING_check(ASN1_BIT_STRING *a,
+                          unsigned char *flags, int flags_len);
+
+# ifndef OPENSSL_NO_BIO
+int ASN1_BIT_STRING_name_print(BIO *out, ASN1_BIT_STRING *bs,
+                               BIT_STRING_BITNAME *tbl, int indent);
+# endif
+int ASN1_BIT_STRING_num_asc(char *name, BIT_STRING_BITNAME *tbl);
+int ASN1_BIT_STRING_set_asc(ASN1_BIT_STRING *bs, char *name, int value,
+                            BIT_STRING_BITNAME *tbl);
+
+int i2d_ASN1_BOOLEAN(int a, unsigned char **pp);
+int d2i_ASN1_BOOLEAN(int *a, const unsigned char **pp, long length);
+
+DECLARE_ASN1_FUNCTIONS(ASN1_INTEGER)
+int i2c_ASN1_INTEGER(ASN1_INTEGER *a, unsigned char **pp);
+ASN1_INTEGER *c2i_ASN1_INTEGER(ASN1_INTEGER **a, const unsigned char **pp,
+                               long length);
+ASN1_INTEGER *d2i_ASN1_UINTEGER(ASN1_INTEGER **a, const unsigned char **pp,
+                                long length);
+ASN1_INTEGER *ASN1_INTEGER_dup(const ASN1_INTEGER *x);
+int ASN1_INTEGER_cmp(const ASN1_INTEGER *x, const ASN1_INTEGER *y);
+
+DECLARE_ASN1_FUNCTIONS(ASN1_ENUMERATED)
+
+int ASN1_UTCTIME_check(const ASN1_UTCTIME *a);
+ASN1_UTCTIME *ASN1_UTCTIME_set(ASN1_UTCTIME *s, time_t t);
+ASN1_UTCTIME *ASN1_UTCTIME_adj(ASN1_UTCTIME *s, time_t t,
+                               int offset_day, long offset_sec);
+int ASN1_UTCTIME_set_string(ASN1_UTCTIME *s, const char *str);
+int ASN1_UTCTIME_cmp_time_t(const ASN1_UTCTIME *s, time_t t);
+# if 0
+time_t ASN1_UTCTIME_get(const ASN1_UTCTIME *s);
+# endif
+
+int ASN1_GENERALIZEDTIME_check(const ASN1_GENERALIZEDTIME *a);
+ASN1_GENERALIZEDTIME *ASN1_GENERALIZEDTIME_set(ASN1_GENERALIZEDTIME *s,
+                                               time_t t);
+ASN1_GENERALIZEDTIME *ASN1_GENERALIZEDTIME_adj(ASN1_GENERALIZEDTIME *s,
+                                               time_t t, int offset_day,
+                                               long offset_sec);
+int ASN1_GENERALIZEDTIME_set_string(ASN1_GENERALIZEDTIME *s, const char *str);
+int ASN1_TIME_diff(int *pday, int *psec,
+                   const ASN1_TIME *from, const ASN1_TIME *to);
+
+DECLARE_ASN1_FUNCTIONS(ASN1_OCTET_STRING)
+ASN1_OCTET_STRING *ASN1_OCTET_STRING_dup(const ASN1_OCTET_STRING *a);
+int ASN1_OCTET_STRING_cmp(const ASN1_OCTET_STRING *a,
+                          const ASN1_OCTET_STRING *b);
+int ASN1_OCTET_STRING_set(ASN1_OCTET_STRING *str, const unsigned char *data,
+                          int len);
+
+DECLARE_ASN1_FUNCTIONS(ASN1_VISIBLESTRING)
+DECLARE_ASN1_FUNCTIONS(ASN1_UNIVERSALSTRING)
+DECLARE_ASN1_FUNCTIONS(ASN1_UTF8STRING)
+DECLARE_ASN1_FUNCTIONS(ASN1_NULL)
+DECLARE_ASN1_FUNCTIONS(ASN1_BMPSTRING)
+
+int UTF8_getc(const unsigned char *str, int len, unsigned long *val);
+int UTF8_putc(unsigned char *str, int len, unsigned long value);
+
+DECLARE_ASN1_FUNCTIONS_name(ASN1_STRING, ASN1_PRINTABLE)
+
+DECLARE_ASN1_FUNCTIONS_name(ASN1_STRING, DIRECTORYSTRING)
+DECLARE_ASN1_FUNCTIONS_name(ASN1_STRING, DISPLAYTEXT)
+DECLARE_ASN1_FUNCTIONS(ASN1_PRINTABLESTRING)
+DECLARE_ASN1_FUNCTIONS(ASN1_T61STRING)
+DECLARE_ASN1_FUNCTIONS(ASN1_IA5STRING)
+DECLARE_ASN1_FUNCTIONS(ASN1_GENERALSTRING)
+DECLARE_ASN1_FUNCTIONS(ASN1_UTCTIME)
+DECLARE_ASN1_FUNCTIONS(ASN1_GENERALIZEDTIME)
+DECLARE_ASN1_FUNCTIONS(ASN1_TIME)
+
+DECLARE_ASN1_ITEM(ASN1_OCTET_STRING_NDEF)
+
+ASN1_TIME *ASN1_TIME_set(ASN1_TIME *s, time_t t);
+ASN1_TIME *ASN1_TIME_adj(ASN1_TIME *s, time_t t,
+                         int offset_day, long offset_sec);
+int ASN1_TIME_check(ASN1_TIME *t);
+ASN1_GENERALIZEDTIME *ASN1_TIME_to_generalizedtime(ASN1_TIME *t, ASN1_GENERALIZEDTIME
+                                                   **out);
+int ASN1_TIME_set_string(ASN1_TIME *s, const char *str);
+
+int i2d_ASN1_SET(STACK_OF(OPENSSL_BLOCK) *a, unsigned char **pp,
+                 i2d_of_void *i2d, int ex_tag, int ex_class, int is_set);
+STACK_OF(OPENSSL_BLOCK) *d2i_ASN1_SET(STACK_OF(OPENSSL_BLOCK) **a,
+                                      const unsigned char **pp,
+                                      long length, d2i_of_void *d2i,
+                                      void (*free_func) (OPENSSL_BLOCK),
+                                      int ex_tag, int ex_class);
+
+# ifndef OPENSSL_NO_BIO
+int i2a_ASN1_INTEGER(BIO *bp, ASN1_INTEGER *a);
+int a2i_ASN1_INTEGER(BIO *bp, ASN1_INTEGER *bs, char *buf, int size);
+int i2a_ASN1_ENUMERATED(BIO *bp, ASN1_ENUMERATED *a);
+int a2i_ASN1_ENUMERATED(BIO *bp, ASN1_ENUMERATED *bs, char *buf, int size);
+int i2a_ASN1_OBJECT(BIO *bp, ASN1_OBJECT *a);
+int a2i_ASN1_STRING(BIO *bp, ASN1_STRING *bs, char *buf, int size);
+int i2a_ASN1_STRING(BIO *bp, ASN1_STRING *a, int type);
+# endif
+int i2t_ASN1_OBJECT(char *buf, int buf_len, ASN1_OBJECT *a);
+
+int a2d_ASN1_OBJECT(unsigned char *out, int olen, const char *buf, int num);
+ASN1_OBJECT *ASN1_OBJECT_create(int nid, unsigned char *data, int len,
+                                const char *sn, const char *ln);
+
+int ASN1_INTEGER_set(ASN1_INTEGER *a, long v);
+long ASN1_INTEGER_get(const ASN1_INTEGER *a);
+ASN1_INTEGER *BN_to_ASN1_INTEGER(const BIGNUM *bn, ASN1_INTEGER *ai);
+BIGNUM *ASN1_INTEGER_to_BN(const ASN1_INTEGER *ai, BIGNUM *bn);
+
+int ASN1_ENUMERATED_set(ASN1_ENUMERATED *a, long v);
+long ASN1_ENUMERATED_get(ASN1_ENUMERATED *a);
+ASN1_ENUMERATED *BN_to_ASN1_ENUMERATED(BIGNUM *bn, ASN1_ENUMERATED *ai);
+BIGNUM *ASN1_ENUMERATED_to_BN(ASN1_ENUMERATED *ai, BIGNUM *bn);
+
+/* General */
+/* given a string, return the correct type, max is the maximum length */
+int ASN1_PRINTABLE_type(const unsigned char *s, int max);
+
+int i2d_ASN1_bytes(ASN1_STRING *a, unsigned char **pp, int tag, int xclass);
+ASN1_STRING *d2i_ASN1_bytes(ASN1_STRING **a, const unsigned char **pp,
+                            long length, int Ptag, int Pclass);
+unsigned long ASN1_tag2bit(int tag);
+/* type is one or more of the B_ASN1_ values. */
+ASN1_STRING *d2i_ASN1_type_bytes(ASN1_STRING **a, const unsigned char **pp,
+                                 long length, int type);
+
+/* PARSING */
+int asn1_Finish(ASN1_CTX *c);
+int asn1_const_Finish(ASN1_const_CTX *c);
+
+/* SPECIALS */
+int ASN1_get_object(const unsigned char **pp, long *plength, int *ptag,
+                    int *pclass, long omax);
+int ASN1_check_infinite_end(unsigned char **p, long len);
+int ASN1_const_check_infinite_end(const unsigned char **p, long len);
+void ASN1_put_object(unsigned char **pp, int constructed, int length,
+                     int tag, int xclass);
+int ASN1_put_eoc(unsigned char **pp);
+int ASN1_object_size(int constructed, int length, int tag);
+
+/* Used to implement other functions */
+void *ASN1_dup(i2d_of_void *i2d, d2i_of_void *d2i, void *x);
+
+# define ASN1_dup_of(type,i2d,d2i,x) \
+    ((type*)ASN1_dup(CHECKED_I2D_OF(type, i2d), \
+                     CHECKED_D2I_OF(type, d2i), \
+                     CHECKED_PTR_OF(type, x)))
+
+# define ASN1_dup_of_const(type,i2d,d2i,x) \
+    ((type*)ASN1_dup(CHECKED_I2D_OF(const type, i2d), \
+                     CHECKED_D2I_OF(type, d2i), \
+                     CHECKED_PTR_OF(const type, x)))
+
+void *ASN1_item_dup(const ASN1_ITEM *it, void *x);
+
+/* ASN1 alloc/free macros for when a type is only used internally */
+
+# define M_ASN1_new_of(type) (type *)ASN1_item_new(ASN1_ITEM_rptr(type))
+# define M_ASN1_free_of(x, type) \
+                ASN1_item_free(CHECKED_PTR_OF(type, x), ASN1_ITEM_rptr(type))
+
+# ifndef OPENSSL_NO_FP_API
+void *ASN1_d2i_fp(void *(*xnew) (void), d2i_of_void *d2i, FILE *in, void **x);
+
+#  define ASN1_d2i_fp_of(type,xnew,d2i,in,x) \
+    ((type*)ASN1_d2i_fp(CHECKED_NEW_OF(type, xnew), \
+                        CHECKED_D2I_OF(type, d2i), \
+                        in, \
+                        CHECKED_PPTR_OF(type, x)))
+
+void *ASN1_item_d2i_fp(const ASN1_ITEM *it, FILE *in, void *x);
+int ASN1_i2d_fp(i2d_of_void *i2d, FILE *out, void *x);
+
+#  define ASN1_i2d_fp_of(type,i2d,out,x) \
+    (ASN1_i2d_fp(CHECKED_I2D_OF(type, i2d), \
+                 out, \
+                 CHECKED_PTR_OF(type, x)))
+
+#  define ASN1_i2d_fp_of_const(type,i2d,out,x) \
+    (ASN1_i2d_fp(CHECKED_I2D_OF(const type, i2d), \
+                 out, \
+                 CHECKED_PTR_OF(const type, x)))
+
+int ASN1_item_i2d_fp(const ASN1_ITEM *it, FILE *out, void *x);
+int ASN1_STRING_print_ex_fp(FILE *fp, ASN1_STRING *str, unsigned long flags);
+# endif
+
+int ASN1_STRING_to_UTF8(unsigned char **out, ASN1_STRING *in);
+
+# ifndef OPENSSL_NO_BIO
+void *ASN1_d2i_bio(void *(*xnew) (void), d2i_of_void *d2i, BIO *in, void **x);
+
+#  define ASN1_d2i_bio_of(type,xnew,d2i,in,x) \
+    ((type*)ASN1_d2i_bio( CHECKED_NEW_OF(type, xnew), \
+                          CHECKED_D2I_OF(type, d2i), \
+                          in, \
+                          CHECKED_PPTR_OF(type, x)))
+
+void *ASN1_item_d2i_bio(const ASN1_ITEM *it, BIO *in, void *x);
+int ASN1_i2d_bio(i2d_of_void *i2d, BIO *out, unsigned char *x);
+
+#  define ASN1_i2d_bio_of(type,i2d,out,x) \
+    (ASN1_i2d_bio(CHECKED_I2D_OF(type, i2d), \
+                  out, \
+                  CHECKED_PTR_OF(type, x)))
+
+#  define ASN1_i2d_bio_of_const(type,i2d,out,x) \
+    (ASN1_i2d_bio(CHECKED_I2D_OF(const type, i2d), \
+                  out, \
+                  CHECKED_PTR_OF(const type, x)))
+
+int ASN1_item_i2d_bio(const ASN1_ITEM *it, BIO *out, void *x);
+int ASN1_UTCTIME_print(BIO *fp, const ASN1_UTCTIME *a);
+int ASN1_GENERALIZEDTIME_print(BIO *fp, const ASN1_GENERALIZEDTIME *a);
+int ASN1_TIME_print(BIO *fp, const ASN1_TIME *a);
+int ASN1_STRING_print(BIO *bp, const ASN1_STRING *v);
+int ASN1_STRING_print_ex(BIO *out, ASN1_STRING *str, unsigned long flags);
+int ASN1_bn_print(BIO *bp, const char *number, const BIGNUM *num,
+                  unsigned char *buf, int off);
+int ASN1_parse(BIO *bp, const unsigned char *pp, long len, int indent);
+int ASN1_parse_dump(BIO *bp, const unsigned char *pp, long len, int indent,
+                    int dump);
+# endif
+const char *ASN1_tag2str(int tag);
+
+/* Used to load and write netscape format cert */
+
+DECLARE_ASN1_FUNCTIONS(NETSCAPE_X509)
+
+int ASN1_UNIVERSALSTRING_to_string(ASN1_UNIVERSALSTRING *s);
+
+int ASN1_TYPE_set_octetstring(ASN1_TYPE *a, unsigned char *data, int len);
+int ASN1_TYPE_get_octetstring(ASN1_TYPE *a, unsigned char *data, int max_len);
+int ASN1_TYPE_set_int_octetstring(ASN1_TYPE *a, long num,
+                                  unsigned char *data, int len);
+int ASN1_TYPE_get_int_octetstring(ASN1_TYPE *a, long *num,
+                                  unsigned char *data, int max_len);
+
+STACK_OF(OPENSSL_BLOCK) *ASN1_seq_unpack(const unsigned char *buf, int len,
+                                         d2i_of_void *d2i,
+                                         void (*free_func) (OPENSSL_BLOCK));
+unsigned char *ASN1_seq_pack(STACK_OF(OPENSSL_BLOCK) *safes, i2d_of_void *i2d,
+                             unsigned char **buf, int *len);
+void *ASN1_unpack_string(ASN1_STRING *oct, d2i_of_void *d2i);
+void *ASN1_item_unpack(ASN1_STRING *oct, const ASN1_ITEM *it);
+ASN1_STRING *ASN1_pack_string(void *obj, i2d_of_void *i2d,
+                              ASN1_OCTET_STRING **oct);
+
+# define ASN1_pack_string_of(type,obj,i2d,oct) \
+    (ASN1_pack_string(CHECKED_PTR_OF(type, obj), \
+                      CHECKED_I2D_OF(type, i2d), \
+                      oct))
+
+ASN1_STRING *ASN1_item_pack(void *obj, const ASN1_ITEM *it,
+                            ASN1_OCTET_STRING **oct);
+
+void ASN1_STRING_set_default_mask(unsigned long mask);
+int ASN1_STRING_set_default_mask_asc(const char *p);
+unsigned long ASN1_STRING_get_default_mask(void);
+int ASN1_mbstring_copy(ASN1_STRING **out, const unsigned char *in, int len,
+                       int inform, unsigned long mask);
+int ASN1_mbstring_ncopy(ASN1_STRING **out, const unsigned char *in, int len,
+                        int inform, unsigned long mask,
+                        long minsize, long maxsize);
+
+ASN1_STRING *ASN1_STRING_set_by_NID(ASN1_STRING **out,
+                                    const unsigned char *in, int inlen,
+                                    int inform, int nid);
+ASN1_STRING_TABLE *ASN1_STRING_TABLE_get(int nid);
+int ASN1_STRING_TABLE_add(int, long, long, unsigned long, unsigned long);
+void ASN1_STRING_TABLE_cleanup(void);
+
+/* ASN1 template functions */
+
+/* Old API compatible functions */
+ASN1_VALUE *ASN1_item_new(const ASN1_ITEM *it);
+void ASN1_item_free(ASN1_VALUE *val, const ASN1_ITEM *it);
+ASN1_VALUE *ASN1_item_d2i(ASN1_VALUE **val, const unsigned char **in,
+                          long len, const ASN1_ITEM *it);
+int ASN1_item_i2d(ASN1_VALUE *val, unsigned char **out, const ASN1_ITEM *it);
+int ASN1_item_ndef_i2d(ASN1_VALUE *val, unsigned char **out,
+                       const ASN1_ITEM *it);
+
+void ASN1_add_oid_module(void);
+
+ASN1_TYPE *ASN1_generate_nconf(char *str, CONF *nconf);
+ASN1_TYPE *ASN1_generate_v3(char *str, X509V3_CTX *cnf);
+
+/* ASN1 Print flags */
+
+/* Indicate missing OPTIONAL fields */
+# define ASN1_PCTX_FLAGS_SHOW_ABSENT             0x001
+/* Mark start and end of SEQUENCE */
+# define ASN1_PCTX_FLAGS_SHOW_SEQUENCE           0x002
+/* Mark start and end of SEQUENCE/SET OF */
+# define ASN1_PCTX_FLAGS_SHOW_SSOF               0x004
+/* Show the ASN1 type of primitives */
+# define ASN1_PCTX_FLAGS_SHOW_TYPE               0x008
+/* Don't show ASN1 type of ANY */
+# define ASN1_PCTX_FLAGS_NO_ANY_TYPE             0x010
+/* Don't show ASN1 type of MSTRINGs */
+# define ASN1_PCTX_FLAGS_NO_MSTRING_TYPE         0x020
+/* Don't show field names in SEQUENCE */
+# define ASN1_PCTX_FLAGS_NO_FIELD_NAME           0x040
+/* Show structure names of each SEQUENCE field */
+# define ASN1_PCTX_FLAGS_SHOW_FIELD_STRUCT_NAME  0x080
+/* Don't show structure name even at top level */
+# define ASN1_PCTX_FLAGS_NO_STRUCT_NAME          0x100
+
+int ASN1_item_print(BIO *out, ASN1_VALUE *ifld, int indent,
+                    const ASN1_ITEM *it, const ASN1_PCTX *pctx);
+ASN1_PCTX *ASN1_PCTX_new(void);
+void ASN1_PCTX_free(ASN1_PCTX *p);
+unsigned long ASN1_PCTX_get_flags(ASN1_PCTX *p);
+void ASN1_PCTX_set_flags(ASN1_PCTX *p, unsigned long flags);
+unsigned long ASN1_PCTX_get_nm_flags(ASN1_PCTX *p);
+void ASN1_PCTX_set_nm_flags(ASN1_PCTX *p, unsigned long flags);
+unsigned long ASN1_PCTX_get_cert_flags(ASN1_PCTX *p);
+void ASN1_PCTX_set_cert_flags(ASN1_PCTX *p, unsigned long flags);
+unsigned long ASN1_PCTX_get_oid_flags(ASN1_PCTX *p);
+void ASN1_PCTX_set_oid_flags(ASN1_PCTX *p, unsigned long flags);
+unsigned long ASN1_PCTX_get_str_flags(ASN1_PCTX *p);
+void ASN1_PCTX_set_str_flags(ASN1_PCTX *p, unsigned long flags);
+
+BIO_METHOD *BIO_f_asn1(void);
+
+BIO *BIO_new_NDEF(BIO *out, ASN1_VALUE *val, const ASN1_ITEM *it);
+
+int i2d_ASN1_bio_stream(BIO *out, ASN1_VALUE *val, BIO *in, int flags,
+                        const ASN1_ITEM *it);
+int PEM_write_bio_ASN1_stream(BIO *out, ASN1_VALUE *val, BIO *in, int flags,
+                              const char *hdr, const ASN1_ITEM *it);
+int SMIME_write_ASN1(BIO *bio, ASN1_VALUE *val, BIO *data, int flags,
+                     int ctype_nid, int econt_nid,
+                     STACK_OF(X509_ALGOR) *mdalgs, const ASN1_ITEM *it);
+ASN1_VALUE *SMIME_read_ASN1(BIO *bio, BIO **bcont, const ASN1_ITEM *it);
+int SMIME_crlf_copy(BIO *in, BIO *out, int flags);
+int SMIME_text(BIO *in, BIO *out);
+
+/* BEGIN ERROR CODES */
+/*
+ * The following lines are auto generated by the script mkerr.pl. Any changes
+ * made after this point may be overwritten when the script is next run.
+ */
+
+void ERR_load_ASN1_strings(void);
+
+/* Error codes for the ASN1 functions. */
+
+/* Function codes. */
+# define ASN1_F_A2D_ASN1_OBJECT                           100
+# define ASN1_F_A2I_ASN1_ENUMERATED                       101
+# define ASN1_F_A2I_ASN1_INTEGER                          102
+# define ASN1_F_A2I_ASN1_STRING                           103
+# define ASN1_F_APPEND_EXP                                176
+# define ASN1_F_ASN1_BIT_STRING_SET_BIT                   183
+# define ASN1_F_ASN1_CB                                   177
+# define ASN1_F_ASN1_CHECK_TLEN                           104
+# define ASN1_F_ASN1_COLLATE_PRIMITIVE                    105
+# define ASN1_F_ASN1_COLLECT                              106
+# define ASN1_F_ASN1_D2I_EX_PRIMITIVE                     108
+# define ASN1_F_ASN1_D2I_FP                               109
+# define ASN1_F_ASN1_D2I_READ_BIO                         107
+# define ASN1_F_ASN1_DIGEST                               184
+# define ASN1_F_ASN1_DO_ADB                               110
+# define ASN1_F_ASN1_DUP                                  111
+# define ASN1_F_ASN1_ENUMERATED_SET                       112
+# define ASN1_F_ASN1_ENUMERATED_TO_BN                     113
+# define ASN1_F_ASN1_EX_C2I                               204
+# define ASN1_F_ASN1_FIND_END                             190
+# define ASN1_F_ASN1_GENERALIZEDTIME_ADJ                  216
+# define ASN1_F_ASN1_GENERALIZEDTIME_SET                  185
+# define ASN1_F_ASN1_GENERATE_V3                          178
+# define ASN1_F_ASN1_GET_OBJECT                           114
+# define ASN1_F_ASN1_HEADER_NEW                           115
+# define ASN1_F_ASN1_I2D_BIO                              116
+# define ASN1_F_ASN1_I2D_FP                               117
+# define ASN1_F_ASN1_INTEGER_SET                          118
+# define ASN1_F_ASN1_INTEGER_TO_BN                        119
+# define ASN1_F_ASN1_ITEM_D2I_FP                          206
+# define ASN1_F_ASN1_ITEM_DUP                             191
+# define ASN1_F_ASN1_ITEM_EX_COMBINE_NEW                  121
+# define ASN1_F_ASN1_ITEM_EX_D2I                          120
+# define ASN1_F_ASN1_ITEM_I2D_BIO                         192
+# define ASN1_F_ASN1_ITEM_I2D_FP                          193
+# define ASN1_F_ASN1_ITEM_PACK                            198
+# define ASN1_F_ASN1_ITEM_SIGN                            195
+# define ASN1_F_ASN1_ITEM_SIGN_CTX                        220
+# define ASN1_F_ASN1_ITEM_UNPACK                          199
+# define ASN1_F_ASN1_ITEM_VERIFY                          197
+# define ASN1_F_ASN1_MBSTRING_NCOPY                       122
+# define ASN1_F_ASN1_OBJECT_NEW                           123
+# define ASN1_F_ASN1_OUTPUT_DATA                          214
+# define ASN1_F_ASN1_PACK_STRING                          124
+# define ASN1_F_ASN1_PCTX_NEW                             205
+# define ASN1_F_ASN1_PKCS5_PBE_SET                        125
+# define ASN1_F_ASN1_SEQ_PACK                             126
+# define ASN1_F_ASN1_SEQ_UNPACK                           127
+# define ASN1_F_ASN1_SIGN                                 128
+# define ASN1_F_ASN1_STR2TYPE                             179
+# define ASN1_F_ASN1_STRING_SET                           186
+# define ASN1_F_ASN1_STRING_TABLE_ADD                     129
+# define ASN1_F_ASN1_STRING_TYPE_NEW                      130
+# define ASN1_F_ASN1_TEMPLATE_EX_D2I                      132
+# define ASN1_F_ASN1_TEMPLATE_NEW                         133
+# define ASN1_F_ASN1_TEMPLATE_NOEXP_D2I                   131
+# define ASN1_F_ASN1_TIME_ADJ                             217
+# define ASN1_F_ASN1_TIME_SET                             175
+# define ASN1_F_ASN1_TYPE_GET_INT_OCTETSTRING             134
+# define ASN1_F_ASN1_TYPE_GET_OCTETSTRING                 135
+# define ASN1_F_ASN1_UNPACK_STRING                        136
+# define ASN1_F_ASN1_UTCTIME_ADJ                          218
+# define ASN1_F_ASN1_UTCTIME_SET                          187
+# define ASN1_F_ASN1_VERIFY                               137
+# define ASN1_F_B64_READ_ASN1                             209
+# define ASN1_F_B64_WRITE_ASN1                            210
+# define ASN1_F_BIO_NEW_NDEF                              208
+# define ASN1_F_BITSTR_CB                                 180
+# define ASN1_F_BN_TO_ASN1_ENUMERATED                     138
+# define ASN1_F_BN_TO_ASN1_INTEGER                        139
+# define ASN1_F_C2I_ASN1_BIT_STRING                       189
+# define ASN1_F_C2I_ASN1_INTEGER                          194
+# define ASN1_F_C2I_ASN1_OBJECT                           196
+# define ASN1_F_COLLECT_DATA                              140
+# define ASN1_F_D2I_ASN1_BIT_STRING                       141
+# define ASN1_F_D2I_ASN1_BOOLEAN                          142
+# define ASN1_F_D2I_ASN1_BYTES                            143
+# define ASN1_F_D2I_ASN1_GENERALIZEDTIME                  144
+# define ASN1_F_D2I_ASN1_HEADER                           145
+# define ASN1_F_D2I_ASN1_INTEGER                          146
+# define ASN1_F_D2I_ASN1_OBJECT                           147
+# define ASN1_F_D2I_ASN1_SET                              148
+# define ASN1_F_D2I_ASN1_TYPE_BYTES                       149
+# define ASN1_F_D2I_ASN1_UINTEGER                         150
+# define ASN1_F_D2I_ASN1_UTCTIME                          151
+# define ASN1_F_D2I_AUTOPRIVATEKEY                        207
+# define ASN1_F_D2I_NETSCAPE_RSA                          152
+# define ASN1_F_D2I_NETSCAPE_RSA_2                        153
+# define ASN1_F_D2I_PRIVATEKEY                            154
+# define ASN1_F_D2I_PUBLICKEY                             155
+# define ASN1_F_D2I_RSA_NET                               200
+# define ASN1_F_D2I_RSA_NET_2                             201
+# define ASN1_F_D2I_X509                                  156
+# define ASN1_F_D2I_X509_CINF                             157
+# define ASN1_F_D2I_X509_PKEY                             159
+# define ASN1_F_DO_BUF                                    221
+# define ASN1_F_I2D_ASN1_BIO_STREAM                       211
+# define ASN1_F_I2D_ASN1_BOOLEAN                          223
+# define ASN1_F_I2D_ASN1_OBJECT                           222
+# define ASN1_F_I2D_ASN1_SET                              188
+# define ASN1_F_I2D_ASN1_TIME                             160
+# define ASN1_F_I2D_DSA_PUBKEY                            161
+# define ASN1_F_I2D_EC_PUBKEY                             181
+# define ASN1_F_I2D_PRIVATEKEY                            163
+# define ASN1_F_I2D_PUBLICKEY                             164
+# define ASN1_F_I2D_RSA_NET                               162
+# define ASN1_F_I2D_RSA_PUBKEY                            165
+# define ASN1_F_LONG_C2I                                  166
+# define ASN1_F_OID_MODULE_INIT                           174
+# define ASN1_F_PARSE_TAGGING                             182
+# define ASN1_F_PKCS5_PBE2_SET_IV                         167
+# define ASN1_F_PKCS5_PBE_SET                             202
+# define ASN1_F_PKCS5_PBE_SET0_ALGOR                      215
+# define ASN1_F_PKCS5_PBKDF2_SET                          219
+# define ASN1_F_SMIME_READ_ASN1                           212
+# define ASN1_F_SMIME_TEXT                                213
+# define ASN1_F_X509_CINF_NEW                             168
+# define ASN1_F_X509_CRL_ADD0_REVOKED                     169
+# define ASN1_F_X509_INFO_NEW                             170
+# define ASN1_F_X509_NAME_ENCODE                          203
+# define ASN1_F_X509_NAME_EX_D2I                          158
+# define ASN1_F_X509_NAME_EX_NEW                          171
+# define ASN1_F_X509_NEW                                  172
+# define ASN1_F_X509_PKEY_NEW                             173
+
+/* Reason codes. */
+# define ASN1_R_ADDING_OBJECT                             171
+# define ASN1_R_ASN1_PARSE_ERROR                          203
+# define ASN1_R_ASN1_SIG_PARSE_ERROR                      204
+# define ASN1_R_AUX_ERROR                                 100
+# define ASN1_R_BAD_CLASS                                 101
+# define ASN1_R_BAD_OBJECT_HEADER                         102
+# define ASN1_R_BAD_PASSWORD_READ                         103
+# define ASN1_R_BAD_TAG                                   104
+# define ASN1_R_BMPSTRING_IS_WRONG_LENGTH                 214
+# define ASN1_R_BN_LIB                                    105
+# define ASN1_R_BOOLEAN_IS_WRONG_LENGTH                   106
+# define ASN1_R_BUFFER_TOO_SMALL                          107
+# define ASN1_R_CIPHER_HAS_NO_OBJECT_IDENTIFIER           108
+# define ASN1_R_CONTEXT_NOT_INITIALISED                   217
+# define ASN1_R_DATA_IS_WRONG                             109
+# define ASN1_R_DECODE_ERROR                              110
+# define ASN1_R_DECODING_ERROR                            111
+# define ASN1_R_DEPTH_EXCEEDED                            174
+# define ASN1_R_DIGEST_AND_KEY_TYPE_NOT_SUPPORTED         198
+# define ASN1_R_ENCODE_ERROR                              112
+# define ASN1_R_ERROR_GETTING_TIME                        173
+# define ASN1_R_ERROR_LOADING_SECTION                     172
+# define ASN1_R_ERROR_PARSING_SET_ELEMENT                 113
+# define ASN1_R_ERROR_SETTING_CIPHER_PARAMS               114
+# define ASN1_R_EXPECTING_AN_INTEGER                      115
+# define ASN1_R_EXPECTING_AN_OBJECT                       116
+# define ASN1_R_EXPECTING_A_BOOLEAN                       117
+# define ASN1_R_EXPECTING_A_TIME                          118
+# define ASN1_R_EXPLICIT_LENGTH_MISMATCH                  119
+# define ASN1_R_EXPLICIT_TAG_NOT_CONSTRUCTED              120
+# define ASN1_R_FIELD_MISSING                             121
+# define ASN1_R_FIRST_NUM_TOO_LARGE                       122
+# define ASN1_R_HEADER_TOO_LONG                           123
+# define ASN1_R_ILLEGAL_BITSTRING_FORMAT                  175
+# define ASN1_R_ILLEGAL_BOOLEAN                           176
+# define ASN1_R_ILLEGAL_CHARACTERS                        124
+# define ASN1_R_ILLEGAL_FORMAT                            177
+# define ASN1_R_ILLEGAL_HEX                               178
+# define ASN1_R_ILLEGAL_IMPLICIT_TAG                      179
+# define ASN1_R_ILLEGAL_INTEGER                           180
+# define ASN1_R_ILLEGAL_NESTED_TAGGING                    181
+# define ASN1_R_ILLEGAL_NULL                              125
+# define ASN1_R_ILLEGAL_NULL_VALUE                        182
+# define ASN1_R_ILLEGAL_OBJECT                            183
+# define ASN1_R_ILLEGAL_OPTIONAL_ANY                      126
+# define ASN1_R_ILLEGAL_OPTIONS_ON_ITEM_TEMPLATE          170
+# define ASN1_R_ILLEGAL_TAGGED_ANY                        127
+# define ASN1_R_ILLEGAL_TIME_VALUE                        184
+# define ASN1_R_INTEGER_NOT_ASCII_FORMAT                  185
+# define ASN1_R_INTEGER_TOO_LARGE_FOR_LONG                128
+# define ASN1_R_INVALID_BIT_STRING_BITS_LEFT              220
+# define ASN1_R_INVALID_BMPSTRING_LENGTH                  129
+# define ASN1_R_INVALID_DIGIT                             130
+# define ASN1_R_INVALID_MIME_TYPE                         205
+# define ASN1_R_INVALID_MODIFIER                          186
+# define ASN1_R_INVALID_NUMBER                            187
+# define ASN1_R_INVALID_OBJECT_ENCODING                   216
+# define ASN1_R_INVALID_SEPARATOR                         131
+# define ASN1_R_INVALID_TIME_FORMAT                       132
+# define ASN1_R_INVALID_UNIVERSALSTRING_LENGTH            133
+# define ASN1_R_INVALID_UTF8STRING                        134
+# define ASN1_R_IV_TOO_LARGE                              135
+# define ASN1_R_LENGTH_ERROR                              136
+# define ASN1_R_LIST_ERROR                                188
+# define ASN1_R_MIME_NO_CONTENT_TYPE                      206
+# define ASN1_R_MIME_PARSE_ERROR                          207
+# define ASN1_R_MIME_SIG_PARSE_ERROR                      208
+# define ASN1_R_MISSING_EOC                               137
+# define ASN1_R_MISSING_SECOND_NUMBER                     138
+# define ASN1_R_MISSING_VALUE                             189
+# define ASN1_R_MSTRING_NOT_UNIVERSAL                     139
+# define ASN1_R_MSTRING_WRONG_TAG                         140
+# define ASN1_R_NESTED_ASN1_STRING                        197
+# define ASN1_R_NESTED_TOO_DEEP                           219
+# define ASN1_R_NON_HEX_CHARACTERS                        141
+# define ASN1_R_NOT_ASCII_FORMAT                          190
+# define ASN1_R_NOT_ENOUGH_DATA                           142
+# define ASN1_R_NO_CONTENT_TYPE                           209
+# define ASN1_R_NO_DEFAULT_DIGEST                         201
+# define ASN1_R_NO_MATCHING_CHOICE_TYPE                   143
+# define ASN1_R_NO_MULTIPART_BODY_FAILURE                 210
+# define ASN1_R_NO_MULTIPART_BOUNDARY                     211
+# define ASN1_R_NO_SIG_CONTENT_TYPE                       212
+# define ASN1_R_NULL_IS_WRONG_LENGTH                      144
+# define ASN1_R_OBJECT_NOT_ASCII_FORMAT                   191
+# define ASN1_R_ODD_NUMBER_OF_CHARS                       145
+# define ASN1_R_PRIVATE_KEY_HEADER_MISSING                146
+# define ASN1_R_SECOND_NUMBER_TOO_LARGE                   147
+# define ASN1_R_SEQUENCE_LENGTH_MISMATCH                  148
+# define ASN1_R_SEQUENCE_NOT_CONSTRUCTED                  149
+# define ASN1_R_SEQUENCE_OR_SET_NEEDS_CONFIG              192
+# define ASN1_R_SHORT_LINE                                150
+# define ASN1_R_SIG_INVALID_MIME_TYPE                     213
+# define ASN1_R_STREAMING_NOT_SUPPORTED                   202
+# define ASN1_R_STRING_TOO_LONG                           151
+# define ASN1_R_STRING_TOO_SHORT                          152
+# define ASN1_R_TAG_VALUE_TOO_HIGH                        153
+# define ASN1_R_THE_ASN1_OBJECT_IDENTIFIER_IS_NOT_KNOWN_FOR_THIS_MD 154
+# define ASN1_R_TIME_NOT_ASCII_FORMAT                     193
+# define ASN1_R_TOO_LONG                                  155
+# define ASN1_R_TYPE_NOT_CONSTRUCTED                      156
+# define ASN1_R_TYPE_NOT_PRIMITIVE                        218
+# define ASN1_R_UNABLE_TO_DECODE_RSA_KEY                  157
+# define ASN1_R_UNABLE_TO_DECODE_RSA_PRIVATE_KEY          158
+# define ASN1_R_UNEXPECTED_EOC                            159
+# define ASN1_R_UNIVERSALSTRING_IS_WRONG_LENGTH           215
+# define ASN1_R_UNKNOWN_FORMAT                            160
+# define ASN1_R_UNKNOWN_MESSAGE_DIGEST_ALGORITHM          161
+# define ASN1_R_UNKNOWN_OBJECT_TYPE                       162
+# define ASN1_R_UNKNOWN_PUBLIC_KEY_TYPE                   163
+# define ASN1_R_UNKNOWN_SIGNATURE_ALGORITHM               199
+# define ASN1_R_UNKNOWN_TAG                               194
+# define ASN1_R_UNKOWN_FORMAT                             195
+# define ASN1_R_UNSUPPORTED_ANY_DEFINED_BY_TYPE           164
+# define ASN1_R_UNSUPPORTED_CIPHER                        165
+# define ASN1_R_UNSUPPORTED_ENCRYPTION_ALGORITHM          166
+# define ASN1_R_UNSUPPORTED_PUBLIC_KEY_TYPE               167
+# define ASN1_R_UNSUPPORTED_TYPE                          196
+# define ASN1_R_WRONG_PUBLIC_KEY_TYPE                     200
+# define ASN1_R_WRONG_TAG                                 168
+# define ASN1_R_WRONG_TYPE                                169
+
+# ifdef  __cplusplus
+}
+# endif
+#endif

+ 579 - 0
libssh2/openssl/include/openssl/asn1_mac.h

@@ -0,0 +1,579 @@
+/* crypto/asn1/asn1_mac.h */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * 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 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. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    "This product includes cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``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 AUTHOR OR CONTRIBUTORS 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.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+#ifndef HEADER_ASN1_MAC_H
+# define HEADER_ASN1_MAC_H
+
+# include <openssl/asn1.h>
+
+#ifdef  __cplusplus
+extern "C" {
+#endif
+
+# ifndef ASN1_MAC_ERR_LIB
+#  define ASN1_MAC_ERR_LIB        ERR_LIB_ASN1
+# endif
+
+# define ASN1_MAC_H_err(f,r,line) \
+        ERR_PUT_error(ASN1_MAC_ERR_LIB,(f),(r),__FILE__,(line))
+
+# define M_ASN1_D2I_vars(a,type,func) \
+        ASN1_const_CTX c; \
+        type ret=NULL; \
+        \
+        c.pp=(const unsigned char **)pp; \
+        c.q= *(const unsigned char **)pp; \
+        c.error=ERR_R_NESTED_ASN1_ERROR; \
+        if ((a == NULL) || ((*a) == NULL)) \
+                { if ((ret=(type)func()) == NULL) \
+                        { c.line=__LINE__; goto err; } } \
+        else    ret=(*a);
+
+# define M_ASN1_D2I_Init() \
+        c.p= *(const unsigned char **)pp; \
+        c.max=(length == 0)?0:(c.p+length);
+
+# define M_ASN1_D2I_Finish_2(a) \
+        if (!asn1_const_Finish(&c)) \
+                { c.line=__LINE__; goto err; } \
+        *(const unsigned char **)pp=c.p; \
+        if (a != NULL) (*a)=ret; \
+        return(ret);
+
+# define M_ASN1_D2I_Finish(a,func,e) \
+        M_ASN1_D2I_Finish_2(a); \
+err:\
+        ASN1_MAC_H_err((e),c.error,c.line); \
+        asn1_add_error(*(const unsigned char **)pp,(int)(c.q- *pp)); \
+        if ((ret != NULL) && ((a == NULL) || (*a != ret))) func(ret); \
+        return(NULL)
+
+# define M_ASN1_D2I_start_sequence() \
+        if (!asn1_GetSequence(&c,&length)) \
+                { c.line=__LINE__; goto err; }
+/* Begin reading ASN1 without a surrounding sequence */
+# define M_ASN1_D2I_begin() \
+        c.slen = length;
+
+/* End reading ASN1 with no check on length */
+# define M_ASN1_D2I_Finish_nolen(a, func, e) \
+        *pp=c.p; \
+        if (a != NULL) (*a)=ret; \
+        return(ret); \
+err:\
+        ASN1_MAC_H_err((e),c.error,c.line); \
+        asn1_add_error(*pp,(int)(c.q- *pp)); \
+        if ((ret != NULL) && ((a == NULL) || (*a != ret))) func(ret); \
+        return(NULL)
+
+# define M_ASN1_D2I_end_sequence() \
+        (((c.inf&1) == 0)?(c.slen <= 0): \
+                (c.eos=ASN1_const_check_infinite_end(&c.p,c.slen)))
+
+/* Don't use this with d2i_ASN1_BOOLEAN() */
+# define M_ASN1_D2I_get(b, func) \
+        c.q=c.p; \
+        if (func(&(b),&c.p,c.slen) == NULL) \
+                {c.line=__LINE__; goto err; } \
+        c.slen-=(c.p-c.q);
+
+/* Don't use this with d2i_ASN1_BOOLEAN() */
+# define M_ASN1_D2I_get_x(type,b,func) \
+        c.q=c.p; \
+        if (((D2I_OF(type))func)(&(b),&c.p,c.slen) == NULL) \
+                {c.line=__LINE__; goto err; } \
+        c.slen-=(c.p-c.q);
+
+/* use this instead () */
+# define M_ASN1_D2I_get_int(b,func) \
+        c.q=c.p; \
+        if (func(&(b),&c.p,c.slen) < 0) \
+                {c.line=__LINE__; goto err; } \
+        c.slen-=(c.p-c.q);
+
+# define M_ASN1_D2I_get_opt(b,func,type) \
+        if ((c.slen != 0) && ((M_ASN1_next & (~V_ASN1_CONSTRUCTED)) \
+                == (V_ASN1_UNIVERSAL|(type)))) \
+                { \
+                M_ASN1_D2I_get(b,func); \
+                }
+
+# define M_ASN1_D2I_get_int_opt(b,func,type) \
+        if ((c.slen != 0) && ((M_ASN1_next & (~V_ASN1_CONSTRUCTED)) \
+                == (V_ASN1_UNIVERSAL|(type)))) \
+                { \
+                M_ASN1_D2I_get_int(b,func); \
+                }
+
+# define M_ASN1_D2I_get_imp(b,func, type) \
+        M_ASN1_next=(_tmp& V_ASN1_CONSTRUCTED)|type; \
+        c.q=c.p; \
+        if (func(&(b),&c.p,c.slen) == NULL) \
+                {c.line=__LINE__; M_ASN1_next_prev = _tmp; goto err; } \
+        c.slen-=(c.p-c.q);\
+        M_ASN1_next_prev=_tmp;
+
+# define M_ASN1_D2I_get_IMP_opt(b,func,tag,type) \
+        if ((c.slen != 0) && ((M_ASN1_next & (~V_ASN1_CONSTRUCTED)) == \
+                (V_ASN1_CONTEXT_SPECIFIC|(tag)))) \
+                { \
+                unsigned char _tmp = M_ASN1_next; \
+                M_ASN1_D2I_get_imp(b,func, type);\
+                }
+
+# define M_ASN1_D2I_get_set(r,func,free_func) \
+                M_ASN1_D2I_get_imp_set(r,func,free_func, \
+                        V_ASN1_SET,V_ASN1_UNIVERSAL);
+
+# define M_ASN1_D2I_get_set_type(type,r,func,free_func) \
+                M_ASN1_D2I_get_imp_set_type(type,r,func,free_func, \
+                        V_ASN1_SET,V_ASN1_UNIVERSAL);
+
+# define M_ASN1_D2I_get_set_opt(r,func,free_func) \
+        if ((c.slen != 0) && (M_ASN1_next == (V_ASN1_UNIVERSAL| \
+                V_ASN1_CONSTRUCTED|V_ASN1_SET)))\
+                { M_ASN1_D2I_get_set(r,func,free_func); }
+
+# define M_ASN1_D2I_get_set_opt_type(type,r,func,free_func) \
+        if ((c.slen != 0) && (M_ASN1_next == (V_ASN1_UNIVERSAL| \
+                V_ASN1_CONSTRUCTED|V_ASN1_SET)))\
+                { M_ASN1_D2I_get_set_type(type,r,func,free_func); }
+
+# define M_ASN1_I2D_len_SET_opt(a,f) \
+        if ((a != NULL) && (sk_num(a) != 0)) \
+                M_ASN1_I2D_len_SET(a,f);
+
+# define M_ASN1_I2D_put_SET_opt(a,f) \
+        if ((a != NULL) && (sk_num(a) != 0)) \
+                M_ASN1_I2D_put_SET(a,f);
+
+# define M_ASN1_I2D_put_SEQUENCE_opt(a,f) \
+        if ((a != NULL) && (sk_num(a) != 0)) \
+                M_ASN1_I2D_put_SEQUENCE(a,f);
+
+# define M_ASN1_I2D_put_SEQUENCE_opt_type(type,a,f) \
+        if ((a != NULL) && (sk_##type##_num(a) != 0)) \
+                M_ASN1_I2D_put_SEQUENCE_type(type,a,f);
+
+# define M_ASN1_D2I_get_IMP_set_opt(b,func,free_func,tag) \
+        if ((c.slen != 0) && \
+                (M_ASN1_next == \
+                (V_ASN1_CONTEXT_SPECIFIC|V_ASN1_CONSTRUCTED|(tag))))\
+                { \
+                M_ASN1_D2I_get_imp_set(b,func,free_func,\
+                        tag,V_ASN1_CONTEXT_SPECIFIC); \
+                }
+
+# define M_ASN1_D2I_get_IMP_set_opt_type(type,b,func,free_func,tag) \
+        if ((c.slen != 0) && \
+                (M_ASN1_next == \
+                (V_ASN1_CONTEXT_SPECIFIC|V_ASN1_CONSTRUCTED|(tag))))\
+                { \
+                M_ASN1_D2I_get_imp_set_type(type,b,func,free_func,\
+                        tag,V_ASN1_CONTEXT_SPECIFIC); \
+                }
+
+# define M_ASN1_D2I_get_seq(r,func,free_func) \
+                M_ASN1_D2I_get_imp_set(r,func,free_func,\
+                        V_ASN1_SEQUENCE,V_ASN1_UNIVERSAL);
+
+# define M_ASN1_D2I_get_seq_type(type,r,func,free_func) \
+                M_ASN1_D2I_get_imp_set_type(type,r,func,free_func,\
+                                            V_ASN1_SEQUENCE,V_ASN1_UNIVERSAL)
+
+# define M_ASN1_D2I_get_seq_opt(r,func,free_func) \
+        if ((c.slen != 0) && (M_ASN1_next == (V_ASN1_UNIVERSAL| \
+                V_ASN1_CONSTRUCTED|V_ASN1_SEQUENCE)))\
+                { M_ASN1_D2I_get_seq(r,func,free_func); }
+
+# define M_ASN1_D2I_get_seq_opt_type(type,r,func,free_func) \
+        if ((c.slen != 0) && (M_ASN1_next == (V_ASN1_UNIVERSAL| \
+                V_ASN1_CONSTRUCTED|V_ASN1_SEQUENCE)))\
+                { M_ASN1_D2I_get_seq_type(type,r,func,free_func); }
+
+# define M_ASN1_D2I_get_IMP_set(r,func,free_func,x) \
+                M_ASN1_D2I_get_imp_set(r,func,free_func,\
+                        x,V_ASN1_CONTEXT_SPECIFIC);
+
+# define M_ASN1_D2I_get_IMP_set_type(type,r,func,free_func,x) \
+                M_ASN1_D2I_get_imp_set_type(type,r,func,free_func,\
+                        x,V_ASN1_CONTEXT_SPECIFIC);
+
+# define M_ASN1_D2I_get_imp_set(r,func,free_func,a,b) \
+        c.q=c.p; \
+        if (d2i_ASN1_SET(&(r),&c.p,c.slen,(char *(*)())func,\
+                (void (*)())free_func,a,b) == NULL) \
+                { c.line=__LINE__; goto err; } \
+        c.slen-=(c.p-c.q);
+
+# define M_ASN1_D2I_get_imp_set_type(type,r,func,free_func,a,b) \
+        c.q=c.p; \
+        if (d2i_ASN1_SET_OF_##type(&(r),&c.p,c.slen,func,\
+                                   free_func,a,b) == NULL) \
+                { c.line=__LINE__; goto err; } \
+        c.slen-=(c.p-c.q);
+
+# define M_ASN1_D2I_get_set_strings(r,func,a,b) \
+        c.q=c.p; \
+        if (d2i_ASN1_STRING_SET(&(r),&c.p,c.slen,a,b) == NULL) \
+                { c.line=__LINE__; goto err; } \
+        c.slen-=(c.p-c.q);
+
+# define M_ASN1_D2I_get_EXP_opt(r,func,tag) \
+        if ((c.slen != 0L) && (M_ASN1_next == \
+                (V_ASN1_CONSTRUCTED|V_ASN1_CONTEXT_SPECIFIC|tag))) \
+                { \
+                int Tinf,Ttag,Tclass; \
+                long Tlen; \
+                \
+                c.q=c.p; \
+                Tinf=ASN1_get_object(&c.p,&Tlen,&Ttag,&Tclass,c.slen); \
+                if (Tinf & 0x80) \
+                        { c.error=ERR_R_BAD_ASN1_OBJECT_HEADER; \
+                        c.line=__LINE__; goto err; } \
+                if (Tinf == (V_ASN1_CONSTRUCTED+1)) \
+                                        Tlen = c.slen - (c.p - c.q) - 2; \
+                if (func(&(r),&c.p,Tlen) == NULL) \
+                        { c.line=__LINE__; goto err; } \
+                if (Tinf == (V_ASN1_CONSTRUCTED+1)) { \
+                        Tlen = c.slen - (c.p - c.q); \
+                        if(!ASN1_const_check_infinite_end(&c.p, Tlen)) \
+                                { c.error=ERR_R_MISSING_ASN1_EOS; \
+                                c.line=__LINE__; goto err; } \
+                }\
+                c.slen-=(c.p-c.q); \
+                }
+
+# define M_ASN1_D2I_get_EXP_set_opt(r,func,free_func,tag,b) \
+        if ((c.slen != 0) && (M_ASN1_next == \
+                (V_ASN1_CONSTRUCTED|V_ASN1_CONTEXT_SPECIFIC|tag))) \
+                { \
+                int Tinf,Ttag,Tclass; \
+                long Tlen; \
+                \
+                c.q=c.p; \
+                Tinf=ASN1_get_object(&c.p,&Tlen,&Ttag,&Tclass,c.slen); \
+                if (Tinf & 0x80) \
+                        { c.error=ERR_R_BAD_ASN1_OBJECT_HEADER; \
+                        c.line=__LINE__; goto err; } \
+                if (Tinf == (V_ASN1_CONSTRUCTED+1)) \
+                                        Tlen = c.slen - (c.p - c.q) - 2; \
+                if (d2i_ASN1_SET(&(r),&c.p,Tlen,(char *(*)())func, \
+                        (void (*)())free_func, \
+                        b,V_ASN1_UNIVERSAL) == NULL) \
+                        { c.line=__LINE__; goto err; } \
+                if (Tinf == (V_ASN1_CONSTRUCTED+1)) { \
+                        Tlen = c.slen - (c.p - c.q); \
+                        if(!ASN1_check_infinite_end(&c.p, Tlen)) \
+                                { c.error=ERR_R_MISSING_ASN1_EOS; \
+                                c.line=__LINE__; goto err; } \
+                }\
+                c.slen-=(c.p-c.q); \
+                }
+
+# define M_ASN1_D2I_get_EXP_set_opt_type(type,r,func,free_func,tag,b) \
+        if ((c.slen != 0) && (M_ASN1_next == \
+                (V_ASN1_CONSTRUCTED|V_ASN1_CONTEXT_SPECIFIC|tag))) \
+                { \
+                int Tinf,Ttag,Tclass; \
+                long Tlen; \
+                \
+                c.q=c.p; \
+                Tinf=ASN1_get_object(&c.p,&Tlen,&Ttag,&Tclass,c.slen); \
+                if (Tinf & 0x80) \
+                        { c.error=ERR_R_BAD_ASN1_OBJECT_HEADER; \
+                        c.line=__LINE__; goto err; } \
+                if (Tinf == (V_ASN1_CONSTRUCTED+1)) \
+                                        Tlen = c.slen - (c.p - c.q) - 2; \
+                if (d2i_ASN1_SET_OF_##type(&(r),&c.p,Tlen,func, \
+                        free_func,b,V_ASN1_UNIVERSAL) == NULL) \
+                        { c.line=__LINE__; goto err; } \
+                if (Tinf == (V_ASN1_CONSTRUCTED+1)) { \
+                        Tlen = c.slen - (c.p - c.q); \
+                        if(!ASN1_check_infinite_end(&c.p, Tlen)) \
+                                { c.error=ERR_R_MISSING_ASN1_EOS; \
+                                c.line=__LINE__; goto err; } \
+                }\
+                c.slen-=(c.p-c.q); \
+                }
+
+/* New macros */
+# define M_ASN1_New_Malloc(ret,type) \
+        if ((ret=(type *)OPENSSL_malloc(sizeof(type))) == NULL) \
+                { c.line=__LINE__; goto err2; }
+
+# define M_ASN1_New(arg,func) \
+        if (((arg)=func()) == NULL) return(NULL)
+
+# define M_ASN1_New_Error(a) \
+/*-     err:    ASN1_MAC_H_err((a),ERR_R_NESTED_ASN1_ERROR,c.line); \
+                return(NULL);*/ \
+        err2:   ASN1_MAC_H_err((a),ERR_R_MALLOC_FAILURE,c.line); \
+                return(NULL)
+
+/*
+ * BIG UGLY WARNING! This is so damn ugly I wanna puke.  Unfortunately, some
+ * macros that use ASN1_const_CTX still insist on writing in the input
+ * stream.  ARGH! ARGH! ARGH! Let's get rid of this macro package. Please? --
+ * Richard Levitte
+ */
+# define M_ASN1_next             (*((unsigned char *)(c.p)))
+# define M_ASN1_next_prev        (*((unsigned char *)(c.q)))
+
+/*************************************************/
+
+# define M_ASN1_I2D_vars(a)      int r=0,ret=0; \
+                                unsigned char *p; \
+                                if (a == NULL) return(0)
+
+/* Length Macros */
+# define M_ASN1_I2D_len(a,f)     ret+=f(a,NULL)
+# define M_ASN1_I2D_len_IMP_opt(a,f)     if (a != NULL) M_ASN1_I2D_len(a,f)
+
+# define M_ASN1_I2D_len_SET(a,f) \
+                ret+=i2d_ASN1_SET(a,NULL,f,V_ASN1_SET,V_ASN1_UNIVERSAL,IS_SET);
+
+# define M_ASN1_I2D_len_SET_type(type,a,f) \
+                ret+=i2d_ASN1_SET_OF_##type(a,NULL,f,V_ASN1_SET, \
+                                            V_ASN1_UNIVERSAL,IS_SET);
+
+# define M_ASN1_I2D_len_SEQUENCE(a,f) \
+                ret+=i2d_ASN1_SET(a,NULL,f,V_ASN1_SEQUENCE,V_ASN1_UNIVERSAL, \
+                                  IS_SEQUENCE);
+
+# define M_ASN1_I2D_len_SEQUENCE_type(type,a,f) \
+                ret+=i2d_ASN1_SET_OF_##type(a,NULL,f,V_ASN1_SEQUENCE, \
+                                            V_ASN1_UNIVERSAL,IS_SEQUENCE)
+
+# define M_ASN1_I2D_len_SEQUENCE_opt(a,f) \
+                if ((a != NULL) && (sk_num(a) != 0)) \
+                        M_ASN1_I2D_len_SEQUENCE(a,f);
+
+# define M_ASN1_I2D_len_SEQUENCE_opt_type(type,a,f) \
+                if ((a != NULL) && (sk_##type##_num(a) != 0)) \
+                        M_ASN1_I2D_len_SEQUENCE_type(type,a,f);
+
+# define M_ASN1_I2D_len_IMP_SET(a,f,x) \
+                ret+=i2d_ASN1_SET(a,NULL,f,x,V_ASN1_CONTEXT_SPECIFIC,IS_SET);
+
+# define M_ASN1_I2D_len_IMP_SET_type(type,a,f,x) \
+                ret+=i2d_ASN1_SET_OF_##type(a,NULL,f,x, \
+                                            V_ASN1_CONTEXT_SPECIFIC,IS_SET);
+
+# define M_ASN1_I2D_len_IMP_SET_opt(a,f,x) \
+                if ((a != NULL) && (sk_num(a) != 0)) \
+                        ret+=i2d_ASN1_SET(a,NULL,f,x,V_ASN1_CONTEXT_SPECIFIC, \
+                                          IS_SET);
+
+# define M_ASN1_I2D_len_IMP_SET_opt_type(type,a,f,x) \
+                if ((a != NULL) && (sk_##type##_num(a) != 0)) \
+                        ret+=i2d_ASN1_SET_OF_##type(a,NULL,f,x, \
+                                               V_ASN1_CONTEXT_SPECIFIC,IS_SET);
+
+# define M_ASN1_I2D_len_IMP_SEQUENCE(a,f,x) \
+                ret+=i2d_ASN1_SET(a,NULL,f,x,V_ASN1_CONTEXT_SPECIFIC, \
+                                  IS_SEQUENCE);
+
+# define M_ASN1_I2D_len_IMP_SEQUENCE_opt(a,f,x) \
+                if ((a != NULL) && (sk_num(a) != 0)) \
+                        ret+=i2d_ASN1_SET(a,NULL,f,x,V_ASN1_CONTEXT_SPECIFIC, \
+                                          IS_SEQUENCE);
+
+# define M_ASN1_I2D_len_IMP_SEQUENCE_opt_type(type,a,f,x) \
+                if ((a != NULL) && (sk_##type##_num(a) != 0)) \
+                        ret+=i2d_ASN1_SET_OF_##type(a,NULL,f,x, \
+                                                    V_ASN1_CONTEXT_SPECIFIC, \
+                                                    IS_SEQUENCE);
+
+# define M_ASN1_I2D_len_EXP_opt(a,f,mtag,v) \
+                if (a != NULL)\
+                        { \
+                        v=f(a,NULL); \
+                        ret+=ASN1_object_size(1,v,mtag); \
+                        }
+
+# define M_ASN1_I2D_len_EXP_SET_opt(a,f,mtag,tag,v) \
+                if ((a != NULL) && (sk_num(a) != 0))\
+                        { \
+                        v=i2d_ASN1_SET(a,NULL,f,tag,V_ASN1_UNIVERSAL,IS_SET); \
+                        ret+=ASN1_object_size(1,v,mtag); \
+                        }
+
+# define M_ASN1_I2D_len_EXP_SEQUENCE_opt(a,f,mtag,tag,v) \
+                if ((a != NULL) && (sk_num(a) != 0))\
+                        { \
+                        v=i2d_ASN1_SET(a,NULL,f,tag,V_ASN1_UNIVERSAL, \
+                                       IS_SEQUENCE); \
+                        ret+=ASN1_object_size(1,v,mtag); \
+                        }
+
+# define M_ASN1_I2D_len_EXP_SEQUENCE_opt_type(type,a,f,mtag,tag,v) \
+                if ((a != NULL) && (sk_##type##_num(a) != 0))\
+                        { \
+                        v=i2d_ASN1_SET_OF_##type(a,NULL,f,tag, \
+                                                 V_ASN1_UNIVERSAL, \
+                                                 IS_SEQUENCE); \
+                        ret+=ASN1_object_size(1,v,mtag); \
+                        }
+
+/* Put Macros */
+# define M_ASN1_I2D_put(a,f)     f(a,&p)
+
+# define M_ASN1_I2D_put_IMP_opt(a,f,t)   \
+                if (a != NULL) \
+                        { \
+                        unsigned char *q=p; \
+                        f(a,&p); \
+                        *q=(V_ASN1_CONTEXT_SPECIFIC|t|(*q&V_ASN1_CONSTRUCTED));\
+                        }
+
+# define M_ASN1_I2D_put_SET(a,f) i2d_ASN1_SET(a,&p,f,V_ASN1_SET,\
+                        V_ASN1_UNIVERSAL,IS_SET)
+# define M_ASN1_I2D_put_SET_type(type,a,f) \
+     i2d_ASN1_SET_OF_##type(a,&p,f,V_ASN1_SET,V_ASN1_UNIVERSAL,IS_SET)
+# define M_ASN1_I2D_put_IMP_SET(a,f,x) i2d_ASN1_SET(a,&p,f,x,\
+                        V_ASN1_CONTEXT_SPECIFIC,IS_SET)
+# define M_ASN1_I2D_put_IMP_SET_type(type,a,f,x) \
+     i2d_ASN1_SET_OF_##type(a,&p,f,x,V_ASN1_CONTEXT_SPECIFIC,IS_SET)
+# define M_ASN1_I2D_put_IMP_SEQUENCE(a,f,x) i2d_ASN1_SET(a,&p,f,x,\
+                        V_ASN1_CONTEXT_SPECIFIC,IS_SEQUENCE)
+
+# define M_ASN1_I2D_put_SEQUENCE(a,f) i2d_ASN1_SET(a,&p,f,V_ASN1_SEQUENCE,\
+                                             V_ASN1_UNIVERSAL,IS_SEQUENCE)
+
+# define M_ASN1_I2D_put_SEQUENCE_type(type,a,f) \
+     i2d_ASN1_SET_OF_##type(a,&p,f,V_ASN1_SEQUENCE,V_ASN1_UNIVERSAL, \
+                            IS_SEQUENCE)
+
+# define M_ASN1_I2D_put_SEQUENCE_opt(a,f) \
+                if ((a != NULL) && (sk_num(a) != 0)) \
+                        M_ASN1_I2D_put_SEQUENCE(a,f);
+
+# define M_ASN1_I2D_put_IMP_SET_opt(a,f,x) \
+                if ((a != NULL) && (sk_num(a) != 0)) \
+                        { i2d_ASN1_SET(a,&p,f,x,V_ASN1_CONTEXT_SPECIFIC, \
+                                       IS_SET); }
+
+# define M_ASN1_I2D_put_IMP_SET_opt_type(type,a,f,x) \
+                if ((a != NULL) && (sk_##type##_num(a) != 0)) \
+                        { i2d_ASN1_SET_OF_##type(a,&p,f,x, \
+                                                 V_ASN1_CONTEXT_SPECIFIC, \
+                                                 IS_SET); }
+
+# define M_ASN1_I2D_put_IMP_SEQUENCE_opt(a,f,x) \
+                if ((a != NULL) && (sk_num(a) != 0)) \
+                        { i2d_ASN1_SET(a,&p,f,x,V_ASN1_CONTEXT_SPECIFIC, \
+                                       IS_SEQUENCE); }
+
+# define M_ASN1_I2D_put_IMP_SEQUENCE_opt_type(type,a,f,x) \
+                if ((a != NULL) && (sk_##type##_num(a) != 0)) \
+                        { i2d_ASN1_SET_OF_##type(a,&p,f,x, \
+                                                 V_ASN1_CONTEXT_SPECIFIC, \
+                                                 IS_SEQUENCE); }
+
+# define M_ASN1_I2D_put_EXP_opt(a,f,tag,v) \
+                if (a != NULL) \
+                        { \
+                        ASN1_put_object(&p,1,v,tag,V_ASN1_CONTEXT_SPECIFIC); \
+                        f(a,&p); \
+                        }
+
+# define M_ASN1_I2D_put_EXP_SET_opt(a,f,mtag,tag,v) \
+                if ((a != NULL) && (sk_num(a) != 0)) \
+                        { \
+                        ASN1_put_object(&p,1,v,mtag,V_ASN1_CONTEXT_SPECIFIC); \
+                        i2d_ASN1_SET(a,&p,f,tag,V_ASN1_UNIVERSAL,IS_SET); \
+                        }
+
+# define M_ASN1_I2D_put_EXP_SEQUENCE_opt(a,f,mtag,tag,v) \
+                if ((a != NULL) && (sk_num(a) != 0)) \
+                        { \
+                        ASN1_put_object(&p,1,v,mtag,V_ASN1_CONTEXT_SPECIFIC); \
+                        i2d_ASN1_SET(a,&p,f,tag,V_ASN1_UNIVERSAL,IS_SEQUENCE); \
+                        }
+
+# define M_ASN1_I2D_put_EXP_SEQUENCE_opt_type(type,a,f,mtag,tag,v) \
+                if ((a != NULL) && (sk_##type##_num(a) != 0)) \
+                        { \
+                        ASN1_put_object(&p,1,v,mtag,V_ASN1_CONTEXT_SPECIFIC); \
+                        i2d_ASN1_SET_OF_##type(a,&p,f,tag,V_ASN1_UNIVERSAL, \
+                                               IS_SEQUENCE); \
+                        }
+
+# define M_ASN1_I2D_seq_total() \
+                r=ASN1_object_size(1,ret,V_ASN1_SEQUENCE); \
+                if (pp == NULL) return(r); \
+                p= *pp; \
+                ASN1_put_object(&p,1,ret,V_ASN1_SEQUENCE,V_ASN1_UNIVERSAL)
+
+# define M_ASN1_I2D_INF_seq_start(tag,ctx) \
+                *(p++)=(V_ASN1_CONSTRUCTED|(tag)|(ctx)); \
+                *(p++)=0x80
+
+# define M_ASN1_I2D_INF_seq_end() *(p++)=0x00; *(p++)=0x00
+
+# define M_ASN1_I2D_finish()     *pp=p; \
+                                return(r);
+
+int asn1_GetSequence(ASN1_const_CTX *c, long *length);
+void asn1_add_error(const unsigned char *address, int offset);
+#ifdef  __cplusplus
+}
+#endif
+
+#endif

+ 973 - 0
libssh2/openssl/include/openssl/asn1t.h

@@ -0,0 +1,973 @@
+/* asn1t.h */
+/*
+ * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL project
+ * 2000.
+ */
+/* ====================================================================
+ * Copyright (c) 2000-2005 The OpenSSL 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. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    licensing@OpenSSL.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED 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 OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS 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.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com).  This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+#ifndef HEADER_ASN1T_H
+# define HEADER_ASN1T_H
+
+# include <stddef.h>
+# include <openssl/e_os2.h>
+# include <openssl/asn1.h>
+
+# ifdef OPENSSL_BUILD_SHLIBCRYPTO
+#  undef OPENSSL_EXTERN
+#  define OPENSSL_EXTERN OPENSSL_EXPORT
+# endif
+
+/* ASN1 template defines, structures and functions */
+
+#ifdef  __cplusplus
+extern "C" {
+#endif
+
+# ifndef OPENSSL_EXPORT_VAR_AS_FUNCTION
+
+/* Macro to obtain ASN1_ADB pointer from a type (only used internally) */
+#  define ASN1_ADB_ptr(iptr) ((const ASN1_ADB *)(iptr))
+
+/* Macros for start and end of ASN1_ITEM definition */
+
+#  define ASN1_ITEM_start(itname) \
+        OPENSSL_GLOBAL const ASN1_ITEM itname##_it = {
+
+#  define ASN1_ITEM_end(itname) \
+                };
+
+# else
+
+/* Macro to obtain ASN1_ADB pointer from a type (only used internally) */
+#  define ASN1_ADB_ptr(iptr) ((const ASN1_ADB *)(iptr()))
+
+/* Macros for start and end of ASN1_ITEM definition */
+
+#  define ASN1_ITEM_start(itname) \
+        const ASN1_ITEM * itname##_it(void) \
+        { \
+                static const ASN1_ITEM local_it = {
+
+#  define ASN1_ITEM_end(itname) \
+                }; \
+        return &local_it; \
+        }
+
+# endif
+
+/* Macros to aid ASN1 template writing */
+
+# define ASN1_ITEM_TEMPLATE(tname) \
+        static const ASN1_TEMPLATE tname##_item_tt
+
+# define ASN1_ITEM_TEMPLATE_END(tname) \
+        ;\
+        ASN1_ITEM_start(tname) \
+                ASN1_ITYPE_PRIMITIVE,\
+                -1,\
+                &tname##_item_tt,\
+                0,\
+                NULL,\
+                0,\
+                #tname \
+        ASN1_ITEM_end(tname)
+
+/* This is a ASN1 type which just embeds a template */
+
+/*-
+ * This pair helps declare a SEQUENCE. We can do:
+ *
+ *      ASN1_SEQUENCE(stname) = {
+ *              ... SEQUENCE components ...
+ *      } ASN1_SEQUENCE_END(stname)
+ *
+ *      This will produce an ASN1_ITEM called stname_it
+ *      for a structure called stname.
+ *
+ *      If you want the same structure but a different
+ *      name then use:
+ *
+ *      ASN1_SEQUENCE(itname) = {
+ *              ... SEQUENCE components ...
+ *      } ASN1_SEQUENCE_END_name(stname, itname)
+ *
+ *      This will create an item called itname_it using
+ *      a structure called stname.
+ */
+
+# define ASN1_SEQUENCE(tname) \
+        static const ASN1_TEMPLATE tname##_seq_tt[]
+
+# define ASN1_SEQUENCE_END(stname) ASN1_SEQUENCE_END_name(stname, stname)
+
+# define ASN1_SEQUENCE_END_name(stname, tname) \
+        ;\
+        ASN1_ITEM_start(tname) \
+                ASN1_ITYPE_SEQUENCE,\
+                V_ASN1_SEQUENCE,\
+                tname##_seq_tt,\
+                sizeof(tname##_seq_tt) / sizeof(ASN1_TEMPLATE),\
+                NULL,\
+                sizeof(stname),\
+                #stname \
+        ASN1_ITEM_end(tname)
+
+# define ASN1_NDEF_SEQUENCE(tname) \
+        ASN1_SEQUENCE(tname)
+
+# define ASN1_NDEF_SEQUENCE_cb(tname, cb) \
+        ASN1_SEQUENCE_cb(tname, cb)
+
+# define ASN1_SEQUENCE_cb(tname, cb) \
+        static const ASN1_AUX tname##_aux = {NULL, 0, 0, 0, cb, 0}; \
+        ASN1_SEQUENCE(tname)
+
+# define ASN1_BROKEN_SEQUENCE(tname) \
+        static const ASN1_AUX tname##_aux = {NULL, ASN1_AFLG_BROKEN, 0, 0, 0, 0}; \
+        ASN1_SEQUENCE(tname)
+
+# define ASN1_SEQUENCE_ref(tname, cb, lck) \
+        static const ASN1_AUX tname##_aux = {NULL, ASN1_AFLG_REFCOUNT, offsetof(tname, references), lck, cb, 0}; \
+        ASN1_SEQUENCE(tname)
+
+# define ASN1_SEQUENCE_enc(tname, enc, cb) \
+        static const ASN1_AUX tname##_aux = {NULL, ASN1_AFLG_ENCODING, 0, 0, cb, offsetof(tname, enc)}; \
+        ASN1_SEQUENCE(tname)
+
+# define ASN1_NDEF_SEQUENCE_END(tname) \
+        ;\
+        ASN1_ITEM_start(tname) \
+                ASN1_ITYPE_NDEF_SEQUENCE,\
+                V_ASN1_SEQUENCE,\
+                tname##_seq_tt,\
+                sizeof(tname##_seq_tt) / sizeof(ASN1_TEMPLATE),\
+                NULL,\
+                sizeof(tname),\
+                #tname \
+        ASN1_ITEM_end(tname)
+
+# define ASN1_BROKEN_SEQUENCE_END(stname) ASN1_SEQUENCE_END_ref(stname, stname)
+
+# define ASN1_SEQUENCE_END_enc(stname, tname) ASN1_SEQUENCE_END_ref(stname, tname)
+
+# define ASN1_SEQUENCE_END_cb(stname, tname) ASN1_SEQUENCE_END_ref(stname, tname)
+
+# define ASN1_SEQUENCE_END_ref(stname, tname) \
+        ;\
+        ASN1_ITEM_start(tname) \
+                ASN1_ITYPE_SEQUENCE,\
+                V_ASN1_SEQUENCE,\
+                tname##_seq_tt,\
+                sizeof(tname##_seq_tt) / sizeof(ASN1_TEMPLATE),\
+                &tname##_aux,\
+                sizeof(stname),\
+                #stname \
+        ASN1_ITEM_end(tname)
+
+# define ASN1_NDEF_SEQUENCE_END_cb(stname, tname) \
+        ;\
+        ASN1_ITEM_start(tname) \
+                ASN1_ITYPE_NDEF_SEQUENCE,\
+                V_ASN1_SEQUENCE,\
+                tname##_seq_tt,\
+                sizeof(tname##_seq_tt) / sizeof(ASN1_TEMPLATE),\
+                &tname##_aux,\
+                sizeof(stname),\
+                #stname \
+        ASN1_ITEM_end(tname)
+
+/*-
+ * This pair helps declare a CHOICE type. We can do:
+ *
+ *      ASN1_CHOICE(chname) = {
+ *              ... CHOICE options ...
+ *      ASN1_CHOICE_END(chname)
+ *
+ *      This will produce an ASN1_ITEM called chname_it
+ *      for a structure called chname. The structure
+ *      definition must look like this:
+ *      typedef struct {
+ *              int type;
+ *              union {
+ *                      ASN1_SOMETHING *opt1;
+ *                      ASN1_SOMEOTHER *opt2;
+ *              } value;
+ *      } chname;
+ *
+ *      the name of the selector must be 'type'.
+ *      to use an alternative selector name use the
+ *      ASN1_CHOICE_END_selector() version.
+ */
+
+# define ASN1_CHOICE(tname) \
+        static const ASN1_TEMPLATE tname##_ch_tt[]
+
+# define ASN1_CHOICE_cb(tname, cb) \
+        static const ASN1_AUX tname##_aux = {NULL, 0, 0, 0, cb, 0}; \
+        ASN1_CHOICE(tname)
+
+# define ASN1_CHOICE_END(stname) ASN1_CHOICE_END_name(stname, stname)
+
+# define ASN1_CHOICE_END_name(stname, tname) ASN1_CHOICE_END_selector(stname, tname, type)
+
+# define ASN1_CHOICE_END_selector(stname, tname, selname) \
+        ;\
+        ASN1_ITEM_start(tname) \
+                ASN1_ITYPE_CHOICE,\
+                offsetof(stname,selname) ,\
+                tname##_ch_tt,\
+                sizeof(tname##_ch_tt) / sizeof(ASN1_TEMPLATE),\
+                NULL,\
+                sizeof(stname),\
+                #stname \
+        ASN1_ITEM_end(tname)
+
+# define ASN1_CHOICE_END_cb(stname, tname, selname) \
+        ;\
+        ASN1_ITEM_start(tname) \
+                ASN1_ITYPE_CHOICE,\
+                offsetof(stname,selname) ,\
+                tname##_ch_tt,\
+                sizeof(tname##_ch_tt) / sizeof(ASN1_TEMPLATE),\
+                &tname##_aux,\
+                sizeof(stname),\
+                #stname \
+        ASN1_ITEM_end(tname)
+
+/* This helps with the template wrapper form of ASN1_ITEM */
+
+# define ASN1_EX_TEMPLATE_TYPE(flags, tag, name, type) { \
+        (flags), (tag), 0,\
+        #name, ASN1_ITEM_ref(type) }
+
+/* These help with SEQUENCE or CHOICE components */
+
+/* used to declare other types */
+
+# define ASN1_EX_TYPE(flags, tag, stname, field, type) { \
+        (flags), (tag), offsetof(stname, field),\
+        #field, ASN1_ITEM_ref(type) }
+
+/* used when the structure is combined with the parent */
+
+# define ASN1_EX_COMBINE(flags, tag, type) { \
+        (flags)|ASN1_TFLG_COMBINE, (tag), 0, NULL, ASN1_ITEM_ref(type) }
+
+/* implicit and explicit helper macros */
+
+# define ASN1_IMP_EX(stname, field, type, tag, ex) \
+                ASN1_EX_TYPE(ASN1_TFLG_IMPLICIT | ex, tag, stname, field, type)
+
+# define ASN1_EXP_EX(stname, field, type, tag, ex) \
+                ASN1_EX_TYPE(ASN1_TFLG_EXPLICIT | ex, tag, stname, field, type)
+
+/* Any defined by macros: the field used is in the table itself */
+
+# ifndef OPENSSL_EXPORT_VAR_AS_FUNCTION
+#  define ASN1_ADB_OBJECT(tblname) { ASN1_TFLG_ADB_OID, -1, 0, #tblname, (const ASN1_ITEM *)&(tblname##_adb) }
+#  define ASN1_ADB_INTEGER(tblname) { ASN1_TFLG_ADB_INT, -1, 0, #tblname, (const ASN1_ITEM *)&(tblname##_adb) }
+# else
+#  define ASN1_ADB_OBJECT(tblname) { ASN1_TFLG_ADB_OID, -1, 0, #tblname, tblname##_adb }
+#  define ASN1_ADB_INTEGER(tblname) { ASN1_TFLG_ADB_INT, -1, 0, #tblname, tblname##_adb }
+# endif
+/* Plain simple type */
+# define ASN1_SIMPLE(stname, field, type) ASN1_EX_TYPE(0,0, stname, field, type)
+
+/* OPTIONAL simple type */
+# define ASN1_OPT(stname, field, type) ASN1_EX_TYPE(ASN1_TFLG_OPTIONAL, 0, stname, field, type)
+
+/* IMPLICIT tagged simple type */
+# define ASN1_IMP(stname, field, type, tag) ASN1_IMP_EX(stname, field, type, tag, 0)
+
+/* IMPLICIT tagged OPTIONAL simple type */
+# define ASN1_IMP_OPT(stname, field, type, tag) ASN1_IMP_EX(stname, field, type, tag, ASN1_TFLG_OPTIONAL)
+
+/* Same as above but EXPLICIT */
+
+# define ASN1_EXP(stname, field, type, tag) ASN1_EXP_EX(stname, field, type, tag, 0)
+# define ASN1_EXP_OPT(stname, field, type, tag) ASN1_EXP_EX(stname, field, type, tag, ASN1_TFLG_OPTIONAL)
+
+/* SEQUENCE OF type */
+# define ASN1_SEQUENCE_OF(stname, field, type) \
+                ASN1_EX_TYPE(ASN1_TFLG_SEQUENCE_OF, 0, stname, field, type)
+
+/* OPTIONAL SEQUENCE OF */
+# define ASN1_SEQUENCE_OF_OPT(stname, field, type) \
+                ASN1_EX_TYPE(ASN1_TFLG_SEQUENCE_OF|ASN1_TFLG_OPTIONAL, 0, stname, field, type)
+
+/* Same as above but for SET OF */
+
+# define ASN1_SET_OF(stname, field, type) \
+                ASN1_EX_TYPE(ASN1_TFLG_SET_OF, 0, stname, field, type)
+
+# define ASN1_SET_OF_OPT(stname, field, type) \
+                ASN1_EX_TYPE(ASN1_TFLG_SET_OF|ASN1_TFLG_OPTIONAL, 0, stname, field, type)
+
+/* Finally compound types of SEQUENCE, SET, IMPLICIT, EXPLICIT and OPTIONAL */
+
+# define ASN1_IMP_SET_OF(stname, field, type, tag) \
+                        ASN1_IMP_EX(stname, field, type, tag, ASN1_TFLG_SET_OF)
+
+# define ASN1_EXP_SET_OF(stname, field, type, tag) \
+                        ASN1_EXP_EX(stname, field, type, tag, ASN1_TFLG_SET_OF)
+
+# define ASN1_IMP_SET_OF_OPT(stname, field, type, tag) \
+                        ASN1_IMP_EX(stname, field, type, tag, ASN1_TFLG_SET_OF|ASN1_TFLG_OPTIONAL)
+
+# define ASN1_EXP_SET_OF_OPT(stname, field, type, tag) \
+                        ASN1_EXP_EX(stname, field, type, tag, ASN1_TFLG_SET_OF|ASN1_TFLG_OPTIONAL)
+
+# define ASN1_IMP_SEQUENCE_OF(stname, field, type, tag) \
+                        ASN1_IMP_EX(stname, field, type, tag, ASN1_TFLG_SEQUENCE_OF)
+
+# define ASN1_IMP_SEQUENCE_OF_OPT(stname, field, type, tag) \
+                        ASN1_IMP_EX(stname, field, type, tag, ASN1_TFLG_SEQUENCE_OF|ASN1_TFLG_OPTIONAL)
+
+# define ASN1_EXP_SEQUENCE_OF(stname, field, type, tag) \
+                        ASN1_EXP_EX(stname, field, type, tag, ASN1_TFLG_SEQUENCE_OF)
+
+# define ASN1_EXP_SEQUENCE_OF_OPT(stname, field, type, tag) \
+                        ASN1_EXP_EX(stname, field, type, tag, ASN1_TFLG_SEQUENCE_OF|ASN1_TFLG_OPTIONAL)
+
+/* EXPLICIT using indefinite length constructed form */
+# define ASN1_NDEF_EXP(stname, field, type, tag) \
+                        ASN1_EXP_EX(stname, field, type, tag, ASN1_TFLG_NDEF)
+
+/* EXPLICIT OPTIONAL using indefinite length constructed form */
+# define ASN1_NDEF_EXP_OPT(stname, field, type, tag) \
+                        ASN1_EXP_EX(stname, field, type, tag, ASN1_TFLG_OPTIONAL|ASN1_TFLG_NDEF)
+
+/* Macros for the ASN1_ADB structure */
+
+# define ASN1_ADB(name) \
+        static const ASN1_ADB_TABLE name##_adbtbl[]
+
+# ifndef OPENSSL_EXPORT_VAR_AS_FUNCTION
+
+#  define ASN1_ADB_END(name, flags, field, app_table, def, none) \
+        ;\
+        static const ASN1_ADB name##_adb = {\
+                flags,\
+                offsetof(name, field),\
+                app_table,\
+                name##_adbtbl,\
+                sizeof(name##_adbtbl) / sizeof(ASN1_ADB_TABLE),\
+                def,\
+                none\
+        }
+
+# else
+
+#  define ASN1_ADB_END(name, flags, field, app_table, def, none) \
+        ;\
+        static const ASN1_ITEM *name##_adb(void) \
+        { \
+        static const ASN1_ADB internal_adb = \
+                {\
+                flags,\
+                offsetof(name, field),\
+                app_table,\
+                name##_adbtbl,\
+                sizeof(name##_adbtbl) / sizeof(ASN1_ADB_TABLE),\
+                def,\
+                none\
+                }; \
+                return (const ASN1_ITEM *) &internal_adb; \
+        } \
+        void dummy_function(void)
+
+# endif
+
+# define ADB_ENTRY(val, template) {val, template}
+
+# define ASN1_ADB_TEMPLATE(name) \
+        static const ASN1_TEMPLATE name##_tt
+
+/*
+ * This is the ASN1 template structure that defines a wrapper round the
+ * actual type. It determines the actual position of the field in the value
+ * structure, various flags such as OPTIONAL and the field name.
+ */
+
+struct ASN1_TEMPLATE_st {
+    unsigned long flags;        /* Various flags */
+    long tag;                   /* tag, not used if no tagging */
+    unsigned long offset;       /* Offset of this field in structure */
+# ifndef NO_ASN1_FIELD_NAMES
+    const char *field_name;     /* Field name */
+# endif
+    ASN1_ITEM_EXP *item;        /* Relevant ASN1_ITEM or ASN1_ADB */
+};
+
+/* Macro to extract ASN1_ITEM and ASN1_ADB pointer from ASN1_TEMPLATE */
+
+# define ASN1_TEMPLATE_item(t) (t->item_ptr)
+# define ASN1_TEMPLATE_adb(t) (t->item_ptr)
+
+typedef struct ASN1_ADB_TABLE_st ASN1_ADB_TABLE;
+typedef struct ASN1_ADB_st ASN1_ADB;
+
+struct ASN1_ADB_st {
+    unsigned long flags;        /* Various flags */
+    unsigned long offset;       /* Offset of selector field */
+    STACK_OF(ASN1_ADB_TABLE) **app_items; /* Application defined items */
+    const ASN1_ADB_TABLE *tbl;  /* Table of possible types */
+    long tblcount;              /* Number of entries in tbl */
+    const ASN1_TEMPLATE *default_tt; /* Type to use if no match */
+    const ASN1_TEMPLATE *null_tt; /* Type to use if selector is NULL */
+};
+
+struct ASN1_ADB_TABLE_st {
+    long value;                 /* NID for an object or value for an int */
+    const ASN1_TEMPLATE tt;     /* item for this value */
+};
+
+/* template flags */
+
+/* Field is optional */
+# define ASN1_TFLG_OPTIONAL      (0x1)
+
+/* Field is a SET OF */
+# define ASN1_TFLG_SET_OF        (0x1 << 1)
+
+/* Field is a SEQUENCE OF */
+# define ASN1_TFLG_SEQUENCE_OF   (0x2 << 1)
+
+/*
+ * Special case: this refers to a SET OF that will be sorted into DER order
+ * when encoded *and* the corresponding STACK will be modified to match the
+ * new order.
+ */
+# define ASN1_TFLG_SET_ORDER     (0x3 << 1)
+
+/* Mask for SET OF or SEQUENCE OF */
+# define ASN1_TFLG_SK_MASK       (0x3 << 1)
+
+/*
+ * These flags mean the tag should be taken from the tag field. If EXPLICIT
+ * then the underlying type is used for the inner tag.
+ */
+
+/* IMPLICIT tagging */
+# define ASN1_TFLG_IMPTAG        (0x1 << 3)
+
+/* EXPLICIT tagging, inner tag from underlying type */
+# define ASN1_TFLG_EXPTAG        (0x2 << 3)
+
+# define ASN1_TFLG_TAG_MASK      (0x3 << 3)
+
+/* context specific IMPLICIT */
+# define ASN1_TFLG_IMPLICIT      ASN1_TFLG_IMPTAG|ASN1_TFLG_CONTEXT
+
+/* context specific EXPLICIT */
+# define ASN1_TFLG_EXPLICIT      ASN1_TFLG_EXPTAG|ASN1_TFLG_CONTEXT
+
+/*
+ * If tagging is in force these determine the type of tag to use. Otherwise
+ * the tag is determined by the underlying type. These values reflect the
+ * actual octet format.
+ */
+
+/* Universal tag */
+# define ASN1_TFLG_UNIVERSAL     (0x0<<6)
+/* Application tag */
+# define ASN1_TFLG_APPLICATION   (0x1<<6)
+/* Context specific tag */
+# define ASN1_TFLG_CONTEXT       (0x2<<6)
+/* Private tag */
+# define ASN1_TFLG_PRIVATE       (0x3<<6)
+
+# define ASN1_TFLG_TAG_CLASS     (0x3<<6)
+
+/*
+ * These are for ANY DEFINED BY type. In this case the 'item' field points to
+ * an ASN1_ADB structure which contains a table of values to decode the
+ * relevant type
+ */
+
+# define ASN1_TFLG_ADB_MASK      (0x3<<8)
+
+# define ASN1_TFLG_ADB_OID       (0x1<<8)
+
+# define ASN1_TFLG_ADB_INT       (0x1<<9)
+
+/*
+ * This flag means a parent structure is passed instead of the field: this is
+ * useful is a SEQUENCE is being combined with a CHOICE for example. Since
+ * this means the structure and item name will differ we need to use the
+ * ASN1_CHOICE_END_name() macro for example.
+ */
+
+# define ASN1_TFLG_COMBINE       (0x1<<10)
+
+/*
+ * This flag when present in a SEQUENCE OF, SET OF or EXPLICIT causes
+ * indefinite length constructed encoding to be used if required.
+ */
+
+# define ASN1_TFLG_NDEF          (0x1<<11)
+
+/* This is the actual ASN1 item itself */
+
+struct ASN1_ITEM_st {
+    char itype;                 /* The item type, primitive, SEQUENCE, CHOICE
+                                 * or extern */
+    long utype;                 /* underlying type */
+    const ASN1_TEMPLATE *templates; /* If SEQUENCE or CHOICE this contains
+                                     * the contents */
+    long tcount;                /* Number of templates if SEQUENCE or CHOICE */
+    const void *funcs;          /* functions that handle this type */
+    long size;                  /* Structure size (usually) */
+# ifndef NO_ASN1_FIELD_NAMES
+    const char *sname;          /* Structure name */
+# endif
+};
+
+/*-
+ * These are values for the itype field and
+ * determine how the type is interpreted.
+ *
+ * For PRIMITIVE types the underlying type
+ * determines the behaviour if items is NULL.
+ *
+ * Otherwise templates must contain a single
+ * template and the type is treated in the
+ * same way as the type specified in the template.
+ *
+ * For SEQUENCE types the templates field points
+ * to the members, the size field is the
+ * structure size.
+ *
+ * For CHOICE types the templates field points
+ * to each possible member (typically a union)
+ * and the 'size' field is the offset of the
+ * selector.
+ *
+ * The 'funcs' field is used for application
+ * specific functions.
+ *
+ * For COMPAT types the funcs field gives a
+ * set of functions that handle this type, this
+ * supports the old d2i, i2d convention.
+ *
+ * The EXTERN type uses a new style d2i/i2d.
+ * The new style should be used where possible
+ * because it avoids things like the d2i IMPLICIT
+ * hack.
+ *
+ * MSTRING is a multiple string type, it is used
+ * for a CHOICE of character strings where the
+ * actual strings all occupy an ASN1_STRING
+ * structure. In this case the 'utype' field
+ * has a special meaning, it is used as a mask
+ * of acceptable types using the B_ASN1 constants.
+ *
+ * NDEF_SEQUENCE is the same as SEQUENCE except
+ * that it will use indefinite length constructed
+ * encoding if requested.
+ *
+ */
+
+# define ASN1_ITYPE_PRIMITIVE            0x0
+
+# define ASN1_ITYPE_SEQUENCE             0x1
+
+# define ASN1_ITYPE_CHOICE               0x2
+
+# define ASN1_ITYPE_COMPAT               0x3
+
+# define ASN1_ITYPE_EXTERN               0x4
+
+# define ASN1_ITYPE_MSTRING              0x5
+
+# define ASN1_ITYPE_NDEF_SEQUENCE        0x6
+
+/*
+ * Cache for ASN1 tag and length, so we don't keep re-reading it for things
+ * like CHOICE
+ */
+
+struct ASN1_TLC_st {
+    char valid;                 /* Values below are valid */
+    int ret;                    /* return value */
+    long plen;                  /* length */
+    int ptag;                   /* class value */
+    int pclass;                 /* class value */
+    int hdrlen;                 /* header length */
+};
+
+/* Typedefs for ASN1 function pointers */
+
+typedef ASN1_VALUE *ASN1_new_func(void);
+typedef void ASN1_free_func(ASN1_VALUE *a);
+typedef ASN1_VALUE *ASN1_d2i_func(ASN1_VALUE **a, const unsigned char **in,
+                                  long length);
+typedef int ASN1_i2d_func(ASN1_VALUE *a, unsigned char **in);
+
+typedef int ASN1_ex_d2i(ASN1_VALUE **pval, const unsigned char **in, long len,
+                        const ASN1_ITEM *it, int tag, int aclass, char opt,
+                        ASN1_TLC *ctx);
+
+typedef int ASN1_ex_i2d(ASN1_VALUE **pval, unsigned char **out,
+                        const ASN1_ITEM *it, int tag, int aclass);
+typedef int ASN1_ex_new_func(ASN1_VALUE **pval, const ASN1_ITEM *it);
+typedef void ASN1_ex_free_func(ASN1_VALUE **pval, const ASN1_ITEM *it);
+
+typedef int ASN1_ex_print_func(BIO *out, ASN1_VALUE **pval,
+                               int indent, const char *fname,
+                               const ASN1_PCTX *pctx);
+
+typedef int ASN1_primitive_i2c(ASN1_VALUE **pval, unsigned char *cont,
+                               int *putype, const ASN1_ITEM *it);
+typedef int ASN1_primitive_c2i(ASN1_VALUE **pval, const unsigned char *cont,
+                               int len, int utype, char *free_cont,
+                               const ASN1_ITEM *it);
+typedef int ASN1_primitive_print(BIO *out, ASN1_VALUE **pval,
+                                 const ASN1_ITEM *it, int indent,
+                                 const ASN1_PCTX *pctx);
+
+typedef struct ASN1_COMPAT_FUNCS_st {
+    ASN1_new_func *asn1_new;
+    ASN1_free_func *asn1_free;
+    ASN1_d2i_func *asn1_d2i;
+    ASN1_i2d_func *asn1_i2d;
+} ASN1_COMPAT_FUNCS;
+
+typedef struct ASN1_EXTERN_FUNCS_st {
+    void *app_data;
+    ASN1_ex_new_func *asn1_ex_new;
+    ASN1_ex_free_func *asn1_ex_free;
+    ASN1_ex_free_func *asn1_ex_clear;
+    ASN1_ex_d2i *asn1_ex_d2i;
+    ASN1_ex_i2d *asn1_ex_i2d;
+    ASN1_ex_print_func *asn1_ex_print;
+} ASN1_EXTERN_FUNCS;
+
+typedef struct ASN1_PRIMITIVE_FUNCS_st {
+    void *app_data;
+    unsigned long flags;
+    ASN1_ex_new_func *prim_new;
+    ASN1_ex_free_func *prim_free;
+    ASN1_ex_free_func *prim_clear;
+    ASN1_primitive_c2i *prim_c2i;
+    ASN1_primitive_i2c *prim_i2c;
+    ASN1_primitive_print *prim_print;
+} ASN1_PRIMITIVE_FUNCS;
+
+/*
+ * This is the ASN1_AUX structure: it handles various miscellaneous
+ * requirements. For example the use of reference counts and an informational
+ * callback. The "informational callback" is called at various points during
+ * the ASN1 encoding and decoding. It can be used to provide minor
+ * customisation of the structures used. This is most useful where the
+ * supplied routines *almost* do the right thing but need some extra help at
+ * a few points. If the callback returns zero then it is assumed a fatal
+ * error has occurred and the main operation should be abandoned. If major
+ * changes in the default behaviour are required then an external type is
+ * more appropriate.
+ */
+
+typedef int ASN1_aux_cb(int operation, ASN1_VALUE **in, const ASN1_ITEM *it,
+                        void *exarg);
+
+typedef struct ASN1_AUX_st {
+    void *app_data;
+    int flags;
+    int ref_offset;             /* Offset of reference value */
+    int ref_lock;               /* Lock type to use */
+    ASN1_aux_cb *asn1_cb;
+    int enc_offset;             /* Offset of ASN1_ENCODING structure */
+} ASN1_AUX;
+
+/* For print related callbacks exarg points to this structure */
+typedef struct ASN1_PRINT_ARG_st {
+    BIO *out;
+    int indent;
+    const ASN1_PCTX *pctx;
+} ASN1_PRINT_ARG;
+
+/* For streaming related callbacks exarg points to this structure */
+typedef struct ASN1_STREAM_ARG_st {
+    /* BIO to stream through */
+    BIO *out;
+    /* BIO with filters appended */
+    BIO *ndef_bio;
+    /* Streaming I/O boundary */
+    unsigned char **boundary;
+} ASN1_STREAM_ARG;
+
+/* Flags in ASN1_AUX */
+
+/* Use a reference count */
+# define ASN1_AFLG_REFCOUNT      1
+/* Save the encoding of structure (useful for signatures) */
+# define ASN1_AFLG_ENCODING      2
+/* The Sequence length is invalid */
+# define ASN1_AFLG_BROKEN        4
+
+/* operation values for asn1_cb */
+
+# define ASN1_OP_NEW_PRE         0
+# define ASN1_OP_NEW_POST        1
+# define ASN1_OP_FREE_PRE        2
+# define ASN1_OP_FREE_POST       3
+# define ASN1_OP_D2I_PRE         4
+# define ASN1_OP_D2I_POST        5
+# define ASN1_OP_I2D_PRE         6
+# define ASN1_OP_I2D_POST        7
+# define ASN1_OP_PRINT_PRE       8
+# define ASN1_OP_PRINT_POST      9
+# define ASN1_OP_STREAM_PRE      10
+# define ASN1_OP_STREAM_POST     11
+# define ASN1_OP_DETACHED_PRE    12
+# define ASN1_OP_DETACHED_POST   13
+
+/* Macro to implement a primitive type */
+# define IMPLEMENT_ASN1_TYPE(stname) IMPLEMENT_ASN1_TYPE_ex(stname, stname, 0)
+# define IMPLEMENT_ASN1_TYPE_ex(itname, vname, ex) \
+                                ASN1_ITEM_start(itname) \
+                                        ASN1_ITYPE_PRIMITIVE, V_##vname, NULL, 0, NULL, ex, #itname \
+                                ASN1_ITEM_end(itname)
+
+/* Macro to implement a multi string type */
+# define IMPLEMENT_ASN1_MSTRING(itname, mask) \
+                                ASN1_ITEM_start(itname) \
+                                        ASN1_ITYPE_MSTRING, mask, NULL, 0, NULL, sizeof(ASN1_STRING), #itname \
+                                ASN1_ITEM_end(itname)
+
+/* Macro to implement an ASN1_ITEM in terms of old style funcs */
+
+# define IMPLEMENT_COMPAT_ASN1(sname) IMPLEMENT_COMPAT_ASN1_type(sname, V_ASN1_SEQUENCE)
+
+# define IMPLEMENT_COMPAT_ASN1_type(sname, tag) \
+        static const ASN1_COMPAT_FUNCS sname##_ff = { \
+                (ASN1_new_func *)sname##_new, \
+                (ASN1_free_func *)sname##_free, \
+                (ASN1_d2i_func *)d2i_##sname, \
+                (ASN1_i2d_func *)i2d_##sname, \
+        }; \
+        ASN1_ITEM_start(sname) \
+                ASN1_ITYPE_COMPAT, \
+                tag, \
+                NULL, \
+                0, \
+                &sname##_ff, \
+                0, \
+                #sname \
+        ASN1_ITEM_end(sname)
+
+# define IMPLEMENT_EXTERN_ASN1(sname, tag, fptrs) \
+        ASN1_ITEM_start(sname) \
+                ASN1_ITYPE_EXTERN, \
+                tag, \
+                NULL, \
+                0, \
+                &fptrs, \
+                0, \
+                #sname \
+        ASN1_ITEM_end(sname)
+
+/* Macro to implement standard functions in terms of ASN1_ITEM structures */
+
+# define IMPLEMENT_ASN1_FUNCTIONS(stname) IMPLEMENT_ASN1_FUNCTIONS_fname(stname, stname, stname)
+
+# define IMPLEMENT_ASN1_FUNCTIONS_name(stname, itname) IMPLEMENT_ASN1_FUNCTIONS_fname(stname, itname, itname)
+
+# define IMPLEMENT_ASN1_FUNCTIONS_ENCODE_name(stname, itname) \
+                        IMPLEMENT_ASN1_FUNCTIONS_ENCODE_fname(stname, itname, itname)
+
+# define IMPLEMENT_STATIC_ASN1_ALLOC_FUNCTIONS(stname) \
+                IMPLEMENT_ASN1_ALLOC_FUNCTIONS_pfname(static, stname, stname, stname)
+
+# define IMPLEMENT_ASN1_ALLOC_FUNCTIONS(stname) \
+                IMPLEMENT_ASN1_ALLOC_FUNCTIONS_fname(stname, stname, stname)
+
+# define IMPLEMENT_ASN1_ALLOC_FUNCTIONS_pfname(pre, stname, itname, fname) \
+        pre stname *fname##_new(void) \
+        { \
+                return (stname *)ASN1_item_new(ASN1_ITEM_rptr(itname)); \
+        } \
+        pre void fname##_free(stname *a) \
+        { \
+                ASN1_item_free((ASN1_VALUE *)a, ASN1_ITEM_rptr(itname)); \
+        }
+
+# define IMPLEMENT_ASN1_ALLOC_FUNCTIONS_fname(stname, itname, fname) \
+        stname *fname##_new(void) \
+        { \
+                return (stname *)ASN1_item_new(ASN1_ITEM_rptr(itname)); \
+        } \
+        void fname##_free(stname *a) \
+        { \
+                ASN1_item_free((ASN1_VALUE *)a, ASN1_ITEM_rptr(itname)); \
+        }
+
+# define IMPLEMENT_ASN1_FUNCTIONS_fname(stname, itname, fname) \
+        IMPLEMENT_ASN1_ENCODE_FUNCTIONS_fname(stname, itname, fname) \
+        IMPLEMENT_ASN1_ALLOC_FUNCTIONS_fname(stname, itname, fname)
+
+# define IMPLEMENT_ASN1_ENCODE_FUNCTIONS_fname(stname, itname, fname) \
+        stname *d2i_##fname(stname **a, const unsigned char **in, long len) \
+        { \
+                return (stname *)ASN1_item_d2i((ASN1_VALUE **)a, in, len, ASN1_ITEM_rptr(itname));\
+        } \
+        int i2d_##fname(stname *a, unsigned char **out) \
+        { \
+                return ASN1_item_i2d((ASN1_VALUE *)a, out, ASN1_ITEM_rptr(itname));\
+        }
+
+# define IMPLEMENT_ASN1_NDEF_FUNCTION(stname) \
+        int i2d_##stname##_NDEF(stname *a, unsigned char **out) \
+        { \
+                return ASN1_item_ndef_i2d((ASN1_VALUE *)a, out, ASN1_ITEM_rptr(stname));\
+        }
+
+/*
+ * This includes evil casts to remove const: they will go away when full ASN1
+ * constification is done.
+ */
+# define IMPLEMENT_ASN1_ENCODE_FUNCTIONS_const_fname(stname, itname, fname) \
+        stname *d2i_##fname(stname **a, const unsigned char **in, long len) \
+        { \
+                return (stname *)ASN1_item_d2i((ASN1_VALUE **)a, in, len, ASN1_ITEM_rptr(itname));\
+        } \
+        int i2d_##fname(const stname *a, unsigned char **out) \
+        { \
+                return ASN1_item_i2d((ASN1_VALUE *)a, out, ASN1_ITEM_rptr(itname));\
+        }
+
+# define IMPLEMENT_ASN1_DUP_FUNCTION(stname) \
+        stname * stname##_dup(stname *x) \
+        { \
+        return ASN1_item_dup(ASN1_ITEM_rptr(stname), x); \
+        }
+
+# define IMPLEMENT_ASN1_PRINT_FUNCTION(stname) \
+        IMPLEMENT_ASN1_PRINT_FUNCTION_fname(stname, stname, stname)
+
+# define IMPLEMENT_ASN1_PRINT_FUNCTION_fname(stname, itname, fname) \
+        int fname##_print_ctx(BIO *out, stname *x, int indent, \
+                                                const ASN1_PCTX *pctx) \
+        { \
+                return ASN1_item_print(out, (ASN1_VALUE *)x, indent, \
+                        ASN1_ITEM_rptr(itname), pctx); \
+        }
+
+# define IMPLEMENT_ASN1_FUNCTIONS_const(name) \
+                IMPLEMENT_ASN1_FUNCTIONS_const_fname(name, name, name)
+
+# define IMPLEMENT_ASN1_FUNCTIONS_const_fname(stname, itname, fname) \
+        IMPLEMENT_ASN1_ENCODE_FUNCTIONS_const_fname(stname, itname, fname) \
+        IMPLEMENT_ASN1_ALLOC_FUNCTIONS_fname(stname, itname, fname)
+
+/* external definitions for primitive types */
+
+DECLARE_ASN1_ITEM(ASN1_BOOLEAN)
+DECLARE_ASN1_ITEM(ASN1_TBOOLEAN)
+DECLARE_ASN1_ITEM(ASN1_FBOOLEAN)
+DECLARE_ASN1_ITEM(ASN1_SEQUENCE)
+DECLARE_ASN1_ITEM(CBIGNUM)
+DECLARE_ASN1_ITEM(BIGNUM)
+DECLARE_ASN1_ITEM(LONG)
+DECLARE_ASN1_ITEM(ZLONG)
+
+DECLARE_STACK_OF(ASN1_VALUE)
+
+/* Functions used internally by the ASN1 code */
+
+int ASN1_item_ex_new(ASN1_VALUE **pval, const ASN1_ITEM *it);
+void ASN1_item_ex_free(ASN1_VALUE **pval, const ASN1_ITEM *it);
+int ASN1_template_new(ASN1_VALUE **pval, const ASN1_TEMPLATE *tt);
+int ASN1_primitive_new(ASN1_VALUE **pval, const ASN1_ITEM *it);
+
+void ASN1_template_free(ASN1_VALUE **pval, const ASN1_TEMPLATE *tt);
+int ASN1_template_d2i(ASN1_VALUE **pval, const unsigned char **in, long len,
+                      const ASN1_TEMPLATE *tt);
+int ASN1_item_ex_d2i(ASN1_VALUE **pval, const unsigned char **in, long len,
+                     const ASN1_ITEM *it, int tag, int aclass, char opt,
+                     ASN1_TLC *ctx);
+
+int ASN1_item_ex_i2d(ASN1_VALUE **pval, unsigned char **out,
+                     const ASN1_ITEM *it, int tag, int aclass);
+int ASN1_template_i2d(ASN1_VALUE **pval, unsigned char **out,
+                      const ASN1_TEMPLATE *tt);
+void ASN1_primitive_free(ASN1_VALUE **pval, const ASN1_ITEM *it);
+
+int asn1_ex_i2c(ASN1_VALUE **pval, unsigned char *cont, int *putype,
+                const ASN1_ITEM *it);
+int asn1_ex_c2i(ASN1_VALUE **pval, const unsigned char *cont, int len,
+                int utype, char *free_cont, const ASN1_ITEM *it);
+
+int asn1_get_choice_selector(ASN1_VALUE **pval, const ASN1_ITEM *it);
+int asn1_set_choice_selector(ASN1_VALUE **pval, int value,
+                             const ASN1_ITEM *it);
+
+ASN1_VALUE **asn1_get_field_ptr(ASN1_VALUE **pval, const ASN1_TEMPLATE *tt);
+
+const ASN1_TEMPLATE *asn1_do_adb(ASN1_VALUE **pval, const ASN1_TEMPLATE *tt,
+                                 int nullerr);
+
+int asn1_do_lock(ASN1_VALUE **pval, int op, const ASN1_ITEM *it);
+
+void asn1_enc_init(ASN1_VALUE **pval, const ASN1_ITEM *it);
+void asn1_enc_free(ASN1_VALUE **pval, const ASN1_ITEM *it);
+int asn1_enc_restore(int *len, unsigned char **out, ASN1_VALUE **pval,
+                     const ASN1_ITEM *it);
+int asn1_enc_save(ASN1_VALUE **pval, const unsigned char *in, int inlen,
+                  const ASN1_ITEM *it);
+
+#ifdef  __cplusplus
+}
+#endif
+#endif

+ 883 - 0
libssh2/openssl/include/openssl/bio.h

@@ -0,0 +1,883 @@
+/* crypto/bio/bio.h */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * 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 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. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    "This product includes cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``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 AUTHOR OR CONTRIBUTORS 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.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+#ifndef HEADER_BIO_H
+# define HEADER_BIO_H
+
+# include <openssl/e_os2.h>
+
+# ifndef OPENSSL_NO_FP_API
+#  include <stdio.h>
+# endif
+# include <stdarg.h>
+
+# include <openssl/crypto.h>
+
+# ifndef OPENSSL_NO_SCTP
+#  ifndef OPENSSL_SYS_VMS
+#   include <stdint.h>
+#  else
+#   include <inttypes.h>
+#  endif
+# endif
+
+#ifdef  __cplusplus
+extern "C" {
+#endif
+
+/* These are the 'types' of BIOs */
+# define BIO_TYPE_NONE           0
+# define BIO_TYPE_MEM            (1|0x0400)
+# define BIO_TYPE_FILE           (2|0x0400)
+
+# define BIO_TYPE_FD             (4|0x0400|0x0100)
+# define BIO_TYPE_SOCKET         (5|0x0400|0x0100)
+# define BIO_TYPE_NULL           (6|0x0400)
+# define BIO_TYPE_SSL            (7|0x0200)
+# define BIO_TYPE_MD             (8|0x0200)/* passive filter */
+# define BIO_TYPE_BUFFER         (9|0x0200)/* filter */
+# define BIO_TYPE_CIPHER         (10|0x0200)/* filter */
+# define BIO_TYPE_BASE64         (11|0x0200)/* filter */
+# define BIO_TYPE_CONNECT        (12|0x0400|0x0100)/* socket - connect */
+# define BIO_TYPE_ACCEPT         (13|0x0400|0x0100)/* socket for accept */
+# define BIO_TYPE_PROXY_CLIENT   (14|0x0200)/* client proxy BIO */
+# define BIO_TYPE_PROXY_SERVER   (15|0x0200)/* server proxy BIO */
+# define BIO_TYPE_NBIO_TEST      (16|0x0200)/* server proxy BIO */
+# define BIO_TYPE_NULL_FILTER    (17|0x0200)
+# define BIO_TYPE_BER            (18|0x0200)/* BER -> bin filter */
+# define BIO_TYPE_BIO            (19|0x0400)/* (half a) BIO pair */
+# define BIO_TYPE_LINEBUFFER     (20|0x0200)/* filter */
+# define BIO_TYPE_DGRAM          (21|0x0400|0x0100)
+# ifndef OPENSSL_NO_SCTP
+#  define BIO_TYPE_DGRAM_SCTP     (24|0x0400|0x0100)
+# endif
+# define BIO_TYPE_ASN1           (22|0x0200)/* filter */
+# define BIO_TYPE_COMP           (23|0x0200)/* filter */
+
+# define BIO_TYPE_DESCRIPTOR     0x0100/* socket, fd, connect or accept */
+# define BIO_TYPE_FILTER         0x0200
+# define BIO_TYPE_SOURCE_SINK    0x0400
+
+/*
+ * BIO_FILENAME_READ|BIO_CLOSE to open or close on free.
+ * BIO_set_fp(in,stdin,BIO_NOCLOSE);
+ */
+# define BIO_NOCLOSE             0x00
+# define BIO_CLOSE               0x01
+
+/*
+ * These are used in the following macros and are passed to BIO_ctrl()
+ */
+# define BIO_CTRL_RESET          1/* opt - rewind/zero etc */
+# define BIO_CTRL_EOF            2/* opt - are we at the eof */
+# define BIO_CTRL_INFO           3/* opt - extra tit-bits */
+# define BIO_CTRL_SET            4/* man - set the 'IO' type */
+# define BIO_CTRL_GET            5/* man - get the 'IO' type */
+# define BIO_CTRL_PUSH           6/* opt - internal, used to signify change */
+# define BIO_CTRL_POP            7/* opt - internal, used to signify change */
+# define BIO_CTRL_GET_CLOSE      8/* man - set the 'close' on free */
+# define BIO_CTRL_SET_CLOSE      9/* man - set the 'close' on free */
+# define BIO_CTRL_PENDING        10/* opt - is their more data buffered */
+# define BIO_CTRL_FLUSH          11/* opt - 'flush' buffered output */
+# define BIO_CTRL_DUP            12/* man - extra stuff for 'duped' BIO */
+# define BIO_CTRL_WPENDING       13/* opt - number of bytes still to write */
+/* callback is int cb(BIO *bio,state,ret); */
+# define BIO_CTRL_SET_CALLBACK   14/* opt - set callback function */
+# define BIO_CTRL_GET_CALLBACK   15/* opt - set callback function */
+
+# define BIO_CTRL_SET_FILENAME   30/* BIO_s_file special */
+
+/* dgram BIO stuff */
+# define BIO_CTRL_DGRAM_CONNECT       31/* BIO dgram special */
+# define BIO_CTRL_DGRAM_SET_CONNECTED 32/* allow for an externally connected
+                                         * socket to be passed in */
+# define BIO_CTRL_DGRAM_SET_RECV_TIMEOUT 33/* setsockopt, essentially */
+# define BIO_CTRL_DGRAM_GET_RECV_TIMEOUT 34/* getsockopt, essentially */
+# define BIO_CTRL_DGRAM_SET_SEND_TIMEOUT 35/* setsockopt, essentially */
+# define BIO_CTRL_DGRAM_GET_SEND_TIMEOUT 36/* getsockopt, essentially */
+
+# define BIO_CTRL_DGRAM_GET_RECV_TIMER_EXP 37/* flag whether the last */
+# define BIO_CTRL_DGRAM_GET_SEND_TIMER_EXP 38/* I/O operation tiemd out */
+
+/* #ifdef IP_MTU_DISCOVER */
+# define BIO_CTRL_DGRAM_MTU_DISCOVER       39/* set DF bit on egress packets */
+/* #endif */
+
+# define BIO_CTRL_DGRAM_QUERY_MTU          40/* as kernel for current MTU */
+# define BIO_CTRL_DGRAM_GET_FALLBACK_MTU   47
+# define BIO_CTRL_DGRAM_GET_MTU            41/* get cached value for MTU */
+# define BIO_CTRL_DGRAM_SET_MTU            42/* set cached value for MTU.
+                                              * want to use this if asking
+                                              * the kernel fails */
+
+# define BIO_CTRL_DGRAM_MTU_EXCEEDED       43/* check whether the MTU was
+                                              * exceed in the previous write
+                                              * operation */
+
+# define BIO_CTRL_DGRAM_GET_PEER           46
+# define BIO_CTRL_DGRAM_SET_PEER           44/* Destination for the data */
+
+# define BIO_CTRL_DGRAM_SET_NEXT_TIMEOUT   45/* Next DTLS handshake timeout
+                                              * to adjust socket timeouts */
+# define BIO_CTRL_DGRAM_SET_DONT_FRAG      48
+
+# define BIO_CTRL_DGRAM_GET_MTU_OVERHEAD   49
+
+# ifndef OPENSSL_NO_SCTP
+/* SCTP stuff */
+#  define BIO_CTRL_DGRAM_SCTP_SET_IN_HANDSHAKE    50
+#  define BIO_CTRL_DGRAM_SCTP_ADD_AUTH_KEY                51
+#  define BIO_CTRL_DGRAM_SCTP_NEXT_AUTH_KEY               52
+#  define BIO_CTRL_DGRAM_SCTP_AUTH_CCS_RCVD               53
+#  define BIO_CTRL_DGRAM_SCTP_GET_SNDINFO         60
+#  define BIO_CTRL_DGRAM_SCTP_SET_SNDINFO         61
+#  define BIO_CTRL_DGRAM_SCTP_GET_RCVINFO         62
+#  define BIO_CTRL_DGRAM_SCTP_SET_RCVINFO         63
+#  define BIO_CTRL_DGRAM_SCTP_GET_PRINFO                  64
+#  define BIO_CTRL_DGRAM_SCTP_SET_PRINFO                  65
+#  define BIO_CTRL_DGRAM_SCTP_SAVE_SHUTDOWN               70
+# endif
+
+/* modifiers */
+# define BIO_FP_READ             0x02
+# define BIO_FP_WRITE            0x04
+# define BIO_FP_APPEND           0x08
+# define BIO_FP_TEXT             0x10
+
+# define BIO_FLAGS_READ          0x01
+# define BIO_FLAGS_WRITE         0x02
+# define BIO_FLAGS_IO_SPECIAL    0x04
+# define BIO_FLAGS_RWS (BIO_FLAGS_READ|BIO_FLAGS_WRITE|BIO_FLAGS_IO_SPECIAL)
+# define BIO_FLAGS_SHOULD_RETRY  0x08
+# ifndef BIO_FLAGS_UPLINK
+/*
+ * "UPLINK" flag denotes file descriptors provided by application. It
+ * defaults to 0, as most platforms don't require UPLINK interface.
+ */
+#  define BIO_FLAGS_UPLINK        0
+# endif
+
+/* Used in BIO_gethostbyname() */
+# define BIO_GHBN_CTRL_HITS              1
+# define BIO_GHBN_CTRL_MISSES            2
+# define BIO_GHBN_CTRL_CACHE_SIZE        3
+# define BIO_GHBN_CTRL_GET_ENTRY         4
+# define BIO_GHBN_CTRL_FLUSH             5
+
+/* Mostly used in the SSL BIO */
+/*-
+ * Not used anymore
+ * #define BIO_FLAGS_PROTOCOL_DELAYED_READ 0x10
+ * #define BIO_FLAGS_PROTOCOL_DELAYED_WRITE 0x20
+ * #define BIO_FLAGS_PROTOCOL_STARTUP   0x40
+ */
+
+# define BIO_FLAGS_BASE64_NO_NL  0x100
+
+/*
+ * This is used with memory BIOs: it means we shouldn't free up or change the
+ * data in any way.
+ */
+# define BIO_FLAGS_MEM_RDONLY    0x200
+
+typedef struct bio_st BIO;
+
+void BIO_set_flags(BIO *b, int flags);
+int BIO_test_flags(const BIO *b, int flags);
+void BIO_clear_flags(BIO *b, int flags);
+
+# define BIO_get_flags(b) BIO_test_flags(b, ~(0x0))
+# define BIO_set_retry_special(b) \
+                BIO_set_flags(b, (BIO_FLAGS_IO_SPECIAL|BIO_FLAGS_SHOULD_RETRY))
+# define BIO_set_retry_read(b) \
+                BIO_set_flags(b, (BIO_FLAGS_READ|BIO_FLAGS_SHOULD_RETRY))
+# define BIO_set_retry_write(b) \
+                BIO_set_flags(b, (BIO_FLAGS_WRITE|BIO_FLAGS_SHOULD_RETRY))
+
+/* These are normally used internally in BIOs */
+# define BIO_clear_retry_flags(b) \
+                BIO_clear_flags(b, (BIO_FLAGS_RWS|BIO_FLAGS_SHOULD_RETRY))
+# define BIO_get_retry_flags(b) \
+                BIO_test_flags(b, (BIO_FLAGS_RWS|BIO_FLAGS_SHOULD_RETRY))
+
+/* These should be used by the application to tell why we should retry */
+# define BIO_should_read(a)              BIO_test_flags(a, BIO_FLAGS_READ)
+# define BIO_should_write(a)             BIO_test_flags(a, BIO_FLAGS_WRITE)
+# define BIO_should_io_special(a)        BIO_test_flags(a, BIO_FLAGS_IO_SPECIAL)
+# define BIO_retry_type(a)               BIO_test_flags(a, BIO_FLAGS_RWS)
+# define BIO_should_retry(a)             BIO_test_flags(a, BIO_FLAGS_SHOULD_RETRY)
+
+/*
+ * The next three are used in conjunction with the BIO_should_io_special()
+ * condition.  After this returns true, BIO *BIO_get_retry_BIO(BIO *bio, int
+ * *reason); will walk the BIO stack and return the 'reason' for the special
+ * and the offending BIO. Given a BIO, BIO_get_retry_reason(bio) will return
+ * the code.
+ */
+/*
+ * Returned from the SSL bio when the certificate retrieval code had an error
+ */
+# define BIO_RR_SSL_X509_LOOKUP          0x01
+/* Returned from the connect BIO when a connect would have blocked */
+# define BIO_RR_CONNECT                  0x02
+/* Returned from the accept BIO when an accept would have blocked */
+# define BIO_RR_ACCEPT                   0x03
+
+/* These are passed by the BIO callback */
+# define BIO_CB_FREE     0x01
+# define BIO_CB_READ     0x02
+# define BIO_CB_WRITE    0x03
+# define BIO_CB_PUTS     0x04
+# define BIO_CB_GETS     0x05
+# define BIO_CB_CTRL     0x06
+
+/*
+ * The callback is called before and after the underling operation, The
+ * BIO_CB_RETURN flag indicates if it is after the call
+ */
+# define BIO_CB_RETURN   0x80
+# define BIO_CB_return(a) ((a)|BIO_CB_RETURN)
+# define BIO_cb_pre(a)   (!((a)&BIO_CB_RETURN))
+# define BIO_cb_post(a)  ((a)&BIO_CB_RETURN)
+
+long (*BIO_get_callback(const BIO *b)) (struct bio_st *, int, const char *,
+                                        int, long, long);
+void BIO_set_callback(BIO *b,
+                      long (*callback) (struct bio_st *, int, const char *,
+                                        int, long, long));
+char *BIO_get_callback_arg(const BIO *b);
+void BIO_set_callback_arg(BIO *b, char *arg);
+
+const char *BIO_method_name(const BIO *b);
+int BIO_method_type(const BIO *b);
+
+typedef void bio_info_cb (struct bio_st *, int, const char *, int, long,
+                          long);
+
+typedef struct bio_method_st {
+    int type;
+    const char *name;
+    int (*bwrite) (BIO *, const char *, int);
+    int (*bread) (BIO *, char *, int);
+    int (*bputs) (BIO *, const char *);
+    int (*bgets) (BIO *, char *, int);
+    long (*ctrl) (BIO *, int, long, void *);
+    int (*create) (BIO *);
+    int (*destroy) (BIO *);
+    long (*callback_ctrl) (BIO *, int, bio_info_cb *);
+} BIO_METHOD;
+
+struct bio_st {
+    BIO_METHOD *method;
+    /* bio, mode, argp, argi, argl, ret */
+    long (*callback) (struct bio_st *, int, const char *, int, long, long);
+    char *cb_arg;               /* first argument for the callback */
+    int init;
+    int shutdown;
+    int flags;                  /* extra storage */
+    int retry_reason;
+    int num;
+    void *ptr;
+    struct bio_st *next_bio;    /* used by filter BIOs */
+    struct bio_st *prev_bio;    /* used by filter BIOs */
+    int references;
+    unsigned long num_read;
+    unsigned long num_write;
+    CRYPTO_EX_DATA ex_data;
+};
+
+DECLARE_STACK_OF(BIO)
+
+typedef struct bio_f_buffer_ctx_struct {
+    /*-
+     * Buffers are setup like this:
+     *
+     * <---------------------- size ----------------------->
+     * +---------------------------------------------------+
+     * | consumed | remaining          | free space        |
+     * +---------------------------------------------------+
+     * <-- off --><------- len ------->
+     */
+    /*- BIO *bio; *//*
+     * this is now in the BIO struct
+     */
+    int ibuf_size;              /* how big is the input buffer */
+    int obuf_size;              /* how big is the output buffer */
+    char *ibuf;                 /* the char array */
+    int ibuf_len;               /* how many bytes are in it */
+    int ibuf_off;               /* write/read offset */
+    char *obuf;                 /* the char array */
+    int obuf_len;               /* how many bytes are in it */
+    int obuf_off;               /* write/read offset */
+} BIO_F_BUFFER_CTX;
+
+/* Prefix and suffix callback in ASN1 BIO */
+typedef int asn1_ps_func (BIO *b, unsigned char **pbuf, int *plen,
+                          void *parg);
+
+# ifndef OPENSSL_NO_SCTP
+/* SCTP parameter structs */
+struct bio_dgram_sctp_sndinfo {
+    uint16_t snd_sid;
+    uint16_t snd_flags;
+    uint32_t snd_ppid;
+    uint32_t snd_context;
+};
+
+struct bio_dgram_sctp_rcvinfo {
+    uint16_t rcv_sid;
+    uint16_t rcv_ssn;
+    uint16_t rcv_flags;
+    uint32_t rcv_ppid;
+    uint32_t rcv_tsn;
+    uint32_t rcv_cumtsn;
+    uint32_t rcv_context;
+};
+
+struct bio_dgram_sctp_prinfo {
+    uint16_t pr_policy;
+    uint32_t pr_value;
+};
+# endif
+
+/* connect BIO stuff */
+# define BIO_CONN_S_BEFORE               1
+# define BIO_CONN_S_GET_IP               2
+# define BIO_CONN_S_GET_PORT             3
+# define BIO_CONN_S_CREATE_SOCKET        4
+# define BIO_CONN_S_CONNECT              5
+# define BIO_CONN_S_OK                   6
+# define BIO_CONN_S_BLOCKED_CONNECT      7
+# define BIO_CONN_S_NBIO                 8
+/*
+ * #define BIO_CONN_get_param_hostname BIO_ctrl
+ */
+
+# define BIO_C_SET_CONNECT                       100
+# define BIO_C_DO_STATE_MACHINE                  101
+# define BIO_C_SET_NBIO                          102
+# define BIO_C_SET_PROXY_PARAM                   103
+# define BIO_C_SET_FD                            104
+# define BIO_C_GET_FD                            105
+# define BIO_C_SET_FILE_PTR                      106
+# define BIO_C_GET_FILE_PTR                      107
+# define BIO_C_SET_FILENAME                      108
+# define BIO_C_SET_SSL                           109
+# define BIO_C_GET_SSL                           110
+# define BIO_C_SET_MD                            111
+# define BIO_C_GET_MD                            112
+# define BIO_C_GET_CIPHER_STATUS                 113
+# define BIO_C_SET_BUF_MEM                       114
+# define BIO_C_GET_BUF_MEM_PTR                   115
+# define BIO_C_GET_BUFF_NUM_LINES                116
+# define BIO_C_SET_BUFF_SIZE                     117
+# define BIO_C_SET_ACCEPT                        118
+# define BIO_C_SSL_MODE                          119
+# define BIO_C_GET_MD_CTX                        120
+# define BIO_C_GET_PROXY_PARAM                   121
+# define BIO_C_SET_BUFF_READ_DATA                122/* data to read first */
+# define BIO_C_GET_CONNECT                       123
+# define BIO_C_GET_ACCEPT                        124
+# define BIO_C_SET_SSL_RENEGOTIATE_BYTES         125
+# define BIO_C_GET_SSL_NUM_RENEGOTIATES          126
+# define BIO_C_SET_SSL_RENEGOTIATE_TIMEOUT       127
+# define BIO_C_FILE_SEEK                         128
+# define BIO_C_GET_CIPHER_CTX                    129
+# define BIO_C_SET_BUF_MEM_EOF_RETURN            130/* return end of input
+                                                     * value */
+# define BIO_C_SET_BIND_MODE                     131
+# define BIO_C_GET_BIND_MODE                     132
+# define BIO_C_FILE_TELL                         133
+# define BIO_C_GET_SOCKS                         134
+# define BIO_C_SET_SOCKS                         135
+
+# define BIO_C_SET_WRITE_BUF_SIZE                136/* for BIO_s_bio */
+# define BIO_C_GET_WRITE_BUF_SIZE                137
+# define BIO_C_MAKE_BIO_PAIR                     138
+# define BIO_C_DESTROY_BIO_PAIR                  139
+# define BIO_C_GET_WRITE_GUARANTEE               140
+# define BIO_C_GET_READ_REQUEST                  141
+# define BIO_C_SHUTDOWN_WR                       142
+# define BIO_C_NREAD0                            143
+# define BIO_C_NREAD                             144
+# define BIO_C_NWRITE0                           145
+# define BIO_C_NWRITE                            146
+# define BIO_C_RESET_READ_REQUEST                147
+# define BIO_C_SET_MD_CTX                        148
+
+# define BIO_C_SET_PREFIX                        149
+# define BIO_C_GET_PREFIX                        150
+# define BIO_C_SET_SUFFIX                        151
+# define BIO_C_GET_SUFFIX                        152
+
+# define BIO_C_SET_EX_ARG                        153
+# define BIO_C_GET_EX_ARG                        154
+
+# define BIO_set_app_data(s,arg)         BIO_set_ex_data(s,0,arg)
+# define BIO_get_app_data(s)             BIO_get_ex_data(s,0)
+
+/* BIO_s_connect() and BIO_s_socks4a_connect() */
+# define BIO_set_conn_hostname(b,name) BIO_ctrl(b,BIO_C_SET_CONNECT,0,(char *)name)
+# define BIO_set_conn_port(b,port) BIO_ctrl(b,BIO_C_SET_CONNECT,1,(char *)port)
+# define BIO_set_conn_ip(b,ip)     BIO_ctrl(b,BIO_C_SET_CONNECT,2,(char *)ip)
+# define BIO_set_conn_int_port(b,port) BIO_ctrl(b,BIO_C_SET_CONNECT,3,(char *)port)
+# define BIO_get_conn_hostname(b)  BIO_ptr_ctrl(b,BIO_C_GET_CONNECT,0)
+# define BIO_get_conn_port(b)      BIO_ptr_ctrl(b,BIO_C_GET_CONNECT,1)
+# define BIO_get_conn_ip(b)               BIO_ptr_ctrl(b,BIO_C_GET_CONNECT,2)
+# define BIO_get_conn_int_port(b) BIO_ctrl(b,BIO_C_GET_CONNECT,3,NULL)
+
+# define BIO_set_nbio(b,n)       BIO_ctrl(b,BIO_C_SET_NBIO,(n),NULL)
+
+/* BIO_s_accept() */
+# define BIO_set_accept_port(b,name) BIO_ctrl(b,BIO_C_SET_ACCEPT,0,(char *)name)
+# define BIO_get_accept_port(b)  BIO_ptr_ctrl(b,BIO_C_GET_ACCEPT,0)
+/* #define BIO_set_nbio(b,n)    BIO_ctrl(b,BIO_C_SET_NBIO,(n),NULL) */
+# define BIO_set_nbio_accept(b,n) BIO_ctrl(b,BIO_C_SET_ACCEPT,1,(n)?(void *)"a":NULL)
+# define BIO_set_accept_bios(b,bio) BIO_ctrl(b,BIO_C_SET_ACCEPT,2,(char *)bio)
+
+# define BIO_BIND_NORMAL                 0
+# define BIO_BIND_REUSEADDR_IF_UNUSED    1
+# define BIO_BIND_REUSEADDR              2
+# define BIO_set_bind_mode(b,mode) BIO_ctrl(b,BIO_C_SET_BIND_MODE,mode,NULL)
+# define BIO_get_bind_mode(b,mode) BIO_ctrl(b,BIO_C_GET_BIND_MODE,0,NULL)
+
+/* BIO_s_accept() and BIO_s_connect() */
+# define BIO_do_connect(b)       BIO_do_handshake(b)
+# define BIO_do_accept(b)        BIO_do_handshake(b)
+# define BIO_do_handshake(b)     BIO_ctrl(b,BIO_C_DO_STATE_MACHINE,0,NULL)
+
+/* BIO_s_proxy_client() */
+# define BIO_set_url(b,url)      BIO_ctrl(b,BIO_C_SET_PROXY_PARAM,0,(char *)(url))
+# define BIO_set_proxies(b,p)    BIO_ctrl(b,BIO_C_SET_PROXY_PARAM,1,(char *)(p))
+/* BIO_set_nbio(b,n) */
+# define BIO_set_filter_bio(b,s) BIO_ctrl(b,BIO_C_SET_PROXY_PARAM,2,(char *)(s))
+/* BIO *BIO_get_filter_bio(BIO *bio); */
+# define BIO_set_proxy_cb(b,cb) BIO_callback_ctrl(b,BIO_C_SET_PROXY_PARAM,3,(void *(*cb)()))
+# define BIO_set_proxy_header(b,sk) BIO_ctrl(b,BIO_C_SET_PROXY_PARAM,4,(char *)sk)
+# define BIO_set_no_connect_return(b,bool) BIO_int_ctrl(b,BIO_C_SET_PROXY_PARAM,5,bool)
+
+# define BIO_get_proxy_header(b,skp) BIO_ctrl(b,BIO_C_GET_PROXY_PARAM,0,(char *)skp)
+# define BIO_get_proxies(b,pxy_p) BIO_ctrl(b,BIO_C_GET_PROXY_PARAM,1,(char *)(pxy_p))
+# define BIO_get_url(b,url)      BIO_ctrl(b,BIO_C_GET_PROXY_PARAM,2,(char *)(url))
+# define BIO_get_no_connect_return(b)    BIO_ctrl(b,BIO_C_GET_PROXY_PARAM,5,NULL)
+
+/* BIO_s_datagram(), BIO_s_fd(), BIO_s_socket(), BIO_s_accept() and BIO_s_connect() */
+# define BIO_set_fd(b,fd,c)      BIO_int_ctrl(b,BIO_C_SET_FD,c,fd)
+# define BIO_get_fd(b,c)         BIO_ctrl(b,BIO_C_GET_FD,0,(char *)c)
+
+/* BIO_s_file() */
+# define BIO_set_fp(b,fp,c)      BIO_ctrl(b,BIO_C_SET_FILE_PTR,c,(char *)fp)
+# define BIO_get_fp(b,fpp)       BIO_ctrl(b,BIO_C_GET_FILE_PTR,0,(char *)fpp)
+
+/* BIO_s_fd() and BIO_s_file() */
+# define BIO_seek(b,ofs) (int)BIO_ctrl(b,BIO_C_FILE_SEEK,ofs,NULL)
+# define BIO_tell(b)     (int)BIO_ctrl(b,BIO_C_FILE_TELL,0,NULL)
+
+/*
+ * name is cast to lose const, but might be better to route through a
+ * function so we can do it safely
+ */
+# ifdef CONST_STRICT
+/*
+ * If you are wondering why this isn't defined, its because CONST_STRICT is
+ * purely a compile-time kludge to allow const to be checked.
+ */
+int BIO_read_filename(BIO *b, const char *name);
+# else
+#  define BIO_read_filename(b,name) BIO_ctrl(b,BIO_C_SET_FILENAME, \
+                BIO_CLOSE|BIO_FP_READ,(char *)name)
+# endif
+# define BIO_write_filename(b,name) BIO_ctrl(b,BIO_C_SET_FILENAME, \
+                BIO_CLOSE|BIO_FP_WRITE,name)
+# define BIO_append_filename(b,name) BIO_ctrl(b,BIO_C_SET_FILENAME, \
+                BIO_CLOSE|BIO_FP_APPEND,name)
+# define BIO_rw_filename(b,name) BIO_ctrl(b,BIO_C_SET_FILENAME, \
+                BIO_CLOSE|BIO_FP_READ|BIO_FP_WRITE,name)
+
+/*
+ * WARNING WARNING, this ups the reference count on the read bio of the SSL
+ * structure.  This is because the ssl read BIO is now pointed to by the
+ * next_bio field in the bio.  So when you free the BIO, make sure you are
+ * doing a BIO_free_all() to catch the underlying BIO.
+ */
+# define BIO_set_ssl(b,ssl,c)    BIO_ctrl(b,BIO_C_SET_SSL,c,(char *)ssl)
+# define BIO_get_ssl(b,sslp)     BIO_ctrl(b,BIO_C_GET_SSL,0,(char *)sslp)
+# define BIO_set_ssl_mode(b,client)      BIO_ctrl(b,BIO_C_SSL_MODE,client,NULL)
+# define BIO_set_ssl_renegotiate_bytes(b,num) \
+        BIO_ctrl(b,BIO_C_SET_SSL_RENEGOTIATE_BYTES,num,NULL)
+# define BIO_get_num_renegotiates(b) \
+        BIO_ctrl(b,BIO_C_GET_SSL_NUM_RENEGOTIATES,0,NULL)
+# define BIO_set_ssl_renegotiate_timeout(b,seconds) \
+        BIO_ctrl(b,BIO_C_SET_SSL_RENEGOTIATE_TIMEOUT,seconds,NULL)
+
+/* defined in evp.h */
+/* #define BIO_set_md(b,md)     BIO_ctrl(b,BIO_C_SET_MD,1,(char *)md) */
+
+# define BIO_get_mem_data(b,pp)  BIO_ctrl(b,BIO_CTRL_INFO,0,(char *)pp)
+# define BIO_set_mem_buf(b,bm,c) BIO_ctrl(b,BIO_C_SET_BUF_MEM,c,(char *)bm)
+# define BIO_get_mem_ptr(b,pp)   BIO_ctrl(b,BIO_C_GET_BUF_MEM_PTR,0,(char *)pp)
+# define BIO_set_mem_eof_return(b,v) \
+                                BIO_ctrl(b,BIO_C_SET_BUF_MEM_EOF_RETURN,v,NULL)
+
+/* For the BIO_f_buffer() type */
+# define BIO_get_buffer_num_lines(b)     BIO_ctrl(b,BIO_C_GET_BUFF_NUM_LINES,0,NULL)
+# define BIO_set_buffer_size(b,size)     BIO_ctrl(b,BIO_C_SET_BUFF_SIZE,size,NULL)
+# define BIO_set_read_buffer_size(b,size) BIO_int_ctrl(b,BIO_C_SET_BUFF_SIZE,size,0)
+# define BIO_set_write_buffer_size(b,size) BIO_int_ctrl(b,BIO_C_SET_BUFF_SIZE,size,1)
+# define BIO_set_buffer_read_data(b,buf,num) BIO_ctrl(b,BIO_C_SET_BUFF_READ_DATA,num,buf)
+
+/* Don't use the next one unless you know what you are doing :-) */
+# define BIO_dup_state(b,ret)    BIO_ctrl(b,BIO_CTRL_DUP,0,(char *)(ret))
+
+# define BIO_reset(b)            (int)BIO_ctrl(b,BIO_CTRL_RESET,0,NULL)
+# define BIO_eof(b)              (int)BIO_ctrl(b,BIO_CTRL_EOF,0,NULL)
+# define BIO_set_close(b,c)      (int)BIO_ctrl(b,BIO_CTRL_SET_CLOSE,(c),NULL)
+# define BIO_get_close(b)        (int)BIO_ctrl(b,BIO_CTRL_GET_CLOSE,0,NULL)
+# define BIO_pending(b)          (int)BIO_ctrl(b,BIO_CTRL_PENDING,0,NULL)
+# define BIO_wpending(b)         (int)BIO_ctrl(b,BIO_CTRL_WPENDING,0,NULL)
+/* ...pending macros have inappropriate return type */
+size_t BIO_ctrl_pending(BIO *b);
+size_t BIO_ctrl_wpending(BIO *b);
+# define BIO_flush(b)            (int)BIO_ctrl(b,BIO_CTRL_FLUSH,0,NULL)
+# define BIO_get_info_callback(b,cbp) (int)BIO_ctrl(b,BIO_CTRL_GET_CALLBACK,0, \
+                                                   cbp)
+# define BIO_set_info_callback(b,cb) (int)BIO_callback_ctrl(b,BIO_CTRL_SET_CALLBACK,cb)
+
+/* For the BIO_f_buffer() type */
+# define BIO_buffer_get_num_lines(b) BIO_ctrl(b,BIO_CTRL_GET,0,NULL)
+
+/* For BIO_s_bio() */
+# define BIO_set_write_buf_size(b,size) (int)BIO_ctrl(b,BIO_C_SET_WRITE_BUF_SIZE,size,NULL)
+# define BIO_get_write_buf_size(b,size) (size_t)BIO_ctrl(b,BIO_C_GET_WRITE_BUF_SIZE,size,NULL)
+# define BIO_make_bio_pair(b1,b2)   (int)BIO_ctrl(b1,BIO_C_MAKE_BIO_PAIR,0,b2)
+# define BIO_destroy_bio_pair(b)    (int)BIO_ctrl(b,BIO_C_DESTROY_BIO_PAIR,0,NULL)
+# define BIO_shutdown_wr(b) (int)BIO_ctrl(b, BIO_C_SHUTDOWN_WR, 0, NULL)
+/* macros with inappropriate type -- but ...pending macros use int too: */
+# define BIO_get_write_guarantee(b) (int)BIO_ctrl(b,BIO_C_GET_WRITE_GUARANTEE,0,NULL)
+# define BIO_get_read_request(b)    (int)BIO_ctrl(b,BIO_C_GET_READ_REQUEST,0,NULL)
+size_t BIO_ctrl_get_write_guarantee(BIO *b);
+size_t BIO_ctrl_get_read_request(BIO *b);
+int BIO_ctrl_reset_read_request(BIO *b);
+
+/* ctrl macros for dgram */
+# define BIO_ctrl_dgram_connect(b,peer)  \
+                     (int)BIO_ctrl(b,BIO_CTRL_DGRAM_CONNECT,0, (char *)peer)
+# define BIO_ctrl_set_connected(b, state, peer) \
+         (int)BIO_ctrl(b, BIO_CTRL_DGRAM_SET_CONNECTED, state, (char *)peer)
+# define BIO_dgram_recv_timedout(b) \
+         (int)BIO_ctrl(b, BIO_CTRL_DGRAM_GET_RECV_TIMER_EXP, 0, NULL)
+# define BIO_dgram_send_timedout(b) \
+         (int)BIO_ctrl(b, BIO_CTRL_DGRAM_GET_SEND_TIMER_EXP, 0, NULL)
+# define BIO_dgram_get_peer(b,peer) \
+         (int)BIO_ctrl(b, BIO_CTRL_DGRAM_GET_PEER, 0, (char *)peer)
+# define BIO_dgram_set_peer(b,peer) \
+         (int)BIO_ctrl(b, BIO_CTRL_DGRAM_SET_PEER, 0, (char *)peer)
+# define BIO_dgram_get_mtu_overhead(b) \
+         (unsigned int)BIO_ctrl((b), BIO_CTRL_DGRAM_GET_MTU_OVERHEAD, 0, NULL)
+
+/* These two aren't currently implemented */
+/* int BIO_get_ex_num(BIO *bio); */
+/* void BIO_set_ex_free_func(BIO *bio,int idx,void (*cb)()); */
+int BIO_set_ex_data(BIO *bio, int idx, void *data);
+void *BIO_get_ex_data(BIO *bio, int idx);
+int BIO_get_ex_new_index(long argl, void *argp, CRYPTO_EX_new *new_func,
+                         CRYPTO_EX_dup *dup_func, CRYPTO_EX_free *free_func);
+unsigned long BIO_number_read(BIO *bio);
+unsigned long BIO_number_written(BIO *bio);
+
+/* For BIO_f_asn1() */
+int BIO_asn1_set_prefix(BIO *b, asn1_ps_func *prefix,
+                        asn1_ps_func *prefix_free);
+int BIO_asn1_get_prefix(BIO *b, asn1_ps_func **pprefix,
+                        asn1_ps_func **pprefix_free);
+int BIO_asn1_set_suffix(BIO *b, asn1_ps_func *suffix,
+                        asn1_ps_func *suffix_free);
+int BIO_asn1_get_suffix(BIO *b, asn1_ps_func **psuffix,
+                        asn1_ps_func **psuffix_free);
+
+# ifndef OPENSSL_NO_FP_API
+BIO_METHOD *BIO_s_file(void);
+BIO *BIO_new_file(const char *filename, const char *mode);
+BIO *BIO_new_fp(FILE *stream, int close_flag);
+#  define BIO_s_file_internal    BIO_s_file
+# endif
+BIO *BIO_new(BIO_METHOD *type);
+int BIO_set(BIO *a, BIO_METHOD *type);
+int BIO_free(BIO *a);
+void BIO_vfree(BIO *a);
+int BIO_read(BIO *b, void *data, int len);
+int BIO_gets(BIO *bp, char *buf, int size);
+int BIO_write(BIO *b, const void *data, int len);
+int BIO_puts(BIO *bp, const char *buf);
+int BIO_indent(BIO *b, int indent, int max);
+long BIO_ctrl(BIO *bp, int cmd, long larg, void *parg);
+long BIO_callback_ctrl(BIO *b, int cmd,
+                       void (*fp) (struct bio_st *, int, const char *, int,
+                                   long, long));
+char *BIO_ptr_ctrl(BIO *bp, int cmd, long larg);
+long BIO_int_ctrl(BIO *bp, int cmd, long larg, int iarg);
+BIO *BIO_push(BIO *b, BIO *append);
+BIO *BIO_pop(BIO *b);
+void BIO_free_all(BIO *a);
+BIO *BIO_find_type(BIO *b, int bio_type);
+BIO *BIO_next(BIO *b);
+BIO *BIO_get_retry_BIO(BIO *bio, int *reason);
+int BIO_get_retry_reason(BIO *bio);
+BIO *BIO_dup_chain(BIO *in);
+
+int BIO_nread0(BIO *bio, char **buf);
+int BIO_nread(BIO *bio, char **buf, int num);
+int BIO_nwrite0(BIO *bio, char **buf);
+int BIO_nwrite(BIO *bio, char **buf, int num);
+
+long BIO_debug_callback(BIO *bio, int cmd, const char *argp, int argi,
+                        long argl, long ret);
+
+BIO_METHOD *BIO_s_mem(void);
+BIO *BIO_new_mem_buf(const void *buf, int len);
+BIO_METHOD *BIO_s_socket(void);
+BIO_METHOD *BIO_s_connect(void);
+BIO_METHOD *BIO_s_accept(void);
+BIO_METHOD *BIO_s_fd(void);
+# ifndef OPENSSL_SYS_OS2
+BIO_METHOD *BIO_s_log(void);
+# endif
+BIO_METHOD *BIO_s_bio(void);
+BIO_METHOD *BIO_s_null(void);
+BIO_METHOD *BIO_f_null(void);
+BIO_METHOD *BIO_f_buffer(void);
+# ifdef OPENSSL_SYS_VMS
+BIO_METHOD *BIO_f_linebuffer(void);
+# endif
+BIO_METHOD *BIO_f_nbio_test(void);
+# ifndef OPENSSL_NO_DGRAM
+BIO_METHOD *BIO_s_datagram(void);
+#  ifndef OPENSSL_NO_SCTP
+BIO_METHOD *BIO_s_datagram_sctp(void);
+#  endif
+# endif
+
+/* BIO_METHOD *BIO_f_ber(void); */
+
+int BIO_sock_should_retry(int i);
+int BIO_sock_non_fatal_error(int error);
+int BIO_dgram_non_fatal_error(int error);
+
+int BIO_fd_should_retry(int i);
+int BIO_fd_non_fatal_error(int error);
+int BIO_dump_cb(int (*cb) (const void *data, size_t len, void *u),
+                void *u, const char *s, int len);
+int BIO_dump_indent_cb(int (*cb) (const void *data, size_t len, void *u),
+                       void *u, const char *s, int len, int indent);
+int BIO_dump(BIO *b, const char *bytes, int len);
+int BIO_dump_indent(BIO *b, const char *bytes, int len, int indent);
+# ifndef OPENSSL_NO_FP_API
+int BIO_dump_fp(FILE *fp, const char *s, int len);
+int BIO_dump_indent_fp(FILE *fp, const char *s, int len, int indent);
+# endif
+int BIO_hex_string(BIO *out, int indent, int width, unsigned char *data,
+                   int datalen);
+
+struct hostent *BIO_gethostbyname(const char *name);
+/*-
+ * We might want a thread-safe interface too:
+ * struct hostent *BIO_gethostbyname_r(const char *name,
+ *     struct hostent *result, void *buffer, size_t buflen);
+ * or something similar (caller allocates a struct hostent,
+ * pointed to by "result", and additional buffer space for the various
+ * substructures; if the buffer does not suffice, NULL is returned
+ * and an appropriate error code is set).
+ */
+int BIO_sock_error(int sock);
+int BIO_socket_ioctl(int fd, long type, void *arg);
+int BIO_socket_nbio(int fd, int mode);
+int BIO_get_port(const char *str, unsigned short *port_ptr);
+int BIO_get_host_ip(const char *str, unsigned char *ip);
+int BIO_get_accept_socket(char *host_port, int mode);
+int BIO_accept(int sock, char **ip_port);
+int BIO_sock_init(void);
+void BIO_sock_cleanup(void);
+int BIO_set_tcp_ndelay(int sock, int turn_on);
+
+BIO *BIO_new_socket(int sock, int close_flag);
+BIO *BIO_new_dgram(int fd, int close_flag);
+# ifndef OPENSSL_NO_SCTP
+BIO *BIO_new_dgram_sctp(int fd, int close_flag);
+int BIO_dgram_is_sctp(BIO *bio);
+int BIO_dgram_sctp_notification_cb(BIO *b,
+                                   void (*handle_notifications) (BIO *bio,
+                                                                 void
+                                                                 *context,
+                                                                 void *buf),
+                                   void *context);
+int BIO_dgram_sctp_wait_for_dry(BIO *b);
+int BIO_dgram_sctp_msg_waiting(BIO *b);
+# endif
+BIO *BIO_new_fd(int fd, int close_flag);
+BIO *BIO_new_connect(const char *host_port);
+BIO *BIO_new_accept(const char *host_port);
+
+int BIO_new_bio_pair(BIO **bio1, size_t writebuf1,
+                     BIO **bio2, size_t writebuf2);
+/*
+ * If successful, returns 1 and in *bio1, *bio2 two BIO pair endpoints.
+ * Otherwise returns 0 and sets *bio1 and *bio2 to NULL. Size 0 uses default
+ * value.
+ */
+
+void BIO_copy_next_retry(BIO *b);
+
+/*
+ * long BIO_ghbn_ctrl(int cmd,int iarg,char *parg);
+ */
+
+# ifdef __GNUC__
+#  define __bio_h__attr__ __attribute__
+# else
+#  define __bio_h__attr__(x)
+# endif
+int BIO_printf(BIO *bio, const char *format, ...)
+__bio_h__attr__((__format__(__printf__, 2, 3)));
+int BIO_vprintf(BIO *bio, const char *format, va_list args)
+__bio_h__attr__((__format__(__printf__, 2, 0)));
+int BIO_snprintf(char *buf, size_t n, const char *format, ...)
+__bio_h__attr__((__format__(__printf__, 3, 4)));
+int BIO_vsnprintf(char *buf, size_t n, const char *format, va_list args)
+__bio_h__attr__((__format__(__printf__, 3, 0)));
+# undef __bio_h__attr__
+
+/* BEGIN ERROR CODES */
+/*
+ * The following lines are auto generated by the script mkerr.pl. Any changes
+ * made after this point may be overwritten when the script is next run.
+ */
+void ERR_load_BIO_strings(void);
+
+/* Error codes for the BIO functions. */
+
+/* Function codes. */
+# define BIO_F_ACPT_STATE                                 100
+# define BIO_F_BIO_ACCEPT                                 101
+# define BIO_F_BIO_BER_GET_HEADER                         102
+# define BIO_F_BIO_CALLBACK_CTRL                          131
+# define BIO_F_BIO_CTRL                                   103
+# define BIO_F_BIO_GETHOSTBYNAME                          120
+# define BIO_F_BIO_GETS                                   104
+# define BIO_F_BIO_GET_ACCEPT_SOCKET                      105
+# define BIO_F_BIO_GET_HOST_IP                            106
+# define BIO_F_BIO_GET_PORT                               107
+# define BIO_F_BIO_MAKE_PAIR                              121
+# define BIO_F_BIO_NEW                                    108
+# define BIO_F_BIO_NEW_FILE                               109
+# define BIO_F_BIO_NEW_MEM_BUF                            126
+# define BIO_F_BIO_NREAD                                  123
+# define BIO_F_BIO_NREAD0                                 124
+# define BIO_F_BIO_NWRITE                                 125
+# define BIO_F_BIO_NWRITE0                                122
+# define BIO_F_BIO_PUTS                                   110
+# define BIO_F_BIO_READ                                   111
+# define BIO_F_BIO_SOCK_INIT                              112
+# define BIO_F_BIO_WRITE                                  113
+# define BIO_F_BUFFER_CTRL                                114
+# define BIO_F_CONN_CTRL                                  127
+# define BIO_F_CONN_STATE                                 115
+# define BIO_F_DGRAM_SCTP_READ                            132
+# define BIO_F_DGRAM_SCTP_WRITE                           133
+# define BIO_F_FILE_CTRL                                  116
+# define BIO_F_FILE_READ                                  130
+# define BIO_F_LINEBUFFER_CTRL                            129
+# define BIO_F_MEM_READ                                   128
+# define BIO_F_MEM_WRITE                                  117
+# define BIO_F_SSL_NEW                                    118
+# define BIO_F_WSASTARTUP                                 119
+
+/* Reason codes. */
+# define BIO_R_ACCEPT_ERROR                               100
+# define BIO_R_BAD_FOPEN_MODE                             101
+# define BIO_R_BAD_HOSTNAME_LOOKUP                        102
+# define BIO_R_BROKEN_PIPE                                124
+# define BIO_R_CONNECT_ERROR                              103
+# define BIO_R_EOF_ON_MEMORY_BIO                          127
+# define BIO_R_ERROR_SETTING_NBIO                         104
+# define BIO_R_ERROR_SETTING_NBIO_ON_ACCEPTED_SOCKET      105
+# define BIO_R_ERROR_SETTING_NBIO_ON_ACCEPT_SOCKET        106
+# define BIO_R_GETHOSTBYNAME_ADDR_IS_NOT_AF_INET          107
+# define BIO_R_INVALID_ARGUMENT                           125
+# define BIO_R_INVALID_IP_ADDRESS                         108
+# define BIO_R_IN_USE                                     123
+# define BIO_R_KEEPALIVE                                  109
+# define BIO_R_NBIO_CONNECT_ERROR                         110
+# define BIO_R_NO_ACCEPT_PORT_SPECIFIED                   111
+# define BIO_R_NO_HOSTNAME_SPECIFIED                      112
+# define BIO_R_NO_PORT_DEFINED                            113
+# define BIO_R_NO_PORT_SPECIFIED                          114
+# define BIO_R_NO_SUCH_FILE                               128
+# define BIO_R_NULL_PARAMETER                             115
+# define BIO_R_TAG_MISMATCH                               116
+# define BIO_R_UNABLE_TO_BIND_SOCKET                      117
+# define BIO_R_UNABLE_TO_CREATE_SOCKET                    118
+# define BIO_R_UNABLE_TO_LISTEN_SOCKET                    119
+# define BIO_R_UNINITIALIZED                              120
+# define BIO_R_UNSUPPORTED_METHOD                         121
+# define BIO_R_WRITE_TO_READ_ONLY_BIO                     126
+# define BIO_R_WSASTARTUP                                 122
+
+#ifdef  __cplusplus
+}
+#endif
+#endif

+ 130 - 0
libssh2/openssl/include/openssl/blowfish.h

@@ -0,0 +1,130 @@
+/* crypto/bf/blowfish.h */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * 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 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. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    "This product includes cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``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 AUTHOR OR CONTRIBUTORS 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.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+#ifndef HEADER_BLOWFISH_H
+# define HEADER_BLOWFISH_H
+
+# include <openssl/e_os2.h>
+
+#ifdef  __cplusplus
+extern "C" {
+#endif
+
+# ifdef OPENSSL_NO_BF
+#  error BF is disabled.
+# endif
+
+# define BF_ENCRYPT      1
+# define BF_DECRYPT      0
+
+/*-
+ * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+ * ! BF_LONG has to be at least 32 bits wide. If it's wider, then !
+ * ! BF_LONG_LOG2 has to be defined along.                        !
+ * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+ */
+
+# if defined(__LP32__)
+#  define BF_LONG unsigned long
+# elif defined(OPENSSL_SYS_CRAY) || defined(__ILP64__)
+#  define BF_LONG unsigned long
+#  define BF_LONG_LOG2 3
+/*
+ * _CRAY note. I could declare short, but I have no idea what impact
+ * does it have on performance on none-T3E machines. I could declare
+ * int, but at least on C90 sizeof(int) can be chosen at compile time.
+ * So I've chosen long...
+ *                                      <appro@fy.chalmers.se>
+ */
+# else
+#  define BF_LONG unsigned int
+# endif
+
+# define BF_ROUNDS       16
+# define BF_BLOCK        8
+
+typedef struct bf_key_st {
+    BF_LONG P[BF_ROUNDS + 2];
+    BF_LONG S[4 * 256];
+} BF_KEY;
+
+# ifdef OPENSSL_FIPS
+void private_BF_set_key(BF_KEY *key, int len, const unsigned char *data);
+# endif
+void BF_set_key(BF_KEY *key, int len, const unsigned char *data);
+
+void BF_encrypt(BF_LONG *data, const BF_KEY *key);
+void BF_decrypt(BF_LONG *data, const BF_KEY *key);
+
+void BF_ecb_encrypt(const unsigned char *in, unsigned char *out,
+                    const BF_KEY *key, int enc);
+void BF_cbc_encrypt(const unsigned char *in, unsigned char *out, long length,
+                    const BF_KEY *schedule, unsigned char *ivec, int enc);
+void BF_cfb64_encrypt(const unsigned char *in, unsigned char *out,
+                      long length, const BF_KEY *schedule,
+                      unsigned char *ivec, int *num, int enc);
+void BF_ofb64_encrypt(const unsigned char *in, unsigned char *out,
+                      long length, const BF_KEY *schedule,
+                      unsigned char *ivec, int *num);
+const char *BF_options(void);
+
+#ifdef  __cplusplus
+}
+#endif
+
+#endif

+ 1015 - 0
libssh2/openssl/include/openssl/bn.h

@@ -0,0 +1,1015 @@
+/* crypto/bn/bn.h */
+/* Copyright (C) 1995-1997 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * 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 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. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    "This product includes cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``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 AUTHOR OR CONTRIBUTORS 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.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+/* ====================================================================
+ * Copyright (c) 1998-2018 The OpenSSL 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. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    openssl-core@openssl.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED 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 OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS 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.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com).  This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+/* ====================================================================
+ * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED.
+ *
+ * Portions of the attached software ("Contribution") are developed by
+ * SUN MICROSYSTEMS, INC., and are contributed to the OpenSSL project.
+ *
+ * The Contribution is licensed pursuant to the Eric Young open source
+ * license provided above.
+ *
+ * The binary polynomial arithmetic software is originally written by
+ * Sheueling Chang Shantz and Douglas Stebila of Sun Microsystems Laboratories.
+ *
+ */
+
+#ifndef HEADER_BN_H
+# define HEADER_BN_H
+
+# include <limits.h>
+# include <openssl/e_os2.h>
+# ifndef OPENSSL_NO_FP_API
+#  include <stdio.h>            /* FILE */
+# endif
+# include <openssl/ossl_typ.h>
+# include <openssl/crypto.h>
+
+#ifdef  __cplusplus
+extern "C" {
+#endif
+
+/*
+ * These preprocessor symbols control various aspects of the bignum headers
+ * and library code. They're not defined by any "normal" configuration, as
+ * they are intended for development and testing purposes. NB: defining all
+ * three can be useful for debugging application code as well as openssl
+ * itself. BN_DEBUG - turn on various debugging alterations to the bignum
+ * code BN_DEBUG_RAND - uses random poisoning of unused words to trip up
+ * mismanagement of bignum internals. You must also define BN_DEBUG.
+ */
+/* #define BN_DEBUG */
+/* #define BN_DEBUG_RAND */
+
+# ifndef OPENSSL_SMALL_FOOTPRINT
+#  define BN_MUL_COMBA
+#  define BN_SQR_COMBA
+#  define BN_RECURSION
+# endif
+
+/*
+ * This next option uses the C libraries (2 word)/(1 word) function. If it is
+ * not defined, I use my C version (which is slower). The reason for this
+ * flag is that when the particular C compiler library routine is used, and
+ * the library is linked with a different compiler, the library is missing.
+ * This mostly happens when the library is built with gcc and then linked
+ * using normal cc.  This would be a common occurrence because gcc normally
+ * produces code that is 2 times faster than system compilers for the big
+ * number stuff. For machines with only one compiler (or shared libraries),
+ * this should be on.  Again this in only really a problem on machines using
+ * "long long's", are 32bit, and are not using my assembler code.
+ */
+# if defined(OPENSSL_SYS_MSDOS) || defined(OPENSSL_SYS_WINDOWS) || \
+    defined(OPENSSL_SYS_WIN32) || defined(linux)
+#  ifndef BN_DIV2W
+#   define BN_DIV2W
+#  endif
+# endif
+
+/*
+ * assuming long is 64bit - this is the DEC Alpha unsigned long long is only
+ * 64 bits :-(, don't define BN_LLONG for the DEC Alpha
+ */
+# ifdef SIXTY_FOUR_BIT_LONG
+#  define BN_ULLONG       unsigned long long
+#  define BN_ULONG        unsigned long
+#  define BN_LONG         long
+#  define BN_BITS         128
+#  define BN_BYTES        8
+#  define BN_BITS2        64
+#  define BN_BITS4        32
+#  define BN_MASK         (0xffffffffffffffffffffffffffffffffLL)
+#  define BN_MASK2        (0xffffffffffffffffL)
+#  define BN_MASK2l       (0xffffffffL)
+#  define BN_MASK2h       (0xffffffff00000000L)
+#  define BN_MASK2h1      (0xffffffff80000000L)
+#  define BN_TBIT         (0x8000000000000000L)
+#  define BN_DEC_CONV     (10000000000000000000UL)
+#  define BN_DEC_FMT1     "%lu"
+#  define BN_DEC_FMT2     "%019lu"
+#  define BN_DEC_NUM      19
+#  define BN_HEX_FMT1     "%lX"
+#  define BN_HEX_FMT2     "%016lX"
+# endif
+
+/*
+ * This is where the long long data type is 64 bits, but long is 32. For
+ * machines where there are 64bit registers, this is the mode to use. IRIX,
+ * on R4000 and above should use this mode, along with the relevant assembler
+ * code :-).  Do NOT define BN_LLONG.
+ */
+# ifdef SIXTY_FOUR_BIT
+#  undef BN_LLONG
+#  undef BN_ULLONG
+#  define BN_ULONG        unsigned long long
+#  define BN_LONG         long long
+#  define BN_BITS         128
+#  define BN_BYTES        8
+#  define BN_BITS2        64
+#  define BN_BITS4        32
+#  define BN_MASK2        (0xffffffffffffffffLL)
+#  define BN_MASK2l       (0xffffffffL)
+#  define BN_MASK2h       (0xffffffff00000000LL)
+#  define BN_MASK2h1      (0xffffffff80000000LL)
+#  define BN_TBIT         (0x8000000000000000LL)
+#  define BN_DEC_CONV     (10000000000000000000ULL)
+#  define BN_DEC_FMT1     "%llu"
+#  define BN_DEC_FMT2     "%019llu"
+#  define BN_DEC_NUM      19
+#  define BN_HEX_FMT1     "%llX"
+#  define BN_HEX_FMT2     "%016llX"
+# endif
+
+# ifdef THIRTY_TWO_BIT
+#  ifdef BN_LLONG
+#   if defined(_WIN32) && !defined(__GNUC__)
+#    define BN_ULLONG     unsigned __int64
+#    define BN_MASK       (0xffffffffffffffffI64)
+#   else
+#    define BN_ULLONG     unsigned long long
+#    define BN_MASK       (0xffffffffffffffffLL)
+#   endif
+#  endif
+#  define BN_ULONG        unsigned int
+#  define BN_LONG         int
+#  define BN_BITS         64
+#  define BN_BYTES        4
+#  define BN_BITS2        32
+#  define BN_BITS4        16
+#  define BN_MASK2        (0xffffffffL)
+#  define BN_MASK2l       (0xffff)
+#  define BN_MASK2h1      (0xffff8000L)
+#  define BN_MASK2h       (0xffff0000L)
+#  define BN_TBIT         (0x80000000L)
+#  define BN_DEC_CONV     (1000000000L)
+#  define BN_DEC_FMT1     "%u"
+#  define BN_DEC_FMT2     "%09u"
+#  define BN_DEC_NUM      9
+#  define BN_HEX_FMT1     "%X"
+#  define BN_HEX_FMT2     "%08X"
+# endif
+
+# define BN_DEFAULT_BITS 1280
+
+# define BN_FLG_MALLOCED         0x01
+# define BN_FLG_STATIC_DATA      0x02
+
+/*
+ * avoid leaking exponent information through timing,
+ * BN_mod_exp_mont() will call BN_mod_exp_mont_consttime,
+ * BN_div() will call BN_div_no_branch,
+ * BN_mod_inverse() will call BN_mod_inverse_no_branch.
+ */
+# define BN_FLG_CONSTTIME        0x04
+
+# ifdef OPENSSL_NO_DEPRECATED
+/* deprecated name for the flag */
+#  define BN_FLG_EXP_CONSTTIME BN_FLG_CONSTTIME
+/*
+ * avoid leaking exponent information through timings
+ * (BN_mod_exp_mont() will call BN_mod_exp_mont_consttime)
+ */
+# endif
+
+# ifndef OPENSSL_NO_DEPRECATED
+#  define BN_FLG_FREE             0x8000
+                                       /* used for debuging */
+# endif
+# define BN_set_flags(b,n)       ((b)->flags|=(n))
+# define BN_get_flags(b,n)       ((b)->flags&(n))
+
+/*
+ * get a clone of a BIGNUM with changed flags, for *temporary* use only (the
+ * two BIGNUMs cannot not be used in parallel!)
+ */
+# define BN_with_flags(dest,b,n)  ((dest)->d=(b)->d, \
+                                  (dest)->top=(b)->top, \
+                                  (dest)->dmax=(b)->dmax, \
+                                  (dest)->neg=(b)->neg, \
+                                  (dest)->flags=(((dest)->flags & BN_FLG_MALLOCED) \
+                                                 |  ((b)->flags & ~BN_FLG_MALLOCED) \
+                                                 |  BN_FLG_STATIC_DATA \
+                                                 |  (n)))
+
+/* Already declared in ossl_typ.h */
+# if 0
+typedef struct bignum_st BIGNUM;
+/* Used for temp variables (declaration hidden in bn_lcl.h) */
+typedef struct bignum_ctx BN_CTX;
+typedef struct bn_blinding_st BN_BLINDING;
+typedef struct bn_mont_ctx_st BN_MONT_CTX;
+typedef struct bn_recp_ctx_st BN_RECP_CTX;
+typedef struct bn_gencb_st BN_GENCB;
+# endif
+
+struct bignum_st {
+    BN_ULONG *d;                /* Pointer to an array of 'BN_BITS2' bit
+                                 * chunks. */
+    int top;                    /* Index of last used d +1. */
+    /* The next are internal book keeping for bn_expand. */
+    int dmax;                   /* Size of the d array. */
+    int neg;                    /* one if the number is negative */
+    int flags;
+};
+
+/* Used for montgomery multiplication */
+struct bn_mont_ctx_st {
+    int ri;                     /* number of bits in R */
+    BIGNUM RR;                  /* used to convert to montgomery form */
+    BIGNUM N;                   /* The modulus */
+    BIGNUM Ni;                  /* R*(1/R mod N) - N*Ni = 1 (Ni is only
+                                 * stored for bignum algorithm) */
+    BN_ULONG n0[2];             /* least significant word(s) of Ni; (type
+                                 * changed with 0.9.9, was "BN_ULONG n0;"
+                                 * before) */
+    int flags;
+};
+
+/*
+ * Used for reciprocal division/mod functions It cannot be shared between
+ * threads
+ */
+struct bn_recp_ctx_st {
+    BIGNUM N;                   /* the divisor */
+    BIGNUM Nr;                  /* the reciprocal */
+    int num_bits;
+    int shift;
+    int flags;
+};
+
+/* Used for slow "generation" functions. */
+struct bn_gencb_st {
+    unsigned int ver;           /* To handle binary (in)compatibility */
+    void *arg;                  /* callback-specific data */
+    union {
+        /* if(ver==1) - handles old style callbacks */
+        void (*cb_1) (int, int, void *);
+        /* if(ver==2) - new callback style */
+        int (*cb_2) (int, int, BN_GENCB *);
+    } cb;
+};
+/* Wrapper function to make using BN_GENCB easier,  */
+int BN_GENCB_call(BN_GENCB *cb, int a, int b);
+/* Macro to populate a BN_GENCB structure with an "old"-style callback */
+# define BN_GENCB_set_old(gencb, callback, cb_arg) { \
+                BN_GENCB *tmp_gencb = (gencb); \
+                tmp_gencb->ver = 1; \
+                tmp_gencb->arg = (cb_arg); \
+                tmp_gencb->cb.cb_1 = (callback); }
+/* Macro to populate a BN_GENCB structure with a "new"-style callback */
+# define BN_GENCB_set(gencb, callback, cb_arg) { \
+                BN_GENCB *tmp_gencb = (gencb); \
+                tmp_gencb->ver = 2; \
+                tmp_gencb->arg = (cb_arg); \
+                tmp_gencb->cb.cb_2 = (callback); }
+
+# define BN_prime_checks 0      /* default: select number of iterations based
+                                 * on the size of the number */
+
+/*
+ * BN_prime_checks_for_size() returns the number of Miller-Rabin iterations
+ * that will be done for checking that a random number is probably prime. The
+ * error rate for accepting a composite number as prime depends on the size of
+ * the prime |b|. The error rates used are for calculating an RSA key with 2 primes,
+ * and so the level is what you would expect for a key of double the size of the
+ * prime.
+ *
+ * This table is generated using the algorithm of FIPS PUB 186-4
+ * Digital Signature Standard (DSS), section F.1, page 117.
+ * (https://dx.doi.org/10.6028/NIST.FIPS.186-4)
+ *
+ * The following magma script was used to generate the output:
+ * securitybits:=125;
+ * k:=1024;
+ * for t:=1 to 65 do
+ *   for M:=3 to Floor(2*Sqrt(k-1)-1) do
+ *     S:=0;
+ *     // Sum over m
+ *     for m:=3 to M do
+ *       s:=0;
+ *       // Sum over j
+ *       for j:=2 to m do
+ *         s+:=(RealField(32)!2)^-(j+(k-1)/j);
+ *       end for;
+ *       S+:=2^(m-(m-1)*t)*s;
+ *     end for;
+ *     A:=2^(k-2-M*t);
+ *     B:=8*(Pi(RealField(32))^2-6)/3*2^(k-2)*S;
+ *     pkt:=2.00743*Log(2)*k*2^-k*(A+B);
+ *     seclevel:=Floor(-Log(2,pkt));
+ *     if seclevel ge securitybits then
+ *       printf "k: %5o, security: %o bits  (t: %o, M: %o)\n",k,seclevel,t,M;
+ *       break;
+ *     end if;
+ *   end for;
+ *   if seclevel ge securitybits then break; end if;
+ * end for;
+ *
+ * It can be run online at:
+ * http://magma.maths.usyd.edu.au/calc
+ *
+ * And will output:
+ * k:  1024, security: 129 bits  (t: 6, M: 23)
+ *
+ * k is the number of bits of the prime, securitybits is the level we want to
+ * reach.
+ *
+ * prime length | RSA key size | # MR tests | security level
+ * -------------+--------------|------------+---------------
+ *  (b) >= 6394 |     >= 12788 |          3 |        256 bit
+ *  (b) >= 3747 |     >=  7494 |          3 |        192 bit
+ *  (b) >= 1345 |     >=  2690 |          4 |        128 bit
+ *  (b) >= 1080 |     >=  2160 |          5 |        128 bit
+ *  (b) >=  852 |     >=  1704 |          5 |        112 bit
+ *  (b) >=  476 |     >=   952 |          5 |         80 bit
+ *  (b) >=  400 |     >=   800 |          6 |         80 bit
+ *  (b) >=  347 |     >=   694 |          7 |         80 bit
+ *  (b) >=  308 |     >=   616 |          8 |         80 bit
+ *  (b) >=   55 |     >=   110 |         27 |         64 bit
+ *  (b) >=    6 |     >=    12 |         34 |         64 bit
+ */
+
+# define BN_prime_checks_for_size(b) ((b) >= 3747 ?  3 : \
+                                (b) >=  1345 ?  4 : \
+                                (b) >=  476 ?  5 : \
+                                (b) >=  400 ?  6 : \
+                                (b) >=  347 ?  7 : \
+                                (b) >=  308 ?  8 : \
+                                (b) >=  55  ? 27 : \
+                                /* b >= 6 */ 34)
+
+# define BN_num_bytes(a) ((BN_num_bits(a)+7)/8)
+
+/* Note that BN_abs_is_word didn't work reliably for w == 0 until 0.9.8 */
+# define BN_abs_is_word(a,w) ((((a)->top == 1) && ((a)->d[0] == (BN_ULONG)(w))) || \
+                                (((w) == 0) && ((a)->top == 0)))
+# define BN_is_zero(a)       ((a)->top == 0)
+# define BN_is_one(a)        (BN_abs_is_word((a),1) && !(a)->neg)
+# define BN_is_word(a,w)     (BN_abs_is_word((a),(w)) && (!(w) || !(a)->neg))
+# define BN_is_odd(a)        (((a)->top > 0) && ((a)->d[0] & 1))
+
+# define BN_one(a)       (BN_set_word((a),1))
+# define BN_zero_ex(a) \
+        do { \
+                BIGNUM *_tmp_bn = (a); \
+                _tmp_bn->top = 0; \
+                _tmp_bn->neg = 0; \
+        } while(0)
+# ifdef OPENSSL_NO_DEPRECATED
+#  define BN_zero(a)      BN_zero_ex(a)
+# else
+#  define BN_zero(a)      (BN_set_word((a),0))
+# endif
+
+const BIGNUM *BN_value_one(void);
+char *BN_options(void);
+BN_CTX *BN_CTX_new(void);
+# ifndef OPENSSL_NO_DEPRECATED
+void BN_CTX_init(BN_CTX *c);
+# endif
+void BN_CTX_free(BN_CTX *c);
+void BN_CTX_start(BN_CTX *ctx);
+BIGNUM *BN_CTX_get(BN_CTX *ctx);
+void BN_CTX_end(BN_CTX *ctx);
+int BN_rand(BIGNUM *rnd, int bits, int top, int bottom);
+int BN_pseudo_rand(BIGNUM *rnd, int bits, int top, int bottom);
+int BN_rand_range(BIGNUM *rnd, const BIGNUM *range);
+int BN_pseudo_rand_range(BIGNUM *rnd, const BIGNUM *range);
+int BN_num_bits(const BIGNUM *a);
+int BN_num_bits_word(BN_ULONG);
+BIGNUM *BN_new(void);
+void BN_init(BIGNUM *);
+void BN_clear_free(BIGNUM *a);
+BIGNUM *BN_copy(BIGNUM *a, const BIGNUM *b);
+void BN_swap(BIGNUM *a, BIGNUM *b);
+BIGNUM *BN_bin2bn(const unsigned char *s, int len, BIGNUM *ret);
+int BN_bn2bin(const BIGNUM *a, unsigned char *to);
+BIGNUM *BN_mpi2bn(const unsigned char *s, int len, BIGNUM *ret);
+int BN_bn2mpi(const BIGNUM *a, unsigned char *to);
+int BN_sub(BIGNUM *r, const BIGNUM *a, const BIGNUM *b);
+int BN_usub(BIGNUM *r, const BIGNUM *a, const BIGNUM *b);
+int BN_uadd(BIGNUM *r, const BIGNUM *a, const BIGNUM *b);
+int BN_add(BIGNUM *r, const BIGNUM *a, const BIGNUM *b);
+int BN_mul(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx);
+int BN_sqr(BIGNUM *r, const BIGNUM *a, BN_CTX *ctx);
+/** BN_set_negative sets sign of a BIGNUM
+ * \param  b  pointer to the BIGNUM object
+ * \param  n  0 if the BIGNUM b should be positive and a value != 0 otherwise
+ */
+void BN_set_negative(BIGNUM *b, int n);
+/** BN_is_negative returns 1 if the BIGNUM is negative
+ * \param  a  pointer to the BIGNUM object
+ * \return 1 if a < 0 and 0 otherwise
+ */
+# define BN_is_negative(a) ((a)->neg != 0)
+
+int BN_div(BIGNUM *dv, BIGNUM *rem, const BIGNUM *m, const BIGNUM *d,
+           BN_CTX *ctx);
+# define BN_mod(rem,m,d,ctx) BN_div(NULL,(rem),(m),(d),(ctx))
+int BN_nnmod(BIGNUM *r, const BIGNUM *m, const BIGNUM *d, BN_CTX *ctx);
+int BN_mod_add(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, const BIGNUM *m,
+               BN_CTX *ctx);
+int BN_mod_add_quick(BIGNUM *r, const BIGNUM *a, const BIGNUM *b,
+                     const BIGNUM *m);
+int BN_mod_sub(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, const BIGNUM *m,
+               BN_CTX *ctx);
+int BN_mod_sub_quick(BIGNUM *r, const BIGNUM *a, const BIGNUM *b,
+                     const BIGNUM *m);
+int BN_mod_mul(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, const BIGNUM *m,
+               BN_CTX *ctx);
+int BN_mod_sqr(BIGNUM *r, const BIGNUM *a, const BIGNUM *m, BN_CTX *ctx);
+int BN_mod_lshift1(BIGNUM *r, const BIGNUM *a, const BIGNUM *m, BN_CTX *ctx);
+int BN_mod_lshift1_quick(BIGNUM *r, const BIGNUM *a, const BIGNUM *m);
+int BN_mod_lshift(BIGNUM *r, const BIGNUM *a, int n, const BIGNUM *m,
+                  BN_CTX *ctx);
+int BN_mod_lshift_quick(BIGNUM *r, const BIGNUM *a, int n, const BIGNUM *m);
+
+BN_ULONG BN_mod_word(const BIGNUM *a, BN_ULONG w);
+BN_ULONG BN_div_word(BIGNUM *a, BN_ULONG w);
+int BN_mul_word(BIGNUM *a, BN_ULONG w);
+int BN_add_word(BIGNUM *a, BN_ULONG w);
+int BN_sub_word(BIGNUM *a, BN_ULONG w);
+int BN_set_word(BIGNUM *a, BN_ULONG w);
+BN_ULONG BN_get_word(const BIGNUM *a);
+
+int BN_cmp(const BIGNUM *a, const BIGNUM *b);
+void BN_free(BIGNUM *a);
+int BN_is_bit_set(const BIGNUM *a, int n);
+int BN_lshift(BIGNUM *r, const BIGNUM *a, int n);
+int BN_lshift1(BIGNUM *r, const BIGNUM *a);
+int BN_exp(BIGNUM *r, const BIGNUM *a, const BIGNUM *p, BN_CTX *ctx);
+
+int BN_mod_exp(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
+               const BIGNUM *m, BN_CTX *ctx);
+int BN_mod_exp_mont(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
+                    const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *m_ctx);
+int BN_mod_exp_mont_consttime(BIGNUM *rr, const BIGNUM *a, const BIGNUM *p,
+                              const BIGNUM *m, BN_CTX *ctx,
+                              BN_MONT_CTX *in_mont);
+int BN_mod_exp_mont_word(BIGNUM *r, BN_ULONG a, const BIGNUM *p,
+                         const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *m_ctx);
+int BN_mod_exp2_mont(BIGNUM *r, const BIGNUM *a1, const BIGNUM *p1,
+                     const BIGNUM *a2, const BIGNUM *p2, const BIGNUM *m,
+                     BN_CTX *ctx, BN_MONT_CTX *m_ctx);
+int BN_mod_exp_simple(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
+                      const BIGNUM *m, BN_CTX *ctx);
+
+int BN_mask_bits(BIGNUM *a, int n);
+# ifndef OPENSSL_NO_FP_API
+int BN_print_fp(FILE *fp, const BIGNUM *a);
+# endif
+# ifdef HEADER_BIO_H
+int BN_print(BIO *fp, const BIGNUM *a);
+# else
+int BN_print(void *fp, const BIGNUM *a);
+# endif
+int BN_reciprocal(BIGNUM *r, const BIGNUM *m, int len, BN_CTX *ctx);
+int BN_rshift(BIGNUM *r, const BIGNUM *a, int n);
+int BN_rshift1(BIGNUM *r, const BIGNUM *a);
+void BN_clear(BIGNUM *a);
+BIGNUM *BN_dup(const BIGNUM *a);
+int BN_ucmp(const BIGNUM *a, const BIGNUM *b);
+int BN_set_bit(BIGNUM *a, int n);
+int BN_clear_bit(BIGNUM *a, int n);
+char *BN_bn2hex(const BIGNUM *a);
+char *BN_bn2dec(const BIGNUM *a);
+int BN_hex2bn(BIGNUM **a, const char *str);
+int BN_dec2bn(BIGNUM **a, const char *str);
+int BN_asc2bn(BIGNUM **a, const char *str);
+int BN_gcd(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx);
+int BN_kronecker(const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx); /* returns
+                                                                  * -2 for
+                                                                  * error */
+BIGNUM *BN_mod_inverse(BIGNUM *ret,
+                       const BIGNUM *a, const BIGNUM *n, BN_CTX *ctx);
+BIGNUM *BN_mod_sqrt(BIGNUM *ret,
+                    const BIGNUM *a, const BIGNUM *n, BN_CTX *ctx);
+
+void BN_consttime_swap(BN_ULONG swap, BIGNUM *a, BIGNUM *b, int nwords);
+
+/* Deprecated versions */
+# ifndef OPENSSL_NO_DEPRECATED
+BIGNUM *BN_generate_prime(BIGNUM *ret, int bits, int safe,
+                          const BIGNUM *add, const BIGNUM *rem,
+                          void (*callback) (int, int, void *), void *cb_arg);
+int BN_is_prime(const BIGNUM *p, int nchecks,
+                void (*callback) (int, int, void *),
+                BN_CTX *ctx, void *cb_arg);
+int BN_is_prime_fasttest(const BIGNUM *p, int nchecks,
+                         void (*callback) (int, int, void *), BN_CTX *ctx,
+                         void *cb_arg, int do_trial_division);
+# endif                         /* !defined(OPENSSL_NO_DEPRECATED) */
+
+/* Newer versions */
+int BN_generate_prime_ex(BIGNUM *ret, int bits, int safe, const BIGNUM *add,
+                         const BIGNUM *rem, BN_GENCB *cb);
+int BN_is_prime_ex(const BIGNUM *p, int nchecks, BN_CTX *ctx, BN_GENCB *cb);
+int BN_is_prime_fasttest_ex(const BIGNUM *p, int nchecks, BN_CTX *ctx,
+                            int do_trial_division, BN_GENCB *cb);
+
+int BN_X931_generate_Xpq(BIGNUM *Xp, BIGNUM *Xq, int nbits, BN_CTX *ctx);
+
+int BN_X931_derive_prime_ex(BIGNUM *p, BIGNUM *p1, BIGNUM *p2,
+                            const BIGNUM *Xp, const BIGNUM *Xp1,
+                            const BIGNUM *Xp2, const BIGNUM *e, BN_CTX *ctx,
+                            BN_GENCB *cb);
+int BN_X931_generate_prime_ex(BIGNUM *p, BIGNUM *p1, BIGNUM *p2, BIGNUM *Xp1,
+                              BIGNUM *Xp2, const BIGNUM *Xp, const BIGNUM *e,
+                              BN_CTX *ctx, BN_GENCB *cb);
+
+BN_MONT_CTX *BN_MONT_CTX_new(void);
+void BN_MONT_CTX_init(BN_MONT_CTX *ctx);
+int BN_mod_mul_montgomery(BIGNUM *r, const BIGNUM *a, const BIGNUM *b,
+                          BN_MONT_CTX *mont, BN_CTX *ctx);
+# define BN_to_montgomery(r,a,mont,ctx)  BN_mod_mul_montgomery(\
+        (r),(a),&((mont)->RR),(mont),(ctx))
+int BN_from_montgomery(BIGNUM *r, const BIGNUM *a,
+                       BN_MONT_CTX *mont, BN_CTX *ctx);
+void BN_MONT_CTX_free(BN_MONT_CTX *mont);
+int BN_MONT_CTX_set(BN_MONT_CTX *mont, const BIGNUM *mod, BN_CTX *ctx);
+BN_MONT_CTX *BN_MONT_CTX_copy(BN_MONT_CTX *to, BN_MONT_CTX *from);
+BN_MONT_CTX *BN_MONT_CTX_set_locked(BN_MONT_CTX **pmont, int lock,
+                                    const BIGNUM *mod, BN_CTX *ctx);
+
+/* BN_BLINDING flags */
+# define BN_BLINDING_NO_UPDATE   0x00000001
+# define BN_BLINDING_NO_RECREATE 0x00000002
+
+BN_BLINDING *BN_BLINDING_new(const BIGNUM *A, const BIGNUM *Ai, BIGNUM *mod);
+void BN_BLINDING_free(BN_BLINDING *b);
+int BN_BLINDING_update(BN_BLINDING *b, BN_CTX *ctx);
+int BN_BLINDING_convert(BIGNUM *n, BN_BLINDING *b, BN_CTX *ctx);
+int BN_BLINDING_invert(BIGNUM *n, BN_BLINDING *b, BN_CTX *ctx);
+int BN_BLINDING_convert_ex(BIGNUM *n, BIGNUM *r, BN_BLINDING *b, BN_CTX *);
+int BN_BLINDING_invert_ex(BIGNUM *n, const BIGNUM *r, BN_BLINDING *b,
+                          BN_CTX *);
+# ifndef OPENSSL_NO_DEPRECATED
+unsigned long BN_BLINDING_get_thread_id(const BN_BLINDING *);
+void BN_BLINDING_set_thread_id(BN_BLINDING *, unsigned long);
+# endif
+CRYPTO_THREADID *BN_BLINDING_thread_id(BN_BLINDING *);
+unsigned long BN_BLINDING_get_flags(const BN_BLINDING *);
+void BN_BLINDING_set_flags(BN_BLINDING *, unsigned long);
+BN_BLINDING *BN_BLINDING_create_param(BN_BLINDING *b,
+                                      const BIGNUM *e, BIGNUM *m, BN_CTX *ctx,
+                                      int (*bn_mod_exp) (BIGNUM *r,
+                                                         const BIGNUM *a,
+                                                         const BIGNUM *p,
+                                                         const BIGNUM *m,
+                                                         BN_CTX *ctx,
+                                                         BN_MONT_CTX *m_ctx),
+                                      BN_MONT_CTX *m_ctx);
+
+# ifndef OPENSSL_NO_DEPRECATED
+void BN_set_params(int mul, int high, int low, int mont);
+int BN_get_params(int which);   /* 0, mul, 1 high, 2 low, 3 mont */
+# endif
+
+void BN_RECP_CTX_init(BN_RECP_CTX *recp);
+BN_RECP_CTX *BN_RECP_CTX_new(void);
+void BN_RECP_CTX_free(BN_RECP_CTX *recp);
+int BN_RECP_CTX_set(BN_RECP_CTX *recp, const BIGNUM *rdiv, BN_CTX *ctx);
+int BN_mod_mul_reciprocal(BIGNUM *r, const BIGNUM *x, const BIGNUM *y,
+                          BN_RECP_CTX *recp, BN_CTX *ctx);
+int BN_mod_exp_recp(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
+                    const BIGNUM *m, BN_CTX *ctx);
+int BN_div_recp(BIGNUM *dv, BIGNUM *rem, const BIGNUM *m,
+                BN_RECP_CTX *recp, BN_CTX *ctx);
+
+# ifndef OPENSSL_NO_EC2M
+
+/*
+ * Functions for arithmetic over binary polynomials represented by BIGNUMs.
+ * The BIGNUM::neg property of BIGNUMs representing binary polynomials is
+ * ignored. Note that input arguments are not const so that their bit arrays
+ * can be expanded to the appropriate size if needed.
+ */
+
+/*
+ * r = a + b
+ */
+int BN_GF2m_add(BIGNUM *r, const BIGNUM *a, const BIGNUM *b);
+#  define BN_GF2m_sub(r, a, b) BN_GF2m_add(r, a, b)
+/*
+ * r=a mod p
+ */
+int BN_GF2m_mod(BIGNUM *r, const BIGNUM *a, const BIGNUM *p);
+/* r = (a * b) mod p */
+int BN_GF2m_mod_mul(BIGNUM *r, const BIGNUM *a, const BIGNUM *b,
+                    const BIGNUM *p, BN_CTX *ctx);
+/* r = (a * a) mod p */
+int BN_GF2m_mod_sqr(BIGNUM *r, const BIGNUM *a, const BIGNUM *p, BN_CTX *ctx);
+/* r = (1 / b) mod p */
+int BN_GF2m_mod_inv(BIGNUM *r, const BIGNUM *b, const BIGNUM *p, BN_CTX *ctx);
+/* r = (a / b) mod p */
+int BN_GF2m_mod_div(BIGNUM *r, const BIGNUM *a, const BIGNUM *b,
+                    const BIGNUM *p, BN_CTX *ctx);
+/* r = (a ^ b) mod p */
+int BN_GF2m_mod_exp(BIGNUM *r, const BIGNUM *a, const BIGNUM *b,
+                    const BIGNUM *p, BN_CTX *ctx);
+/* r = sqrt(a) mod p */
+int BN_GF2m_mod_sqrt(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
+                     BN_CTX *ctx);
+/* r^2 + r = a mod p */
+int BN_GF2m_mod_solve_quad(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
+                           BN_CTX *ctx);
+#  define BN_GF2m_cmp(a, b) BN_ucmp((a), (b))
+/*-
+ * Some functions allow for representation of the irreducible polynomials
+ * as an unsigned int[], say p.  The irreducible f(t) is then of the form:
+ *     t^p[0] + t^p[1] + ... + t^p[k]
+ * where m = p[0] > p[1] > ... > p[k] = 0.
+ */
+/* r = a mod p */
+int BN_GF2m_mod_arr(BIGNUM *r, const BIGNUM *a, const int p[]);
+/* r = (a * b) mod p */
+int BN_GF2m_mod_mul_arr(BIGNUM *r, const BIGNUM *a, const BIGNUM *b,
+                        const int p[], BN_CTX *ctx);
+/* r = (a * a) mod p */
+int BN_GF2m_mod_sqr_arr(BIGNUM *r, const BIGNUM *a, const int p[],
+                        BN_CTX *ctx);
+/* r = (1 / b) mod p */
+int BN_GF2m_mod_inv_arr(BIGNUM *r, const BIGNUM *b, const int p[],
+                        BN_CTX *ctx);
+/* r = (a / b) mod p */
+int BN_GF2m_mod_div_arr(BIGNUM *r, const BIGNUM *a, const BIGNUM *b,
+                        const int p[], BN_CTX *ctx);
+/* r = (a ^ b) mod p */
+int BN_GF2m_mod_exp_arr(BIGNUM *r, const BIGNUM *a, const BIGNUM *b,
+                        const int p[], BN_CTX *ctx);
+/* r = sqrt(a) mod p */
+int BN_GF2m_mod_sqrt_arr(BIGNUM *r, const BIGNUM *a,
+                         const int p[], BN_CTX *ctx);
+/* r^2 + r = a mod p */
+int BN_GF2m_mod_solve_quad_arr(BIGNUM *r, const BIGNUM *a,
+                               const int p[], BN_CTX *ctx);
+int BN_GF2m_poly2arr(const BIGNUM *a, int p[], int max);
+int BN_GF2m_arr2poly(const int p[], BIGNUM *a);
+
+# endif
+
+/*
+ * faster mod functions for the 'NIST primes' 0 <= a < p^2
+ */
+int BN_nist_mod_192(BIGNUM *r, const BIGNUM *a, const BIGNUM *p, BN_CTX *ctx);
+int BN_nist_mod_224(BIGNUM *r, const BIGNUM *a, const BIGNUM *p, BN_CTX *ctx);
+int BN_nist_mod_256(BIGNUM *r, const BIGNUM *a, const BIGNUM *p, BN_CTX *ctx);
+int BN_nist_mod_384(BIGNUM *r, const BIGNUM *a, const BIGNUM *p, BN_CTX *ctx);
+int BN_nist_mod_521(BIGNUM *r, const BIGNUM *a, const BIGNUM *p, BN_CTX *ctx);
+
+const BIGNUM *BN_get0_nist_prime_192(void);
+const BIGNUM *BN_get0_nist_prime_224(void);
+const BIGNUM *BN_get0_nist_prime_256(void);
+const BIGNUM *BN_get0_nist_prime_384(void);
+const BIGNUM *BN_get0_nist_prime_521(void);
+
+/* library internal functions */
+
+# define bn_expand(a,bits) \
+    ( \
+        bits > (INT_MAX - BN_BITS2 + 1) ? \
+            NULL \
+        : \
+            (((bits+BN_BITS2-1)/BN_BITS2) <= (a)->dmax) ? \
+                (a) \
+            : \
+                bn_expand2((a),(bits+BN_BITS2-1)/BN_BITS2) \
+    )
+
+# define bn_wexpand(a,words) (((words) <= (a)->dmax)?(a):bn_expand2((a),(words)))
+BIGNUM *bn_expand2(BIGNUM *a, int words);
+# ifndef OPENSSL_NO_DEPRECATED
+BIGNUM *bn_dup_expand(const BIGNUM *a, int words); /* unused */
+# endif
+
+/*-
+ * Bignum consistency macros
+ * There is one "API" macro, bn_fix_top(), for stripping leading zeroes from
+ * bignum data after direct manipulations on the data. There is also an
+ * "internal" macro, bn_check_top(), for verifying that there are no leading
+ * zeroes. Unfortunately, some auditing is required due to the fact that
+ * bn_fix_top() has become an overabused duct-tape because bignum data is
+ * occasionally passed around in an inconsistent state. So the following
+ * changes have been made to sort this out;
+ * - bn_fix_top()s implementation has been moved to bn_correct_top()
+ * - if BN_DEBUG isn't defined, bn_fix_top() maps to bn_correct_top(), and
+ *   bn_check_top() is as before.
+ * - if BN_DEBUG *is* defined;
+ *   - bn_check_top() tries to pollute unused words even if the bignum 'top' is
+ *     consistent. (ed: only if BN_DEBUG_RAND is defined)
+ *   - bn_fix_top() maps to bn_check_top() rather than "fixing" anything.
+ * The idea is to have debug builds flag up inconsistent bignums when they
+ * occur. If that occurs in a bn_fix_top(), we examine the code in question; if
+ * the use of bn_fix_top() was appropriate (ie. it follows directly after code
+ * that manipulates the bignum) it is converted to bn_correct_top(), and if it
+ * was not appropriate, we convert it permanently to bn_check_top() and track
+ * down the cause of the bug. Eventually, no internal code should be using the
+ * bn_fix_top() macro. External applications and libraries should try this with
+ * their own code too, both in terms of building against the openssl headers
+ * with BN_DEBUG defined *and* linking with a version of OpenSSL built with it
+ * defined. This not only improves external code, it provides more test
+ * coverage for openssl's own code.
+ */
+
+# ifdef BN_DEBUG
+
+/* We only need assert() when debugging */
+#  include <assert.h>
+
+/*
+ * The new BN_FLG_FIXED_TOP flag marks vectors that were not treated with
+ * bn_correct_top, in other words such vectors are permitted to have zeros
+ * in most significant limbs. Such vectors are used internally to achieve
+ * execution time invariance for critical operations with private keys.
+ * It's BN_DEBUG-only flag, because user application is not supposed to
+ * observe it anyway. Moreover, optimizing compiler would actually remove
+ * all operations manipulating the bit in question in non-BN_DEBUG build.
+ */
+#  define BN_FLG_FIXED_TOP 0x10000
+#  ifdef BN_DEBUG_RAND
+/* To avoid "make update" cvs wars due to BN_DEBUG, use some tricks */
+#   ifndef RAND_pseudo_bytes
+int RAND_pseudo_bytes(unsigned char *buf, int num);
+#    define BN_DEBUG_TRIX
+#   endif
+#   define bn_pollute(a) \
+        do { \
+                const BIGNUM *_bnum1 = (a); \
+                if(_bnum1->top < _bnum1->dmax) { \
+                        unsigned char _tmp_char; \
+                        /* We cast away const without the compiler knowing, any \
+                         * *genuinely* constant variables that aren't mutable \
+                         * wouldn't be constructed with top!=dmax. */ \
+                        BN_ULONG *_not_const; \
+                        memcpy(&_not_const, &_bnum1->d, sizeof(BN_ULONG*)); \
+                        /* Debug only - safe to ignore error return */ \
+                        RAND_pseudo_bytes(&_tmp_char, 1); \
+                        memset((unsigned char *)(_not_const + _bnum1->top), _tmp_char, \
+                                (_bnum1->dmax - _bnum1->top) * sizeof(BN_ULONG)); \
+                } \
+        } while(0)
+#   ifdef BN_DEBUG_TRIX
+#    undef RAND_pseudo_bytes
+#   endif
+#  else
+#   define bn_pollute(a)
+#  endif
+#  define bn_check_top(a) \
+        do { \
+                const BIGNUM *_bnum2 = (a); \
+                if (_bnum2 != NULL) { \
+                        int _top = _bnum2->top; \
+                        assert((_top == 0) || \
+                               (_bnum2->flags & BN_FLG_FIXED_TOP) || \
+                               (_bnum2->d[_top - 1] != 0)); \
+                        bn_pollute(_bnum2); \
+                } \
+        } while(0)
+
+#  define bn_fix_top(a)           bn_check_top(a)
+
+#  define bn_check_size(bn, bits) bn_wcheck_size(bn, ((bits+BN_BITS2-1))/BN_BITS2)
+#  define bn_wcheck_size(bn, words) \
+        do { \
+                const BIGNUM *_bnum2 = (bn); \
+                assert((words) <= (_bnum2)->dmax && (words) >= (_bnum2)->top); \
+                /* avoid unused variable warning with NDEBUG */ \
+                (void)(_bnum2); \
+        } while(0)
+
+# else                          /* !BN_DEBUG */
+
+#  define BN_FLG_FIXED_TOP 0
+#  define bn_pollute(a)
+#  define bn_check_top(a)
+#  define bn_fix_top(a)           bn_correct_top(a)
+#  define bn_check_size(bn, bits)
+#  define bn_wcheck_size(bn, words)
+
+# endif
+
+# define bn_correct_top(a) \
+        { \
+        BN_ULONG *ftl; \
+        int tmp_top = (a)->top; \
+        if (tmp_top > 0) \
+                { \
+                for (ftl= &((a)->d[tmp_top-1]); tmp_top > 0; tmp_top--) \
+                        if (*(ftl--)) break; \
+                (a)->top = tmp_top; \
+                } \
+        if ((a)->top == 0) \
+            (a)->neg = 0; \
+        bn_pollute(a); \
+        }
+
+BN_ULONG bn_mul_add_words(BN_ULONG *rp, const BN_ULONG *ap, int num,
+                          BN_ULONG w);
+BN_ULONG bn_mul_words(BN_ULONG *rp, const BN_ULONG *ap, int num, BN_ULONG w);
+void bn_sqr_words(BN_ULONG *rp, const BN_ULONG *ap, int num);
+BN_ULONG bn_div_words(BN_ULONG h, BN_ULONG l, BN_ULONG d);
+BN_ULONG bn_add_words(BN_ULONG *rp, const BN_ULONG *ap, const BN_ULONG *bp,
+                      int num);
+BN_ULONG bn_sub_words(BN_ULONG *rp, const BN_ULONG *ap, const BN_ULONG *bp,
+                      int num);
+
+/* Primes from RFC 2409 */
+BIGNUM *get_rfc2409_prime_768(BIGNUM *bn);
+BIGNUM *get_rfc2409_prime_1024(BIGNUM *bn);
+
+/* Primes from RFC 3526 */
+BIGNUM *get_rfc3526_prime_1536(BIGNUM *bn);
+BIGNUM *get_rfc3526_prime_2048(BIGNUM *bn);
+BIGNUM *get_rfc3526_prime_3072(BIGNUM *bn);
+BIGNUM *get_rfc3526_prime_4096(BIGNUM *bn);
+BIGNUM *get_rfc3526_prime_6144(BIGNUM *bn);
+BIGNUM *get_rfc3526_prime_8192(BIGNUM *bn);
+
+int BN_bntest_rand(BIGNUM *rnd, int bits, int top, int bottom);
+
+/* BEGIN ERROR CODES */
+/*
+ * The following lines are auto generated by the script mkerr.pl. Any changes
+ * made after this point may be overwritten when the script is next run.
+ */
+void ERR_load_BN_strings(void);
+
+/* Error codes for the BN functions. */
+
+/* Function codes. */
+# define BN_F_BNRAND                                      127
+# define BN_F_BN_BLINDING_CONVERT_EX                      100
+# define BN_F_BN_BLINDING_CREATE_PARAM                    128
+# define BN_F_BN_BLINDING_INVERT_EX                       101
+# define BN_F_BN_BLINDING_NEW                             102
+# define BN_F_BN_BLINDING_UPDATE                          103
+# define BN_F_BN_BN2DEC                                   104
+# define BN_F_BN_BN2HEX                                   105
+# define BN_F_BN_CTX_GET                                  116
+# define BN_F_BN_CTX_NEW                                  106
+# define BN_F_BN_CTX_START                                129
+# define BN_F_BN_DIV                                      107
+# define BN_F_BN_DIV_NO_BRANCH                            138
+# define BN_F_BN_DIV_RECP                                 130
+# define BN_F_BN_EXP                                      123
+# define BN_F_BN_EXPAND2                                  108
+# define BN_F_BN_EXPAND_INTERNAL                          120
+# define BN_F_BN_GF2M_MOD                                 131
+# define BN_F_BN_GF2M_MOD_EXP                             132
+# define BN_F_BN_GF2M_MOD_MUL                             133
+# define BN_F_BN_GF2M_MOD_SOLVE_QUAD                      134
+# define BN_F_BN_GF2M_MOD_SOLVE_QUAD_ARR                  135
+# define BN_F_BN_GF2M_MOD_SQR                             136
+# define BN_F_BN_GF2M_MOD_SQRT                            137
+# define BN_F_BN_LSHIFT                                   145
+# define BN_F_BN_MOD_EXP2_MONT                            118
+# define BN_F_BN_MOD_EXP_MONT                             109
+# define BN_F_BN_MOD_EXP_MONT_CONSTTIME                   124
+# define BN_F_BN_MOD_EXP_MONT_WORD                        117
+# define BN_F_BN_MOD_EXP_RECP                             125
+# define BN_F_BN_MOD_EXP_SIMPLE                           126
+# define BN_F_BN_MOD_INVERSE                              110
+# define BN_F_BN_MOD_INVERSE_NO_BRANCH                    139
+# define BN_F_BN_MOD_LSHIFT_QUICK                         119
+# define BN_F_BN_MOD_MUL_RECIPROCAL                       111
+# define BN_F_BN_MOD_SQRT                                 121
+# define BN_F_BN_MPI2BN                                   112
+# define BN_F_BN_NEW                                      113
+# define BN_F_BN_RAND                                     114
+# define BN_F_BN_RAND_RANGE                               122
+# define BN_F_BN_RSHIFT                                   146
+# define BN_F_BN_USUB                                     115
+
+/* Reason codes. */
+# define BN_R_ARG2_LT_ARG3                                100
+# define BN_R_BAD_RECIPROCAL                              101
+# define BN_R_BIGNUM_TOO_LONG                             114
+# define BN_R_BITS_TOO_SMALL                              118
+# define BN_R_CALLED_WITH_EVEN_MODULUS                    102
+# define BN_R_DIV_BY_ZERO                                 103
+# define BN_R_ENCODING_ERROR                              104
+# define BN_R_EXPAND_ON_STATIC_BIGNUM_DATA                105
+# define BN_R_INPUT_NOT_REDUCED                           110
+# define BN_R_INVALID_LENGTH                              106
+# define BN_R_INVALID_RANGE                               115
+# define BN_R_INVALID_SHIFT                               119
+# define BN_R_NOT_A_SQUARE                                111
+# define BN_R_NOT_INITIALIZED                             107
+# define BN_R_NO_INVERSE                                  108
+# define BN_R_NO_SOLUTION                                 116
+# define BN_R_P_IS_NOT_PRIME                              112
+# define BN_R_TOO_MANY_ITERATIONS                         113
+# define BN_R_TOO_MANY_TEMPORARY_VARIABLES                109
+
+#ifdef  __cplusplus
+}
+#endif
+#endif

+ 125 - 0
libssh2/openssl/include/openssl/buffer.h

@@ -0,0 +1,125 @@
+/* crypto/buffer/buffer.h */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * 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 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. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    "This product includes cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``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 AUTHOR OR CONTRIBUTORS 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.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+#ifndef HEADER_BUFFER_H
+# define HEADER_BUFFER_H
+
+# include <openssl/ossl_typ.h>
+
+#ifdef  __cplusplus
+extern "C" {
+#endif
+
+# include <stddef.h>
+
+# if !defined(NO_SYS_TYPES_H)
+#  include <sys/types.h>
+# endif
+
+/* Already declared in ossl_typ.h */
+/* typedef struct buf_mem_st BUF_MEM; */
+
+struct buf_mem_st {
+    size_t length;              /* current number of bytes */
+    char *data;
+    size_t max;                 /* size of buffer */
+};
+
+BUF_MEM *BUF_MEM_new(void);
+void BUF_MEM_free(BUF_MEM *a);
+int BUF_MEM_grow(BUF_MEM *str, size_t len);
+int BUF_MEM_grow_clean(BUF_MEM *str, size_t len);
+size_t BUF_strnlen(const char *str, size_t maxlen);
+char *BUF_strdup(const char *str);
+
+/*
+ * Like strndup, but in addition, explicitly guarantees to never read past the
+ * first |siz| bytes of |str|.
+ */
+char *BUF_strndup(const char *str, size_t siz);
+
+void *BUF_memdup(const void *data, size_t siz);
+void BUF_reverse(unsigned char *out, const unsigned char *in, size_t siz);
+
+/* safe string functions */
+size_t BUF_strlcpy(char *dst, const char *src, size_t siz);
+size_t BUF_strlcat(char *dst, const char *src, size_t siz);
+
+/* BEGIN ERROR CODES */
+/*
+ * The following lines are auto generated by the script mkerr.pl. Any changes
+ * made after this point may be overwritten when the script is next run.
+ */
+void ERR_load_BUF_strings(void);
+
+/* Error codes for the BUF functions. */
+
+/* Function codes. */
+# define BUF_F_BUF_MEMDUP                                 103
+# define BUF_F_BUF_MEM_GROW                               100
+# define BUF_F_BUF_MEM_GROW_CLEAN                         105
+# define BUF_F_BUF_MEM_NEW                                101
+# define BUF_F_BUF_STRDUP                                 102
+# define BUF_F_BUF_STRNDUP                                104
+
+/* Reason codes. */
+
+#ifdef  __cplusplus
+}
+#endif
+#endif

+ 132 - 0
libssh2/openssl/include/openssl/camellia.h

@@ -0,0 +1,132 @@
+/* crypto/camellia/camellia.h */
+/* ====================================================================
+ * Copyright (c) 2006 The OpenSSL 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. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    openssl-core@openssl.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED 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 OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS 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 HEADER_CAMELLIA_H
+# define HEADER_CAMELLIA_H
+
+# include <openssl/opensslconf.h>
+
+# ifdef OPENSSL_NO_CAMELLIA
+#  error CAMELLIA is disabled.
+# endif
+
+# include <stddef.h>
+
+# define CAMELLIA_ENCRYPT        1
+# define CAMELLIA_DECRYPT        0
+
+/*
+ * Because array size can't be a const in C, the following two are macros.
+ * Both sizes are in bytes.
+ */
+
+#ifdef  __cplusplus
+extern "C" {
+#endif
+
+/* This should be a hidden type, but EVP requires that the size be known */
+
+# define CAMELLIA_BLOCK_SIZE 16
+# define CAMELLIA_TABLE_BYTE_LEN 272
+# define CAMELLIA_TABLE_WORD_LEN (CAMELLIA_TABLE_BYTE_LEN / 4)
+
+typedef unsigned int KEY_TABLE_TYPE[CAMELLIA_TABLE_WORD_LEN]; /* to match
+                                                               * with WORD */
+
+struct camellia_key_st {
+    union {
+        double d;               /* ensures 64-bit align */
+        KEY_TABLE_TYPE rd_key;
+    } u;
+    int grand_rounds;
+};
+typedef struct camellia_key_st CAMELLIA_KEY;
+
+# ifdef OPENSSL_FIPS
+int private_Camellia_set_key(const unsigned char *userKey, const int bits,
+                             CAMELLIA_KEY *key);
+# endif
+int Camellia_set_key(const unsigned char *userKey, const int bits,
+                     CAMELLIA_KEY *key);
+
+void Camellia_encrypt(const unsigned char *in, unsigned char *out,
+                      const CAMELLIA_KEY *key);
+void Camellia_decrypt(const unsigned char *in, unsigned char *out,
+                      const CAMELLIA_KEY *key);
+
+void Camellia_ecb_encrypt(const unsigned char *in, unsigned char *out,
+                          const CAMELLIA_KEY *key, const int enc);
+void Camellia_cbc_encrypt(const unsigned char *in, unsigned char *out,
+                          size_t length, const CAMELLIA_KEY *key,
+                          unsigned char *ivec, const int enc);
+void Camellia_cfb128_encrypt(const unsigned char *in, unsigned char *out,
+                             size_t length, const CAMELLIA_KEY *key,
+                             unsigned char *ivec, int *num, const int enc);
+void Camellia_cfb1_encrypt(const unsigned char *in, unsigned char *out,
+                           size_t length, const CAMELLIA_KEY *key,
+                           unsigned char *ivec, int *num, const int enc);
+void Camellia_cfb8_encrypt(const unsigned char *in, unsigned char *out,
+                           size_t length, const CAMELLIA_KEY *key,
+                           unsigned char *ivec, int *num, const int enc);
+void Camellia_ofb128_encrypt(const unsigned char *in, unsigned char *out,
+                             size_t length, const CAMELLIA_KEY *key,
+                             unsigned char *ivec, int *num);
+void Camellia_ctr128_encrypt(const unsigned char *in, unsigned char *out,
+                             size_t length, const CAMELLIA_KEY *key,
+                             unsigned char ivec[CAMELLIA_BLOCK_SIZE],
+                             unsigned char ecount_buf[CAMELLIA_BLOCK_SIZE],
+                             unsigned int *num);
+
+#ifdef  __cplusplus
+}
+#endif
+
+#endif                          /* !HEADER_Camellia_H */

+ 107 - 0
libssh2/openssl/include/openssl/cast.h

@@ -0,0 +1,107 @@
+/* crypto/cast/cast.h */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * 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 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. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    "This product includes cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``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 AUTHOR OR CONTRIBUTORS 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.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+#ifndef HEADER_CAST_H
+# define HEADER_CAST_H
+
+#ifdef  __cplusplus
+extern "C" {
+#endif
+
+# include <openssl/opensslconf.h>
+
+# ifdef OPENSSL_NO_CAST
+#  error CAST is disabled.
+# endif
+
+# define CAST_ENCRYPT    1
+# define CAST_DECRYPT    0
+
+# define CAST_LONG unsigned int
+
+# define CAST_BLOCK      8
+# define CAST_KEY_LENGTH 16
+
+typedef struct cast_key_st {
+    CAST_LONG data[32];
+    int short_key;              /* Use reduced rounds for short key */
+} CAST_KEY;
+
+# ifdef OPENSSL_FIPS
+void private_CAST_set_key(CAST_KEY *key, int len, const unsigned char *data);
+# endif
+void CAST_set_key(CAST_KEY *key, int len, const unsigned char *data);
+void CAST_ecb_encrypt(const unsigned char *in, unsigned char *out,
+                      const CAST_KEY *key, int enc);
+void CAST_encrypt(CAST_LONG *data, const CAST_KEY *key);
+void CAST_decrypt(CAST_LONG *data, const CAST_KEY *key);
+void CAST_cbc_encrypt(const unsigned char *in, unsigned char *out,
+                      long length, const CAST_KEY *ks, unsigned char *iv,
+                      int enc);
+void CAST_cfb64_encrypt(const unsigned char *in, unsigned char *out,
+                        long length, const CAST_KEY *schedule,
+                        unsigned char *ivec, int *num, int enc);
+void CAST_ofb64_encrypt(const unsigned char *in, unsigned char *out,
+                        long length, const CAST_KEY *schedule,
+                        unsigned char *ivec, int *num);
+
+#ifdef  __cplusplus
+}
+#endif
+
+#endif

+ 82 - 0
libssh2/openssl/include/openssl/cmac.h

@@ -0,0 +1,82 @@
+/* crypto/cmac/cmac.h */
+/*
+ * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
+ * project.
+ */
+/* ====================================================================
+ * Copyright (c) 2010 The OpenSSL 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. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    licensing@OpenSSL.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED 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 OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS 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 HEADER_CMAC_H
+# define HEADER_CMAC_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+# include <openssl/evp.h>
+
+/* Opaque */
+typedef struct CMAC_CTX_st CMAC_CTX;
+
+CMAC_CTX *CMAC_CTX_new(void);
+void CMAC_CTX_cleanup(CMAC_CTX *ctx);
+void CMAC_CTX_free(CMAC_CTX *ctx);
+EVP_CIPHER_CTX *CMAC_CTX_get0_cipher_ctx(CMAC_CTX *ctx);
+int CMAC_CTX_copy(CMAC_CTX *out, const CMAC_CTX *in);
+
+int CMAC_Init(CMAC_CTX *ctx, const void *key, size_t keylen,
+              const EVP_CIPHER *cipher, ENGINE *impl);
+int CMAC_Update(CMAC_CTX *ctx, const void *data, size_t dlen);
+int CMAC_Final(CMAC_CTX *ctx, unsigned char *out, size_t *poutlen);
+int CMAC_resume(CMAC_CTX *ctx);
+
+#ifdef  __cplusplus
+}
+#endif
+#endif

+ 555 - 0
libssh2/openssl/include/openssl/cms.h

@@ -0,0 +1,555 @@
+/* crypto/cms/cms.h */
+/*
+ * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
+ * project.
+ */
+/* ====================================================================
+ * Copyright (c) 2008 The OpenSSL 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. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    licensing@OpenSSL.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED 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 OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS 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 HEADER_CMS_H
+# define HEADER_CMS_H
+
+# include <openssl/x509.h>
+
+# ifdef OPENSSL_NO_CMS
+#  error CMS is disabled.
+# endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef struct CMS_ContentInfo_st CMS_ContentInfo;
+typedef struct CMS_SignerInfo_st CMS_SignerInfo;
+typedef struct CMS_CertificateChoices CMS_CertificateChoices;
+typedef struct CMS_RevocationInfoChoice_st CMS_RevocationInfoChoice;
+typedef struct CMS_RecipientInfo_st CMS_RecipientInfo;
+typedef struct CMS_ReceiptRequest_st CMS_ReceiptRequest;
+typedef struct CMS_Receipt_st CMS_Receipt;
+typedef struct CMS_RecipientEncryptedKey_st CMS_RecipientEncryptedKey;
+typedef struct CMS_OtherKeyAttribute_st CMS_OtherKeyAttribute;
+
+DECLARE_STACK_OF(CMS_SignerInfo)
+DECLARE_STACK_OF(GENERAL_NAMES)
+DECLARE_STACK_OF(CMS_RecipientEncryptedKey)
+DECLARE_ASN1_FUNCTIONS(CMS_ContentInfo)
+DECLARE_ASN1_FUNCTIONS(CMS_ReceiptRequest)
+DECLARE_ASN1_PRINT_FUNCTION(CMS_ContentInfo)
+
+# define CMS_SIGNERINFO_ISSUER_SERIAL    0
+# define CMS_SIGNERINFO_KEYIDENTIFIER    1
+
+# define CMS_RECIPINFO_NONE              -1
+# define CMS_RECIPINFO_TRANS             0
+# define CMS_RECIPINFO_AGREE             1
+# define CMS_RECIPINFO_KEK               2
+# define CMS_RECIPINFO_PASS              3
+# define CMS_RECIPINFO_OTHER             4
+
+/* S/MIME related flags */
+
+# define CMS_TEXT                        0x1
+# define CMS_NOCERTS                     0x2
+# define CMS_NO_CONTENT_VERIFY           0x4
+# define CMS_NO_ATTR_VERIFY              0x8
+# define CMS_NOSIGS                      \
+                        (CMS_NO_CONTENT_VERIFY|CMS_NO_ATTR_VERIFY)
+# define CMS_NOINTERN                    0x10
+# define CMS_NO_SIGNER_CERT_VERIFY       0x20
+# define CMS_NOVERIFY                    0x20
+# define CMS_DETACHED                    0x40
+# define CMS_BINARY                      0x80
+# define CMS_NOATTR                      0x100
+# define CMS_NOSMIMECAP                  0x200
+# define CMS_NOOLDMIMETYPE               0x400
+# define CMS_CRLFEOL                     0x800
+# define CMS_STREAM                      0x1000
+# define CMS_NOCRL                       0x2000
+# define CMS_PARTIAL                     0x4000
+# define CMS_REUSE_DIGEST                0x8000
+# define CMS_USE_KEYID                   0x10000
+# define CMS_DEBUG_DECRYPT               0x20000
+# define CMS_KEY_PARAM                   0x40000
+
+const ASN1_OBJECT *CMS_get0_type(CMS_ContentInfo *cms);
+
+BIO *CMS_dataInit(CMS_ContentInfo *cms, BIO *icont);
+int CMS_dataFinal(CMS_ContentInfo *cms, BIO *bio);
+
+ASN1_OCTET_STRING **CMS_get0_content(CMS_ContentInfo *cms);
+int CMS_is_detached(CMS_ContentInfo *cms);
+int CMS_set_detached(CMS_ContentInfo *cms, int detached);
+
+# ifdef HEADER_PEM_H
+DECLARE_PEM_rw_const(CMS, CMS_ContentInfo)
+# endif
+int CMS_stream(unsigned char ***boundary, CMS_ContentInfo *cms);
+CMS_ContentInfo *d2i_CMS_bio(BIO *bp, CMS_ContentInfo **cms);
+int i2d_CMS_bio(BIO *bp, CMS_ContentInfo *cms);
+
+BIO *BIO_new_CMS(BIO *out, CMS_ContentInfo *cms);
+int i2d_CMS_bio_stream(BIO *out, CMS_ContentInfo *cms, BIO *in, int flags);
+int PEM_write_bio_CMS_stream(BIO *out, CMS_ContentInfo *cms, BIO *in,
+                             int flags);
+CMS_ContentInfo *SMIME_read_CMS(BIO *bio, BIO **bcont);
+int SMIME_write_CMS(BIO *bio, CMS_ContentInfo *cms, BIO *data, int flags);
+
+int CMS_final(CMS_ContentInfo *cms, BIO *data, BIO *dcont,
+              unsigned int flags);
+
+CMS_ContentInfo *CMS_sign(X509 *signcert, EVP_PKEY *pkey,
+                          STACK_OF(X509) *certs, BIO *data,
+                          unsigned int flags);
+
+CMS_ContentInfo *CMS_sign_receipt(CMS_SignerInfo *si,
+                                  X509 *signcert, EVP_PKEY *pkey,
+                                  STACK_OF(X509) *certs, unsigned int flags);
+
+int CMS_data(CMS_ContentInfo *cms, BIO *out, unsigned int flags);
+CMS_ContentInfo *CMS_data_create(BIO *in, unsigned int flags);
+
+int CMS_digest_verify(CMS_ContentInfo *cms, BIO *dcont, BIO *out,
+                      unsigned int flags);
+CMS_ContentInfo *CMS_digest_create(BIO *in, const EVP_MD *md,
+                                   unsigned int flags);
+
+int CMS_EncryptedData_decrypt(CMS_ContentInfo *cms,
+                              const unsigned char *key, size_t keylen,
+                              BIO *dcont, BIO *out, unsigned int flags);
+
+CMS_ContentInfo *CMS_EncryptedData_encrypt(BIO *in, const EVP_CIPHER *cipher,
+                                           const unsigned char *key,
+                                           size_t keylen, unsigned int flags);
+
+int CMS_EncryptedData_set1_key(CMS_ContentInfo *cms, const EVP_CIPHER *ciph,
+                               const unsigned char *key, size_t keylen);
+
+int CMS_verify(CMS_ContentInfo *cms, STACK_OF(X509) *certs,
+               X509_STORE *store, BIO *dcont, BIO *out, unsigned int flags);
+
+int CMS_verify_receipt(CMS_ContentInfo *rcms, CMS_ContentInfo *ocms,
+                       STACK_OF(X509) *certs,
+                       X509_STORE *store, unsigned int flags);
+
+STACK_OF(X509) *CMS_get0_signers(CMS_ContentInfo *cms);
+
+CMS_ContentInfo *CMS_encrypt(STACK_OF(X509) *certs, BIO *in,
+                             const EVP_CIPHER *cipher, unsigned int flags);
+
+int CMS_decrypt(CMS_ContentInfo *cms, EVP_PKEY *pkey, X509 *cert,
+                BIO *dcont, BIO *out, unsigned int flags);
+
+int CMS_decrypt_set1_pkey(CMS_ContentInfo *cms, EVP_PKEY *pk, X509 *cert);
+int CMS_decrypt_set1_key(CMS_ContentInfo *cms,
+                         unsigned char *key, size_t keylen,
+                         unsigned char *id, size_t idlen);
+int CMS_decrypt_set1_password(CMS_ContentInfo *cms,
+                              unsigned char *pass, ossl_ssize_t passlen);
+
+STACK_OF(CMS_RecipientInfo) *CMS_get0_RecipientInfos(CMS_ContentInfo *cms);
+int CMS_RecipientInfo_type(CMS_RecipientInfo *ri);
+EVP_PKEY_CTX *CMS_RecipientInfo_get0_pkey_ctx(CMS_RecipientInfo *ri);
+CMS_ContentInfo *CMS_EnvelopedData_create(const EVP_CIPHER *cipher);
+CMS_RecipientInfo *CMS_add1_recipient_cert(CMS_ContentInfo *cms,
+                                           X509 *recip, unsigned int flags);
+int CMS_RecipientInfo_set0_pkey(CMS_RecipientInfo *ri, EVP_PKEY *pkey);
+int CMS_RecipientInfo_ktri_cert_cmp(CMS_RecipientInfo *ri, X509 *cert);
+int CMS_RecipientInfo_ktri_get0_algs(CMS_RecipientInfo *ri,
+                                     EVP_PKEY **pk, X509 **recip,
+                                     X509_ALGOR **palg);
+int CMS_RecipientInfo_ktri_get0_signer_id(CMS_RecipientInfo *ri,
+                                          ASN1_OCTET_STRING **keyid,
+                                          X509_NAME **issuer,
+                                          ASN1_INTEGER **sno);
+
+CMS_RecipientInfo *CMS_add0_recipient_key(CMS_ContentInfo *cms, int nid,
+                                          unsigned char *key, size_t keylen,
+                                          unsigned char *id, size_t idlen,
+                                          ASN1_GENERALIZEDTIME *date,
+                                          ASN1_OBJECT *otherTypeId,
+                                          ASN1_TYPE *otherType);
+
+int CMS_RecipientInfo_kekri_get0_id(CMS_RecipientInfo *ri,
+                                    X509_ALGOR **palg,
+                                    ASN1_OCTET_STRING **pid,
+                                    ASN1_GENERALIZEDTIME **pdate,
+                                    ASN1_OBJECT **potherid,
+                                    ASN1_TYPE **pothertype);
+
+int CMS_RecipientInfo_set0_key(CMS_RecipientInfo *ri,
+                               unsigned char *key, size_t keylen);
+
+int CMS_RecipientInfo_kekri_id_cmp(CMS_RecipientInfo *ri,
+                                   const unsigned char *id, size_t idlen);
+
+int CMS_RecipientInfo_set0_password(CMS_RecipientInfo *ri,
+                                    unsigned char *pass,
+                                    ossl_ssize_t passlen);
+
+CMS_RecipientInfo *CMS_add0_recipient_password(CMS_ContentInfo *cms,
+                                               int iter, int wrap_nid,
+                                               int pbe_nid,
+                                               unsigned char *pass,
+                                               ossl_ssize_t passlen,
+                                               const EVP_CIPHER *kekciph);
+
+int CMS_RecipientInfo_decrypt(CMS_ContentInfo *cms, CMS_RecipientInfo *ri);
+int CMS_RecipientInfo_encrypt(CMS_ContentInfo *cms, CMS_RecipientInfo *ri);
+
+int CMS_uncompress(CMS_ContentInfo *cms, BIO *dcont, BIO *out,
+                   unsigned int flags);
+CMS_ContentInfo *CMS_compress(BIO *in, int comp_nid, unsigned int flags);
+
+int CMS_set1_eContentType(CMS_ContentInfo *cms, const ASN1_OBJECT *oid);
+const ASN1_OBJECT *CMS_get0_eContentType(CMS_ContentInfo *cms);
+
+CMS_CertificateChoices *CMS_add0_CertificateChoices(CMS_ContentInfo *cms);
+int CMS_add0_cert(CMS_ContentInfo *cms, X509 *cert);
+int CMS_add1_cert(CMS_ContentInfo *cms, X509 *cert);
+STACK_OF(X509) *CMS_get1_certs(CMS_ContentInfo *cms);
+
+CMS_RevocationInfoChoice *CMS_add0_RevocationInfoChoice(CMS_ContentInfo *cms);
+int CMS_add0_crl(CMS_ContentInfo *cms, X509_CRL *crl);
+int CMS_add1_crl(CMS_ContentInfo *cms, X509_CRL *crl);
+STACK_OF(X509_CRL) *CMS_get1_crls(CMS_ContentInfo *cms);
+
+int CMS_SignedData_init(CMS_ContentInfo *cms);
+CMS_SignerInfo *CMS_add1_signer(CMS_ContentInfo *cms,
+                                X509 *signer, EVP_PKEY *pk, const EVP_MD *md,
+                                unsigned int flags);
+EVP_PKEY_CTX *CMS_SignerInfo_get0_pkey_ctx(CMS_SignerInfo *si);
+EVP_MD_CTX *CMS_SignerInfo_get0_md_ctx(CMS_SignerInfo *si);
+STACK_OF(CMS_SignerInfo) *CMS_get0_SignerInfos(CMS_ContentInfo *cms);
+
+void CMS_SignerInfo_set1_signer_cert(CMS_SignerInfo *si, X509 *signer);
+int CMS_SignerInfo_get0_signer_id(CMS_SignerInfo *si,
+                                  ASN1_OCTET_STRING **keyid,
+                                  X509_NAME **issuer, ASN1_INTEGER **sno);
+int CMS_SignerInfo_cert_cmp(CMS_SignerInfo *si, X509 *cert);
+int CMS_set1_signers_certs(CMS_ContentInfo *cms, STACK_OF(X509) *certs,
+                           unsigned int flags);
+void CMS_SignerInfo_get0_algs(CMS_SignerInfo *si, EVP_PKEY **pk,
+                              X509 **signer, X509_ALGOR **pdig,
+                              X509_ALGOR **psig);
+ASN1_OCTET_STRING *CMS_SignerInfo_get0_signature(CMS_SignerInfo *si);
+int CMS_SignerInfo_sign(CMS_SignerInfo *si);
+int CMS_SignerInfo_verify(CMS_SignerInfo *si);
+int CMS_SignerInfo_verify_content(CMS_SignerInfo *si, BIO *chain);
+
+int CMS_add_smimecap(CMS_SignerInfo *si, STACK_OF(X509_ALGOR) *algs);
+int CMS_add_simple_smimecap(STACK_OF(X509_ALGOR) **algs,
+                            int algnid, int keysize);
+int CMS_add_standard_smimecap(STACK_OF(X509_ALGOR) **smcap);
+
+int CMS_signed_get_attr_count(const CMS_SignerInfo *si);
+int CMS_signed_get_attr_by_NID(const CMS_SignerInfo *si, int nid,
+                               int lastpos);
+int CMS_signed_get_attr_by_OBJ(const CMS_SignerInfo *si, ASN1_OBJECT *obj,
+                               int lastpos);
+X509_ATTRIBUTE *CMS_signed_get_attr(const CMS_SignerInfo *si, int loc);
+X509_ATTRIBUTE *CMS_signed_delete_attr(CMS_SignerInfo *si, int loc);
+int CMS_signed_add1_attr(CMS_SignerInfo *si, X509_ATTRIBUTE *attr);
+int CMS_signed_add1_attr_by_OBJ(CMS_SignerInfo *si,
+                                const ASN1_OBJECT *obj, int type,
+                                const void *bytes, int len);
+int CMS_signed_add1_attr_by_NID(CMS_SignerInfo *si,
+                                int nid, int type,
+                                const void *bytes, int len);
+int CMS_signed_add1_attr_by_txt(CMS_SignerInfo *si,
+                                const char *attrname, int type,
+                                const void *bytes, int len);
+void *CMS_signed_get0_data_by_OBJ(CMS_SignerInfo *si, ASN1_OBJECT *oid,
+                                  int lastpos, int type);
+
+int CMS_unsigned_get_attr_count(const CMS_SignerInfo *si);
+int CMS_unsigned_get_attr_by_NID(const CMS_SignerInfo *si, int nid,
+                                 int lastpos);
+int CMS_unsigned_get_attr_by_OBJ(const CMS_SignerInfo *si, ASN1_OBJECT *obj,
+                                 int lastpos);
+X509_ATTRIBUTE *CMS_unsigned_get_attr(const CMS_SignerInfo *si, int loc);
+X509_ATTRIBUTE *CMS_unsigned_delete_attr(CMS_SignerInfo *si, int loc);
+int CMS_unsigned_add1_attr(CMS_SignerInfo *si, X509_ATTRIBUTE *attr);
+int CMS_unsigned_add1_attr_by_OBJ(CMS_SignerInfo *si,
+                                  const ASN1_OBJECT *obj, int type,
+                                  const void *bytes, int len);
+int CMS_unsigned_add1_attr_by_NID(CMS_SignerInfo *si,
+                                  int nid, int type,
+                                  const void *bytes, int len);
+int CMS_unsigned_add1_attr_by_txt(CMS_SignerInfo *si,
+                                  const char *attrname, int type,
+                                  const void *bytes, int len);
+void *CMS_unsigned_get0_data_by_OBJ(CMS_SignerInfo *si, ASN1_OBJECT *oid,
+                                    int lastpos, int type);
+
+# ifdef HEADER_X509V3_H
+
+int CMS_get1_ReceiptRequest(CMS_SignerInfo *si, CMS_ReceiptRequest **prr);
+CMS_ReceiptRequest *CMS_ReceiptRequest_create0(unsigned char *id, int idlen,
+                                               int allorfirst,
+                                               STACK_OF(GENERAL_NAMES)
+                                               *receiptList, STACK_OF(GENERAL_NAMES)
+                                               *receiptsTo);
+int CMS_add1_ReceiptRequest(CMS_SignerInfo *si, CMS_ReceiptRequest *rr);
+void CMS_ReceiptRequest_get0_values(CMS_ReceiptRequest *rr,
+                                    ASN1_STRING **pcid,
+                                    int *pallorfirst,
+                                    STACK_OF(GENERAL_NAMES) **plist,
+                                    STACK_OF(GENERAL_NAMES) **prto);
+# endif
+int CMS_RecipientInfo_kari_get0_alg(CMS_RecipientInfo *ri,
+                                    X509_ALGOR **palg,
+                                    ASN1_OCTET_STRING **pukm);
+STACK_OF(CMS_RecipientEncryptedKey)
+*CMS_RecipientInfo_kari_get0_reks(CMS_RecipientInfo *ri);
+
+int CMS_RecipientInfo_kari_get0_orig_id(CMS_RecipientInfo *ri,
+                                        X509_ALGOR **pubalg,
+                                        ASN1_BIT_STRING **pubkey,
+                                        ASN1_OCTET_STRING **keyid,
+                                        X509_NAME **issuer,
+                                        ASN1_INTEGER **sno);
+
+int CMS_RecipientInfo_kari_orig_id_cmp(CMS_RecipientInfo *ri, X509 *cert);
+
+int CMS_RecipientEncryptedKey_get0_id(CMS_RecipientEncryptedKey *rek,
+                                      ASN1_OCTET_STRING **keyid,
+                                      ASN1_GENERALIZEDTIME **tm,
+                                      CMS_OtherKeyAttribute **other,
+                                      X509_NAME **issuer, ASN1_INTEGER **sno);
+int CMS_RecipientEncryptedKey_cert_cmp(CMS_RecipientEncryptedKey *rek,
+                                       X509 *cert);
+int CMS_RecipientInfo_kari_set0_pkey(CMS_RecipientInfo *ri, EVP_PKEY *pk);
+EVP_CIPHER_CTX *CMS_RecipientInfo_kari_get0_ctx(CMS_RecipientInfo *ri);
+int CMS_RecipientInfo_kari_decrypt(CMS_ContentInfo *cms,
+                                   CMS_RecipientInfo *ri,
+                                   CMS_RecipientEncryptedKey *rek);
+
+int CMS_SharedInfo_encode(unsigned char **pder, X509_ALGOR *kekalg,
+                          ASN1_OCTET_STRING *ukm, int keylen);
+
+/* BEGIN ERROR CODES */
+/*
+ * The following lines are auto generated by the script mkerr.pl. Any changes
+ * made after this point may be overwritten when the script is next run.
+ */
+void ERR_load_CMS_strings(void);
+
+/* Error codes for the CMS functions. */
+
+/* Function codes. */
+# define CMS_F_CHECK_CONTENT                              99
+# define CMS_F_CMS_ADD0_CERT                              164
+# define CMS_F_CMS_ADD0_RECIPIENT_KEY                     100
+# define CMS_F_CMS_ADD0_RECIPIENT_PASSWORD                165
+# define CMS_F_CMS_ADD1_RECEIPTREQUEST                    158
+# define CMS_F_CMS_ADD1_RECIPIENT_CERT                    101
+# define CMS_F_CMS_ADD1_SIGNER                            102
+# define CMS_F_CMS_ADD1_SIGNINGTIME                       103
+# define CMS_F_CMS_COMPRESS                               104
+# define CMS_F_CMS_COMPRESSEDDATA_CREATE                  105
+# define CMS_F_CMS_COMPRESSEDDATA_INIT_BIO                106
+# define CMS_F_CMS_COPY_CONTENT                           107
+# define CMS_F_CMS_COPY_MESSAGEDIGEST                     108
+# define CMS_F_CMS_DATA                                   109
+# define CMS_F_CMS_DATAFINAL                              110
+# define CMS_F_CMS_DATAINIT                               111
+# define CMS_F_CMS_DECRYPT                                112
+# define CMS_F_CMS_DECRYPT_SET1_KEY                       113
+# define CMS_F_CMS_DECRYPT_SET1_PASSWORD                  166
+# define CMS_F_CMS_DECRYPT_SET1_PKEY                      114
+# define CMS_F_CMS_DIGESTALGORITHM_FIND_CTX               115
+# define CMS_F_CMS_DIGESTALGORITHM_INIT_BIO               116
+# define CMS_F_CMS_DIGESTEDDATA_DO_FINAL                  117
+# define CMS_F_CMS_DIGEST_VERIFY                          118
+# define CMS_F_CMS_ENCODE_RECEIPT                         161
+# define CMS_F_CMS_ENCRYPT                                119
+# define CMS_F_CMS_ENCRYPTEDCONTENT_INIT_BIO              120
+# define CMS_F_CMS_ENCRYPTEDDATA_DECRYPT                  121
+# define CMS_F_CMS_ENCRYPTEDDATA_ENCRYPT                  122
+# define CMS_F_CMS_ENCRYPTEDDATA_SET1_KEY                 123
+# define CMS_F_CMS_ENVELOPEDDATA_CREATE                   124
+# define CMS_F_CMS_ENVELOPEDDATA_INIT_BIO                 125
+# define CMS_F_CMS_ENVELOPED_DATA_INIT                    126
+# define CMS_F_CMS_ENV_ASN1_CTRL                          171
+# define CMS_F_CMS_FINAL                                  127
+# define CMS_F_CMS_GET0_CERTIFICATE_CHOICES               128
+# define CMS_F_CMS_GET0_CONTENT                           129
+# define CMS_F_CMS_GET0_ECONTENT_TYPE                     130
+# define CMS_F_CMS_GET0_ENVELOPED                         131
+# define CMS_F_CMS_GET0_REVOCATION_CHOICES                132
+# define CMS_F_CMS_GET0_SIGNED                            133
+# define CMS_F_CMS_MSGSIGDIGEST_ADD1                      162
+# define CMS_F_CMS_RECEIPTREQUEST_CREATE0                 159
+# define CMS_F_CMS_RECEIPT_VERIFY                         160
+# define CMS_F_CMS_RECIPIENTINFO_DECRYPT                  134
+# define CMS_F_CMS_RECIPIENTINFO_ENCRYPT                  169
+# define CMS_F_CMS_RECIPIENTINFO_KARI_ENCRYPT             178
+# define CMS_F_CMS_RECIPIENTINFO_KARI_GET0_ALG            175
+# define CMS_F_CMS_RECIPIENTINFO_KARI_GET0_ORIG_ID        173
+# define CMS_F_CMS_RECIPIENTINFO_KARI_GET0_REKS           172
+# define CMS_F_CMS_RECIPIENTINFO_KARI_ORIG_ID_CMP         174
+# define CMS_F_CMS_RECIPIENTINFO_KEKRI_DECRYPT            135
+# define CMS_F_CMS_RECIPIENTINFO_KEKRI_ENCRYPT            136
+# define CMS_F_CMS_RECIPIENTINFO_KEKRI_GET0_ID            137
+# define CMS_F_CMS_RECIPIENTINFO_KEKRI_ID_CMP             138
+# define CMS_F_CMS_RECIPIENTINFO_KTRI_CERT_CMP            139
+# define CMS_F_CMS_RECIPIENTINFO_KTRI_DECRYPT             140
+# define CMS_F_CMS_RECIPIENTINFO_KTRI_ENCRYPT             141
+# define CMS_F_CMS_RECIPIENTINFO_KTRI_GET0_ALGS           142
+# define CMS_F_CMS_RECIPIENTINFO_KTRI_GET0_SIGNER_ID      143
+# define CMS_F_CMS_RECIPIENTINFO_PWRI_CRYPT               167
+# define CMS_F_CMS_RECIPIENTINFO_SET0_KEY                 144
+# define CMS_F_CMS_RECIPIENTINFO_SET0_PASSWORD            168
+# define CMS_F_CMS_RECIPIENTINFO_SET0_PKEY                145
+# define CMS_F_CMS_SD_ASN1_CTRL                           170
+# define CMS_F_CMS_SET1_IAS                               176
+# define CMS_F_CMS_SET1_KEYID                             177
+# define CMS_F_CMS_SET1_SIGNERIDENTIFIER                  146
+# define CMS_F_CMS_SET_DETACHED                           147
+# define CMS_F_CMS_SIGN                                   148
+# define CMS_F_CMS_SIGNED_DATA_INIT                       149
+# define CMS_F_CMS_SIGNERINFO_CONTENT_SIGN                150
+# define CMS_F_CMS_SIGNERINFO_SIGN                        151
+# define CMS_F_CMS_SIGNERINFO_VERIFY                      152
+# define CMS_F_CMS_SIGNERINFO_VERIFY_CERT                 153
+# define CMS_F_CMS_SIGNERINFO_VERIFY_CONTENT              154
+# define CMS_F_CMS_SIGN_RECEIPT                           163
+# define CMS_F_CMS_STREAM                                 155
+# define CMS_F_CMS_UNCOMPRESS                             156
+# define CMS_F_CMS_VERIFY                                 157
+
+/* Reason codes. */
+# define CMS_R_ADD_SIGNER_ERROR                           99
+# define CMS_R_CERTIFICATE_ALREADY_PRESENT                175
+# define CMS_R_CERTIFICATE_HAS_NO_KEYID                   160
+# define CMS_R_CERTIFICATE_VERIFY_ERROR                   100
+# define CMS_R_CIPHER_INITIALISATION_ERROR                101
+# define CMS_R_CIPHER_PARAMETER_INITIALISATION_ERROR      102
+# define CMS_R_CMS_DATAFINAL_ERROR                        103
+# define CMS_R_CMS_LIB                                    104
+# define CMS_R_CONTENTIDENTIFIER_MISMATCH                 170
+# define CMS_R_CONTENT_NOT_FOUND                          105
+# define CMS_R_CONTENT_TYPE_MISMATCH                      171
+# define CMS_R_CONTENT_TYPE_NOT_COMPRESSED_DATA           106
+# define CMS_R_CONTENT_TYPE_NOT_ENVELOPED_DATA            107
+# define CMS_R_CONTENT_TYPE_NOT_SIGNED_DATA               108
+# define CMS_R_CONTENT_VERIFY_ERROR                       109
+# define CMS_R_CTRL_ERROR                                 110
+# define CMS_R_CTRL_FAILURE                               111
+# define CMS_R_DECRYPT_ERROR                              112
+# define CMS_R_DIGEST_ERROR                               161
+# define CMS_R_ERROR_GETTING_PUBLIC_KEY                   113
+# define CMS_R_ERROR_READING_MESSAGEDIGEST_ATTRIBUTE      114
+# define CMS_R_ERROR_SETTING_KEY                          115
+# define CMS_R_ERROR_SETTING_RECIPIENTINFO                116
+# define CMS_R_INVALID_ENCRYPTED_KEY_LENGTH               117
+# define CMS_R_INVALID_KEY_ENCRYPTION_PARAMETER           176
+# define CMS_R_INVALID_KEY_LENGTH                         118
+# define CMS_R_MD_BIO_INIT_ERROR                          119
+# define CMS_R_MESSAGEDIGEST_ATTRIBUTE_WRONG_LENGTH       120
+# define CMS_R_MESSAGEDIGEST_WRONG_LENGTH                 121
+# define CMS_R_MSGSIGDIGEST_ERROR                         172
+# define CMS_R_MSGSIGDIGEST_VERIFICATION_FAILURE          162
+# define CMS_R_MSGSIGDIGEST_WRONG_LENGTH                  163
+# define CMS_R_NEED_ONE_SIGNER                            164
+# define CMS_R_NOT_A_SIGNED_RECEIPT                       165
+# define CMS_R_NOT_ENCRYPTED_DATA                         122
+# define CMS_R_NOT_KEK                                    123
+# define CMS_R_NOT_KEY_AGREEMENT                          181
+# define CMS_R_NOT_KEY_TRANSPORT                          124
+# define CMS_R_NOT_PWRI                                   177
+# define CMS_R_NOT_SUPPORTED_FOR_THIS_KEY_TYPE            125
+# define CMS_R_NO_CIPHER                                  126
+# define CMS_R_NO_CONTENT                                 127
+# define CMS_R_NO_CONTENT_TYPE                            173
+# define CMS_R_NO_DEFAULT_DIGEST                          128
+# define CMS_R_NO_DIGEST_SET                              129
+# define CMS_R_NO_KEY                                     130
+# define CMS_R_NO_KEY_OR_CERT                             174
+# define CMS_R_NO_MATCHING_DIGEST                         131
+# define CMS_R_NO_MATCHING_RECIPIENT                      132
+# define CMS_R_NO_MATCHING_SIGNATURE                      166
+# define CMS_R_NO_MSGSIGDIGEST                            167
+# define CMS_R_NO_PASSWORD                                178
+# define CMS_R_NO_PRIVATE_KEY                             133
+# define CMS_R_NO_PUBLIC_KEY                              134
+# define CMS_R_NO_RECEIPT_REQUEST                         168
+# define CMS_R_NO_SIGNERS                                 135
+# define CMS_R_PRIVATE_KEY_DOES_NOT_MATCH_CERTIFICATE     136
+# define CMS_R_RECEIPT_DECODE_ERROR                       169
+# define CMS_R_RECIPIENT_ERROR                            137
+# define CMS_R_SIGNER_CERTIFICATE_NOT_FOUND               138
+# define CMS_R_SIGNFINAL_ERROR                            139
+# define CMS_R_SMIME_TEXT_ERROR                           140
+# define CMS_R_STORE_INIT_ERROR                           141
+# define CMS_R_TYPE_NOT_COMPRESSED_DATA                   142
+# define CMS_R_TYPE_NOT_DATA                              143
+# define CMS_R_TYPE_NOT_DIGESTED_DATA                     144
+# define CMS_R_TYPE_NOT_ENCRYPTED_DATA                    145
+# define CMS_R_TYPE_NOT_ENVELOPED_DATA                    146
+# define CMS_R_UNABLE_TO_FINALIZE_CONTEXT                 147
+# define CMS_R_UNKNOWN_CIPHER                             148
+# define CMS_R_UNKNOWN_DIGEST_ALGORIHM                    149
+# define CMS_R_UNKNOWN_ID                                 150
+# define CMS_R_UNSUPPORTED_COMPRESSION_ALGORITHM          151
+# define CMS_R_UNSUPPORTED_CONTENT_TYPE                   152
+# define CMS_R_UNSUPPORTED_KEK_ALGORITHM                  153
+# define CMS_R_UNSUPPORTED_KEY_ENCRYPTION_ALGORITHM       179
+# define CMS_R_UNSUPPORTED_RECIPIENT_TYPE                 154
+# define CMS_R_UNSUPPORTED_RECPIENTINFO_TYPE              155
+# define CMS_R_UNSUPPORTED_TYPE                           156
+# define CMS_R_UNWRAP_ERROR                               157
+# define CMS_R_UNWRAP_FAILURE                             180
+# define CMS_R_VERIFICATION_FAILURE                       158
+# define CMS_R_WRAP_ERROR                                 159
+
+#ifdef  __cplusplus
+}
+#endif
+#endif

+ 83 - 0
libssh2/openssl/include/openssl/comp.h

@@ -0,0 +1,83 @@
+
+#ifndef HEADER_COMP_H
+# define HEADER_COMP_H
+
+# include <openssl/crypto.h>
+
+# ifdef OPENSSL_NO_COMP
+#  error COMP is disabled.
+# endif
+
+#ifdef  __cplusplus
+extern "C" {
+#endif
+
+typedef struct comp_ctx_st COMP_CTX;
+
+struct comp_method_st {
+    int type;                   /* NID for compression library */
+    const char *name;           /* A text string to identify the library */
+    int (*init) (COMP_CTX *ctx);
+    void (*finish) (COMP_CTX *ctx);
+    int (*compress) (COMP_CTX *ctx,
+                     unsigned char *out, unsigned int olen,
+                     unsigned char *in, unsigned int ilen);
+    int (*expand) (COMP_CTX *ctx,
+                   unsigned char *out, unsigned int olen,
+                   unsigned char *in, unsigned int ilen);
+    /*
+     * The following two do NOTHING, but are kept for backward compatibility
+     */
+    long (*ctrl) (void);
+    long (*callback_ctrl) (void);
+};
+
+struct comp_ctx_st {
+    COMP_METHOD *meth;
+    unsigned long compress_in;
+    unsigned long compress_out;
+    unsigned long expand_in;
+    unsigned long expand_out;
+    CRYPTO_EX_DATA ex_data;
+};
+
+COMP_CTX *COMP_CTX_new(COMP_METHOD *meth);
+void COMP_CTX_free(COMP_CTX *ctx);
+int COMP_compress_block(COMP_CTX *ctx, unsigned char *out, int olen,
+                        unsigned char *in, int ilen);
+int COMP_expand_block(COMP_CTX *ctx, unsigned char *out, int olen,
+                      unsigned char *in, int ilen);
+COMP_METHOD *COMP_rle(void);
+COMP_METHOD *COMP_zlib(void);
+void COMP_zlib_cleanup(void);
+
+# ifdef HEADER_BIO_H
+#  ifdef ZLIB
+BIO_METHOD *BIO_f_zlib(void);
+#  endif
+# endif
+
+/* BEGIN ERROR CODES */
+/*
+ * The following lines are auto generated by the script mkerr.pl. Any changes
+ * made after this point may be overwritten when the script is next run.
+ */
+void ERR_load_COMP_strings(void);
+
+/* Error codes for the COMP functions. */
+
+/* Function codes. */
+# define COMP_F_BIO_ZLIB_FLUSH                            99
+# define COMP_F_BIO_ZLIB_NEW                              100
+# define COMP_F_BIO_ZLIB_READ                             101
+# define COMP_F_BIO_ZLIB_WRITE                            102
+
+/* Reason codes. */
+# define COMP_R_ZLIB_DEFLATE_ERROR                        99
+# define COMP_R_ZLIB_INFLATE_ERROR                        100
+# define COMP_R_ZLIB_NOT_SUPPORTED                        101
+
+#ifdef  __cplusplus
+}
+#endif
+#endif

+ 268 - 0
libssh2/openssl/include/openssl/conf.h

@@ -0,0 +1,268 @@
+/* crypto/conf/conf.h */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * 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 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. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    "This product includes cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``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 AUTHOR OR CONTRIBUTORS 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.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+#ifndef  HEADER_CONF_H
+# define HEADER_CONF_H
+
+# include <openssl/bio.h>
+# include <openssl/lhash.h>
+# include <openssl/stack.h>
+# include <openssl/safestack.h>
+# include <openssl/e_os2.h>
+
+# include <openssl/ossl_typ.h>
+
+#ifdef  __cplusplus
+extern "C" {
+#endif
+
+typedef struct {
+    char *section;
+    char *name;
+    char *value;
+} CONF_VALUE;
+
+DECLARE_STACK_OF(CONF_VALUE)
+DECLARE_LHASH_OF(CONF_VALUE);
+
+struct conf_st;
+struct conf_method_st;
+typedef struct conf_method_st CONF_METHOD;
+
+struct conf_method_st {
+    const char *name;
+    CONF *(*create) (CONF_METHOD *meth);
+    int (*init) (CONF *conf);
+    int (*destroy) (CONF *conf);
+    int (*destroy_data) (CONF *conf);
+    int (*load_bio) (CONF *conf, BIO *bp, long *eline);
+    int (*dump) (const CONF *conf, BIO *bp);
+    int (*is_number) (const CONF *conf, char c);
+    int (*to_int) (const CONF *conf, char c);
+    int (*load) (CONF *conf, const char *name, long *eline);
+};
+
+/* Module definitions */
+
+typedef struct conf_imodule_st CONF_IMODULE;
+typedef struct conf_module_st CONF_MODULE;
+
+DECLARE_STACK_OF(CONF_MODULE)
+DECLARE_STACK_OF(CONF_IMODULE)
+
+/* DSO module function typedefs */
+typedef int conf_init_func (CONF_IMODULE *md, const CONF *cnf);
+typedef void conf_finish_func (CONF_IMODULE *md);
+
+# define CONF_MFLAGS_IGNORE_ERRORS       0x1
+# define CONF_MFLAGS_IGNORE_RETURN_CODES 0x2
+# define CONF_MFLAGS_SILENT              0x4
+# define CONF_MFLAGS_NO_DSO              0x8
+# define CONF_MFLAGS_IGNORE_MISSING_FILE 0x10
+# define CONF_MFLAGS_DEFAULT_SECTION     0x20
+
+int CONF_set_default_method(CONF_METHOD *meth);
+void CONF_set_nconf(CONF *conf, LHASH_OF(CONF_VALUE) *hash);
+LHASH_OF(CONF_VALUE) *CONF_load(LHASH_OF(CONF_VALUE) *conf, const char *file,
+                                long *eline);
+# ifndef OPENSSL_NO_FP_API
+LHASH_OF(CONF_VALUE) *CONF_load_fp(LHASH_OF(CONF_VALUE) *conf, FILE *fp,
+                                   long *eline);
+# endif
+LHASH_OF(CONF_VALUE) *CONF_load_bio(LHASH_OF(CONF_VALUE) *conf, BIO *bp,
+                                    long *eline);
+STACK_OF(CONF_VALUE) *CONF_get_section(LHASH_OF(CONF_VALUE) *conf,
+                                       const char *section);
+char *CONF_get_string(LHASH_OF(CONF_VALUE) *conf, const char *group,
+                      const char *name);
+long CONF_get_number(LHASH_OF(CONF_VALUE) *conf, const char *group,
+                     const char *name);
+void CONF_free(LHASH_OF(CONF_VALUE) *conf);
+int CONF_dump_fp(LHASH_OF(CONF_VALUE) *conf, FILE *out);
+int CONF_dump_bio(LHASH_OF(CONF_VALUE) *conf, BIO *out);
+
+void OPENSSL_config(const char *config_name);
+void OPENSSL_no_config(void);
+
+/*
+ * New conf code.  The semantics are different from the functions above. If
+ * that wasn't the case, the above functions would have been replaced
+ */
+
+struct conf_st {
+    CONF_METHOD *meth;
+    void *meth_data;
+    LHASH_OF(CONF_VALUE) *data;
+};
+
+CONF *NCONF_new(CONF_METHOD *meth);
+CONF_METHOD *NCONF_default(void);
+CONF_METHOD *NCONF_WIN32(void);
+# if 0                          /* Just to give you an idea of what I have in
+                                 * mind */
+CONF_METHOD *NCONF_XML(void);
+# endif
+void NCONF_free(CONF *conf);
+void NCONF_free_data(CONF *conf);
+
+int NCONF_load(CONF *conf, const char *file, long *eline);
+# ifndef OPENSSL_NO_FP_API
+int NCONF_load_fp(CONF *conf, FILE *fp, long *eline);
+# endif
+int NCONF_load_bio(CONF *conf, BIO *bp, long *eline);
+STACK_OF(CONF_VALUE) *NCONF_get_section(const CONF *conf,
+                                        const char *section);
+char *NCONF_get_string(const CONF *conf, const char *group, const char *name);
+int NCONF_get_number_e(const CONF *conf, const char *group, const char *name,
+                       long *result);
+int NCONF_dump_fp(const CONF *conf, FILE *out);
+int NCONF_dump_bio(const CONF *conf, BIO *out);
+
+# if 0                          /* The following function has no error
+                                 * checking, and should therefore be avoided */
+long NCONF_get_number(CONF *conf, char *group, char *name);
+# else
+#  define NCONF_get_number(c,g,n,r) NCONF_get_number_e(c,g,n,r)
+# endif
+
+/* Module functions */
+
+int CONF_modules_load(const CONF *cnf, const char *appname,
+                      unsigned long flags);
+int CONF_modules_load_file(const char *filename, const char *appname,
+                           unsigned long flags);
+void CONF_modules_unload(int all);
+void CONF_modules_finish(void);
+void CONF_modules_free(void);
+int CONF_module_add(const char *name, conf_init_func *ifunc,
+                    conf_finish_func *ffunc);
+
+const char *CONF_imodule_get_name(const CONF_IMODULE *md);
+const char *CONF_imodule_get_value(const CONF_IMODULE *md);
+void *CONF_imodule_get_usr_data(const CONF_IMODULE *md);
+void CONF_imodule_set_usr_data(CONF_IMODULE *md, void *usr_data);
+CONF_MODULE *CONF_imodule_get_module(const CONF_IMODULE *md);
+unsigned long CONF_imodule_get_flags(const CONF_IMODULE *md);
+void CONF_imodule_set_flags(CONF_IMODULE *md, unsigned long flags);
+void *CONF_module_get_usr_data(CONF_MODULE *pmod);
+void CONF_module_set_usr_data(CONF_MODULE *pmod, void *usr_data);
+
+char *CONF_get1_default_config_file(void);
+
+int CONF_parse_list(const char *list, int sep, int nospc,
+                    int (*list_cb) (const char *elem, int len, void *usr),
+                    void *arg);
+
+void OPENSSL_load_builtin_modules(void);
+
+/* BEGIN ERROR CODES */
+/*
+ * The following lines are auto generated by the script mkerr.pl. Any changes
+ * made after this point may be overwritten when the script is next run.
+ */
+void ERR_load_CONF_strings(void);
+
+/* Error codes for the CONF functions. */
+
+/* Function codes. */
+# define CONF_F_CONF_DUMP_FP                              104
+# define CONF_F_CONF_LOAD                                 100
+# define CONF_F_CONF_LOAD_BIO                             102
+# define CONF_F_CONF_LOAD_FP                              103
+# define CONF_F_CONF_MODULES_LOAD                         116
+# define CONF_F_CONF_PARSE_LIST                           119
+# define CONF_F_DEF_LOAD                                  120
+# define CONF_F_DEF_LOAD_BIO                              121
+# define CONF_F_MODULE_INIT                               115
+# define CONF_F_MODULE_LOAD_DSO                           117
+# define CONF_F_MODULE_RUN                                118
+# define CONF_F_NCONF_DUMP_BIO                            105
+# define CONF_F_NCONF_DUMP_FP                             106
+# define CONF_F_NCONF_GET_NUMBER                          107
+# define CONF_F_NCONF_GET_NUMBER_E                        112
+# define CONF_F_NCONF_GET_SECTION                         108
+# define CONF_F_NCONF_GET_STRING                          109
+# define CONF_F_NCONF_LOAD                                113
+# define CONF_F_NCONF_LOAD_BIO                            110
+# define CONF_F_NCONF_LOAD_FP                             114
+# define CONF_F_NCONF_NEW                                 111
+# define CONF_F_STR_COPY                                  101
+
+/* Reason codes. */
+# define CONF_R_ERROR_LOADING_DSO                         110
+# define CONF_R_LIST_CANNOT_BE_NULL                       115
+# define CONF_R_MISSING_CLOSE_SQUARE_BRACKET              100
+# define CONF_R_MISSING_EQUAL_SIGN                        101
+# define CONF_R_MISSING_FINISH_FUNCTION                   111
+# define CONF_R_MISSING_INIT_FUNCTION                     112
+# define CONF_R_MODULE_INITIALIZATION_ERROR               109
+# define CONF_R_NO_CLOSE_BRACE                            102
+# define CONF_R_NO_CONF                                   105
+# define CONF_R_NO_CONF_OR_ENVIRONMENT_VARIABLE           106
+# define CONF_R_NO_SECTION                                107
+# define CONF_R_NO_SUCH_FILE                              114
+# define CONF_R_NO_VALUE                                  108
+# define CONF_R_UNABLE_TO_CREATE_NEW_SECTION              103
+# define CONF_R_UNKNOWN_MODULE_NAME                       113
+# define CONF_R_VARIABLE_EXPANSION_TOO_LONG               116
+# define CONF_R_VARIABLE_HAS_NO_VALUE                     104
+
+#ifdef  __cplusplus
+}
+#endif
+#endif

+ 89 - 0
libssh2/openssl/include/openssl/conf_api.h

@@ -0,0 +1,89 @@
+/* conf_api.h */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * 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 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. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    "This product includes cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``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 AUTHOR OR CONTRIBUTORS 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.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+#ifndef  HEADER_CONF_API_H
+# define HEADER_CONF_API_H
+
+# include <openssl/lhash.h>
+# include <openssl/conf.h>
+
+#ifdef  __cplusplus
+extern "C" {
+#endif
+
+/* Up until OpenSSL 0.9.5a, this was new_section */
+CONF_VALUE *_CONF_new_section(CONF *conf, const char *section);
+/* Up until OpenSSL 0.9.5a, this was get_section */
+CONF_VALUE *_CONF_get_section(const CONF *conf, const char *section);
+/* Up until OpenSSL 0.9.5a, this was CONF_get_section */
+STACK_OF(CONF_VALUE) *_CONF_get_section_values(const CONF *conf,
+                                               const char *section);
+
+int _CONF_add_string(CONF *conf, CONF_VALUE *section, CONF_VALUE *value);
+char *_CONF_get_string(const CONF *conf, const char *section,
+                       const char *name);
+long _CONF_get_number(const CONF *conf, const char *section,
+                      const char *name);
+
+int _CONF_new_data(CONF *conf);
+void _CONF_free_data(CONF *conf);
+
+#ifdef  __cplusplus
+}
+#endif
+#endif

+ 661 - 0
libssh2/openssl/include/openssl/crypto.h

@@ -0,0 +1,661 @@
+/* crypto/crypto.h */
+/* ====================================================================
+ * Copyright (c) 1998-2006 The OpenSSL 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. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    openssl-core@openssl.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED 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 OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS 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.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com).  This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * 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 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. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    "This product includes cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``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 AUTHOR OR CONTRIBUTORS 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.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+/* ====================================================================
+ * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED.
+ * ECDH support in OpenSSL originally developed by
+ * SUN MICROSYSTEMS, INC., and contributed to the OpenSSL project.
+ */
+
+#ifndef HEADER_CRYPTO_H
+# define HEADER_CRYPTO_H
+
+# include <stdlib.h>
+
+# include <openssl/e_os2.h>
+
+# ifndef OPENSSL_NO_FP_API
+#  include <stdio.h>
+# endif
+
+# include <openssl/stack.h>
+# include <openssl/safestack.h>
+# include <openssl/opensslv.h>
+# include <openssl/ossl_typ.h>
+
+# ifdef CHARSET_EBCDIC
+#  include <openssl/ebcdic.h>
+# endif
+
+/*
+ * Resolve problems on some operating systems with symbol names that clash
+ * one way or another
+ */
+# include <openssl/symhacks.h>
+
+#ifdef  __cplusplus
+extern "C" {
+#endif
+
+/* Backward compatibility to SSLeay */
+/*
+ * This is more to be used to check the correct DLL is being used in the MS
+ * world.
+ */
+# define SSLEAY_VERSION_NUMBER   OPENSSL_VERSION_NUMBER
+# define SSLEAY_VERSION          0
+/* #define SSLEAY_OPTIONS       1 no longer supported */
+# define SSLEAY_CFLAGS           2
+# define SSLEAY_BUILT_ON         3
+# define SSLEAY_PLATFORM         4
+# define SSLEAY_DIR              5
+
+/* Already declared in ossl_typ.h */
+# if 0
+typedef struct crypto_ex_data_st CRYPTO_EX_DATA;
+/* Called when a new object is created */
+typedef int CRYPTO_EX_new (void *parent, void *ptr, CRYPTO_EX_DATA *ad,
+                           int idx, long argl, void *argp);
+/* Called when an object is free()ed */
+typedef void CRYPTO_EX_free (void *parent, void *ptr, CRYPTO_EX_DATA *ad,
+                             int idx, long argl, void *argp);
+/* Called when we need to dup an object */
+typedef int CRYPTO_EX_dup (CRYPTO_EX_DATA *to, CRYPTO_EX_DATA *from,
+                           void *from_d, int idx, long argl, void *argp);
+# endif
+
+/* A generic structure to pass assorted data in a expandable way */
+typedef struct openssl_item_st {
+    int code;
+    void *value;                /* Not used for flag attributes */
+    size_t value_size;          /* Max size of value for output, length for
+                                 * input */
+    size_t *value_length;       /* Returned length of value for output */
+} OPENSSL_ITEM;
+
+/*
+ * When changing the CRYPTO_LOCK_* list, be sure to maintin the text lock
+ * names in cryptlib.c
+ */
+
+# define CRYPTO_LOCK_ERR                 1
+# define CRYPTO_LOCK_EX_DATA             2
+# define CRYPTO_LOCK_X509                3
+# define CRYPTO_LOCK_X509_INFO           4
+# define CRYPTO_LOCK_X509_PKEY           5
+# define CRYPTO_LOCK_X509_CRL            6
+# define CRYPTO_LOCK_X509_REQ            7
+# define CRYPTO_LOCK_DSA                 8
+# define CRYPTO_LOCK_RSA                 9
+# define CRYPTO_LOCK_EVP_PKEY            10
+# define CRYPTO_LOCK_X509_STORE          11
+# define CRYPTO_LOCK_SSL_CTX             12
+# define CRYPTO_LOCK_SSL_CERT            13
+# define CRYPTO_LOCK_SSL_SESSION         14
+# define CRYPTO_LOCK_SSL_SESS_CERT       15
+# define CRYPTO_LOCK_SSL                 16
+# define CRYPTO_LOCK_SSL_METHOD          17
+# define CRYPTO_LOCK_RAND                18
+# define CRYPTO_LOCK_RAND2               19
+# define CRYPTO_LOCK_MALLOC              20
+# define CRYPTO_LOCK_BIO                 21
+# define CRYPTO_LOCK_GETHOSTBYNAME       22
+# define CRYPTO_LOCK_GETSERVBYNAME       23
+# define CRYPTO_LOCK_READDIR             24
+# define CRYPTO_LOCK_RSA_BLINDING        25
+# define CRYPTO_LOCK_DH                  26
+# define CRYPTO_LOCK_MALLOC2             27
+# define CRYPTO_LOCK_DSO                 28
+# define CRYPTO_LOCK_DYNLOCK             29
+# define CRYPTO_LOCK_ENGINE              30
+# define CRYPTO_LOCK_UI                  31
+# define CRYPTO_LOCK_ECDSA               32
+# define CRYPTO_LOCK_EC                  33
+# define CRYPTO_LOCK_ECDH                34
+# define CRYPTO_LOCK_BN                  35
+# define CRYPTO_LOCK_EC_PRE_COMP         36
+# define CRYPTO_LOCK_STORE               37
+# define CRYPTO_LOCK_COMP                38
+# define CRYPTO_LOCK_FIPS                39
+# define CRYPTO_LOCK_FIPS2               40
+# define CRYPTO_NUM_LOCKS                41
+
+# define CRYPTO_LOCK             1
+# define CRYPTO_UNLOCK           2
+# define CRYPTO_READ             4
+# define CRYPTO_WRITE            8
+
+# ifndef OPENSSL_NO_LOCKING
+#  ifndef CRYPTO_w_lock
+#   define CRYPTO_w_lock(type)     \
+        CRYPTO_lock(CRYPTO_LOCK|CRYPTO_WRITE,type,__FILE__,__LINE__)
+#   define CRYPTO_w_unlock(type)   \
+        CRYPTO_lock(CRYPTO_UNLOCK|CRYPTO_WRITE,type,__FILE__,__LINE__)
+#   define CRYPTO_r_lock(type)     \
+        CRYPTO_lock(CRYPTO_LOCK|CRYPTO_READ,type,__FILE__,__LINE__)
+#   define CRYPTO_r_unlock(type)   \
+        CRYPTO_lock(CRYPTO_UNLOCK|CRYPTO_READ,type,__FILE__,__LINE__)
+#   define CRYPTO_add(addr,amount,type)    \
+        CRYPTO_add_lock(addr,amount,type,__FILE__,__LINE__)
+#  endif
+# else
+#  define CRYPTO_w_lock(a)
+#  define CRYPTO_w_unlock(a)
+#  define CRYPTO_r_lock(a)
+#  define CRYPTO_r_unlock(a)
+#  define CRYPTO_add(a,b,c)       ((*(a))+=(b))
+# endif
+
+/*
+ * Some applications as well as some parts of OpenSSL need to allocate and
+ * deallocate locks in a dynamic fashion.  The following typedef makes this
+ * possible in a type-safe manner.
+ */
+/* struct CRYPTO_dynlock_value has to be defined by the application. */
+typedef struct {
+    int references;
+    struct CRYPTO_dynlock_value *data;
+} CRYPTO_dynlock;
+
+/*
+ * The following can be used to detect memory leaks in the SSLeay library. It
+ * used, it turns on malloc checking
+ */
+
+# define CRYPTO_MEM_CHECK_OFF    0x0/* an enume */
+# define CRYPTO_MEM_CHECK_ON     0x1/* a bit */
+# define CRYPTO_MEM_CHECK_ENABLE 0x2/* a bit */
+# define CRYPTO_MEM_CHECK_DISABLE 0x3/* an enume */
+
+/*
+ * The following are bit values to turn on or off options connected to the
+ * malloc checking functionality
+ */
+
+/* Adds time to the memory checking information */
+# define V_CRYPTO_MDEBUG_TIME    0x1/* a bit */
+/* Adds thread number to the memory checking information */
+# define V_CRYPTO_MDEBUG_THREAD  0x2/* a bit */
+
+# define V_CRYPTO_MDEBUG_ALL (V_CRYPTO_MDEBUG_TIME | V_CRYPTO_MDEBUG_THREAD)
+
+/* predec of the BIO type */
+typedef struct bio_st BIO_dummy;
+
+struct crypto_ex_data_st {
+    STACK_OF(void) *sk;
+    /* gcc is screwing up this data structure :-( */
+    int dummy;
+};
+DECLARE_STACK_OF(void)
+
+/*
+ * This stuff is basically class callback functions The current classes are
+ * SSL_CTX, SSL, SSL_SESSION, and a few more
+ */
+
+typedef struct crypto_ex_data_func_st {
+    long argl;                  /* Arbitary long */
+    void *argp;                 /* Arbitary void * */
+    CRYPTO_EX_new *new_func;
+    CRYPTO_EX_free *free_func;
+    CRYPTO_EX_dup *dup_func;
+} CRYPTO_EX_DATA_FUNCS;
+
+DECLARE_STACK_OF(CRYPTO_EX_DATA_FUNCS)
+
+/*
+ * Per class, we have a STACK of CRYPTO_EX_DATA_FUNCS for each CRYPTO_EX_DATA
+ * entry.
+ */
+
+# define CRYPTO_EX_INDEX_BIO             0
+# define CRYPTO_EX_INDEX_SSL             1
+# define CRYPTO_EX_INDEX_SSL_CTX         2
+# define CRYPTO_EX_INDEX_SSL_SESSION     3
+# define CRYPTO_EX_INDEX_X509_STORE      4
+# define CRYPTO_EX_INDEX_X509_STORE_CTX  5
+# define CRYPTO_EX_INDEX_RSA             6
+# define CRYPTO_EX_INDEX_DSA             7
+# define CRYPTO_EX_INDEX_DH              8
+# define CRYPTO_EX_INDEX_ENGINE          9
+# define CRYPTO_EX_INDEX_X509            10
+# define CRYPTO_EX_INDEX_UI              11
+# define CRYPTO_EX_INDEX_ECDSA           12
+# define CRYPTO_EX_INDEX_ECDH            13
+# define CRYPTO_EX_INDEX_COMP            14
+# define CRYPTO_EX_INDEX_STORE           15
+
+/*
+ * Dynamically assigned indexes start from this value (don't use directly,
+ * use via CRYPTO_ex_data_new_class).
+ */
+# define CRYPTO_EX_INDEX_USER            100
+
+/*
+ * This is the default callbacks, but we can have others as well: this is
+ * needed in Win32 where the application malloc and the library malloc may
+ * not be the same.
+ */
+# define CRYPTO_malloc_init()    CRYPTO_set_mem_functions(\
+        malloc, realloc, free)
+
+# if defined CRYPTO_MDEBUG_ALL || defined CRYPTO_MDEBUG_TIME || defined CRYPTO_MDEBUG_THREAD
+#  ifndef CRYPTO_MDEBUG         /* avoid duplicate #define */
+#   define CRYPTO_MDEBUG
+#  endif
+# endif
+
+/*
+ * Set standard debugging functions (not done by default unless CRYPTO_MDEBUG
+ * is defined)
+ */
+# define CRYPTO_malloc_debug_init()      do {\
+        CRYPTO_set_mem_debug_functions(\
+                CRYPTO_dbg_malloc,\
+                CRYPTO_dbg_realloc,\
+                CRYPTO_dbg_free,\
+                CRYPTO_dbg_set_options,\
+                CRYPTO_dbg_get_options);\
+        } while(0)
+
+int CRYPTO_mem_ctrl(int mode);
+int CRYPTO_is_mem_check_on(void);
+
+/* for applications */
+# define MemCheck_start() CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_ON)
+# define MemCheck_stop() CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_OFF)
+
+/* for library-internal use */
+# define MemCheck_on()   CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_ENABLE)
+# define MemCheck_off()  CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_DISABLE)
+# define is_MemCheck_on() CRYPTO_is_mem_check_on()
+
+# define OPENSSL_malloc(num)     CRYPTO_malloc((int)num,__FILE__,__LINE__)
+# define OPENSSL_strdup(str)     CRYPTO_strdup((str),__FILE__,__LINE__)
+# define OPENSSL_realloc(addr,num) \
+        CRYPTO_realloc((char *)addr,(int)num,__FILE__,__LINE__)
+# define OPENSSL_realloc_clean(addr,old_num,num) \
+        CRYPTO_realloc_clean(addr,old_num,num,__FILE__,__LINE__)
+# define OPENSSL_remalloc(addr,num) \
+        CRYPTO_remalloc((char **)addr,(int)num,__FILE__,__LINE__)
+# define OPENSSL_freeFunc        CRYPTO_free
+# define OPENSSL_free(addr)      CRYPTO_free(addr)
+
+# define OPENSSL_malloc_locked(num) \
+        CRYPTO_malloc_locked((int)num,__FILE__,__LINE__)
+# define OPENSSL_free_locked(addr) CRYPTO_free_locked(addr)
+
+const char *SSLeay_version(int type);
+unsigned long SSLeay(void);
+
+int OPENSSL_issetugid(void);
+
+/* An opaque type representing an implementation of "ex_data" support */
+typedef struct st_CRYPTO_EX_DATA_IMPL CRYPTO_EX_DATA_IMPL;
+/* Return an opaque pointer to the current "ex_data" implementation */
+const CRYPTO_EX_DATA_IMPL *CRYPTO_get_ex_data_implementation(void);
+/* Sets the "ex_data" implementation to be used (if it's not too late) */
+int CRYPTO_set_ex_data_implementation(const CRYPTO_EX_DATA_IMPL *i);
+/* Get a new "ex_data" class, and return the corresponding "class_index" */
+int CRYPTO_ex_data_new_class(void);
+/* Within a given class, get/register a new index */
+int CRYPTO_get_ex_new_index(int class_index, long argl, void *argp,
+                            CRYPTO_EX_new *new_func, CRYPTO_EX_dup *dup_func,
+                            CRYPTO_EX_free *free_func);
+/*
+ * Initialise/duplicate/free CRYPTO_EX_DATA variables corresponding to a
+ * given class (invokes whatever per-class callbacks are applicable)
+ */
+int CRYPTO_new_ex_data(int class_index, void *obj, CRYPTO_EX_DATA *ad);
+int CRYPTO_dup_ex_data(int class_index, CRYPTO_EX_DATA *to,
+                       CRYPTO_EX_DATA *from);
+void CRYPTO_free_ex_data(int class_index, void *obj, CRYPTO_EX_DATA *ad);
+/*
+ * Get/set data in a CRYPTO_EX_DATA variable corresponding to a particular
+ * index (relative to the class type involved)
+ */
+int CRYPTO_set_ex_data(CRYPTO_EX_DATA *ad, int idx, void *val);
+void *CRYPTO_get_ex_data(const CRYPTO_EX_DATA *ad, int idx);
+/*
+ * This function cleans up all "ex_data" state. It mustn't be called under
+ * potential race-conditions.
+ */
+void CRYPTO_cleanup_all_ex_data(void);
+
+int CRYPTO_get_new_lockid(char *name);
+
+int CRYPTO_num_locks(void);     /* return CRYPTO_NUM_LOCKS (shared libs!) */
+void CRYPTO_lock(int mode, int type, const char *file, int line);
+void CRYPTO_set_locking_callback(void (*func) (int mode, int type,
+                                               const char *file, int line));
+void (*CRYPTO_get_locking_callback(void)) (int mode, int type,
+                                           const char *file, int line);
+void CRYPTO_set_add_lock_callback(int (*func)
+                                   (int *num, int mount, int type,
+                                    const char *file, int line));
+int (*CRYPTO_get_add_lock_callback(void)) (int *num, int mount, int type,
+                                           const char *file, int line);
+
+/* Don't use this structure directly. */
+typedef struct crypto_threadid_st {
+    void *ptr;
+    unsigned long val;
+} CRYPTO_THREADID;
+/* Only use CRYPTO_THREADID_set_[numeric|pointer]() within callbacks */
+void CRYPTO_THREADID_set_numeric(CRYPTO_THREADID *id, unsigned long val);
+void CRYPTO_THREADID_set_pointer(CRYPTO_THREADID *id, void *ptr);
+int CRYPTO_THREADID_set_callback(void (*threadid_func) (CRYPTO_THREADID *));
+void (*CRYPTO_THREADID_get_callback(void)) (CRYPTO_THREADID *);
+void CRYPTO_THREADID_current(CRYPTO_THREADID *id);
+int CRYPTO_THREADID_cmp(const CRYPTO_THREADID *a, const CRYPTO_THREADID *b);
+void CRYPTO_THREADID_cpy(CRYPTO_THREADID *dest, const CRYPTO_THREADID *src);
+unsigned long CRYPTO_THREADID_hash(const CRYPTO_THREADID *id);
+# ifndef OPENSSL_NO_DEPRECATED
+void CRYPTO_set_id_callback(unsigned long (*func) (void));
+unsigned long (*CRYPTO_get_id_callback(void)) (void);
+unsigned long CRYPTO_thread_id(void);
+# endif
+
+const char *CRYPTO_get_lock_name(int type);
+int CRYPTO_add_lock(int *pointer, int amount, int type, const char *file,
+                    int line);
+
+int CRYPTO_get_new_dynlockid(void);
+void CRYPTO_destroy_dynlockid(int i);
+struct CRYPTO_dynlock_value *CRYPTO_get_dynlock_value(int i);
+void CRYPTO_set_dynlock_create_callback(struct CRYPTO_dynlock_value
+                                        *(*dyn_create_function) (const char
+                                                                 *file,
+                                                                 int line));
+void CRYPTO_set_dynlock_lock_callback(void (*dyn_lock_function)
+                                       (int mode,
+                                        struct CRYPTO_dynlock_value *l,
+                                        const char *file, int line));
+void CRYPTO_set_dynlock_destroy_callback(void (*dyn_destroy_function)
+                                          (struct CRYPTO_dynlock_value *l,
+                                           const char *file, int line));
+struct CRYPTO_dynlock_value
+*(*CRYPTO_get_dynlock_create_callback(void)) (const char *file, int line);
+void (*CRYPTO_get_dynlock_lock_callback(void)) (int mode,
+                                                struct CRYPTO_dynlock_value
+                                                *l, const char *file,
+                                                int line);
+void (*CRYPTO_get_dynlock_destroy_callback(void)) (struct CRYPTO_dynlock_value
+                                                   *l, const char *file,
+                                                   int line);
+
+/*
+ * CRYPTO_set_mem_functions includes CRYPTO_set_locked_mem_functions -- call
+ * the latter last if you need different functions
+ */
+int CRYPTO_set_mem_functions(void *(*m) (size_t), void *(*r) (void *, size_t),
+                             void (*f) (void *));
+int CRYPTO_set_locked_mem_functions(void *(*m) (size_t),
+                                    void (*free_func) (void *));
+int CRYPTO_set_mem_ex_functions(void *(*m) (size_t, const char *, int),
+                                void *(*r) (void *, size_t, const char *,
+                                            int), void (*f) (void *));
+int CRYPTO_set_locked_mem_ex_functions(void *(*m) (size_t, const char *, int),
+                                       void (*free_func) (void *));
+int CRYPTO_set_mem_debug_functions(void (*m)
+                                    (void *, int, const char *, int, int),
+                                   void (*r) (void *, void *, int,
+                                              const char *, int, int),
+                                   void (*f) (void *, int), void (*so) (long),
+                                   long (*go) (void));
+void CRYPTO_get_mem_functions(void *(**m) (size_t),
+                              void *(**r) (void *, size_t),
+                              void (**f) (void *));
+void CRYPTO_get_locked_mem_functions(void *(**m) (size_t),
+                                     void (**f) (void *));
+void CRYPTO_get_mem_ex_functions(void *(**m) (size_t, const char *, int),
+                                 void *(**r) (void *, size_t, const char *,
+                                              int), void (**f) (void *));
+void CRYPTO_get_locked_mem_ex_functions(void
+                                        *(**m) (size_t, const char *, int),
+                                        void (**f) (void *));
+void CRYPTO_get_mem_debug_functions(void (**m)
+                                     (void *, int, const char *, int, int),
+                                    void (**r) (void *, void *, int,
+                                                const char *, int, int),
+                                    void (**f) (void *, int),
+                                    void (**so) (long), long (**go) (void));
+
+void *CRYPTO_malloc_locked(int num, const char *file, int line);
+void CRYPTO_free_locked(void *ptr);
+void *CRYPTO_malloc(int num, const char *file, int line);
+char *CRYPTO_strdup(const char *str, const char *file, int line);
+void CRYPTO_free(void *ptr);
+void *CRYPTO_realloc(void *addr, int num, const char *file, int line);
+void *CRYPTO_realloc_clean(void *addr, int old_num, int num, const char *file,
+                           int line);
+void *CRYPTO_remalloc(void *addr, int num, const char *file, int line);
+
+void OPENSSL_cleanse(void *ptr, size_t len);
+
+void CRYPTO_set_mem_debug_options(long bits);
+long CRYPTO_get_mem_debug_options(void);
+
+# define CRYPTO_push_info(info) \
+        CRYPTO_push_info_(info, __FILE__, __LINE__);
+int CRYPTO_push_info_(const char *info, const char *file, int line);
+int CRYPTO_pop_info(void);
+int CRYPTO_remove_all_info(void);
+
+/*
+ * Default debugging functions (enabled by CRYPTO_malloc_debug_init() macro;
+ * used as default in CRYPTO_MDEBUG compilations):
+ */
+/*-
+ * The last argument has the following significance:
+ *
+ * 0:   called before the actual memory allocation has taken place
+ * 1:   called after the actual memory allocation has taken place
+ */
+void CRYPTO_dbg_malloc(void *addr, int num, const char *file, int line,
+                       int before_p);
+void CRYPTO_dbg_realloc(void *addr1, void *addr2, int num, const char *file,
+                        int line, int before_p);
+void CRYPTO_dbg_free(void *addr, int before_p);
+/*-
+ * Tell the debugging code about options.  By default, the following values
+ * apply:
+ *
+ * 0:                           Clear all options.
+ * V_CRYPTO_MDEBUG_TIME (1):    Set the "Show Time" option.
+ * V_CRYPTO_MDEBUG_THREAD (2):  Set the "Show Thread Number" option.
+ * V_CRYPTO_MDEBUG_ALL (3):     1 + 2
+ */
+void CRYPTO_dbg_set_options(long bits);
+long CRYPTO_dbg_get_options(void);
+
+# ifndef OPENSSL_NO_FP_API
+void CRYPTO_mem_leaks_fp(FILE *);
+# endif
+void CRYPTO_mem_leaks(struct bio_st *bio);
+/* unsigned long order, char *file, int line, int num_bytes, char *addr */
+typedef void *CRYPTO_MEM_LEAK_CB (unsigned long, const char *, int, int,
+                                  void *);
+void CRYPTO_mem_leaks_cb(CRYPTO_MEM_LEAK_CB *cb);
+
+/* die if we have to */
+void OpenSSLDie(const char *file, int line, const char *assertion);
+# define OPENSSL_assert(e)       (void)((e) ? 0 : (OpenSSLDie(__FILE__, __LINE__, #e),1))
+
+unsigned long *OPENSSL_ia32cap_loc(void);
+# define OPENSSL_ia32cap (*(OPENSSL_ia32cap_loc()))
+int OPENSSL_isservice(void);
+
+int FIPS_mode(void);
+int FIPS_mode_set(int r);
+
+void OPENSSL_init(void);
+
+# define fips_md_init(alg) fips_md_init_ctx(alg, alg)
+
+# ifdef OPENSSL_FIPS
+#  define fips_md_init_ctx(alg, cx) \
+        int alg##_Init(cx##_CTX *c) \
+        { \
+        if (FIPS_mode()) OpenSSLDie(__FILE__, __LINE__, \
+                "Low level API call to digest " #alg " forbidden in FIPS mode!"); \
+        return private_##alg##_Init(c); \
+        } \
+        int private_##alg##_Init(cx##_CTX *c)
+
+#  define fips_cipher_abort(alg) \
+        if (FIPS_mode()) OpenSSLDie(__FILE__, __LINE__, \
+                "Low level API call to cipher " #alg " forbidden in FIPS mode!")
+
+# else
+#  define fips_md_init_ctx(alg, cx) \
+        int alg##_Init(cx##_CTX *c)
+#  define fips_cipher_abort(alg) while(0)
+# endif
+
+/*
+ * CRYPTO_memcmp returns zero iff the |len| bytes at |a| and |b| are equal.
+ * It takes an amount of time dependent on |len|, but independent of the
+ * contents of |a| and |b|. Unlike memcmp, it cannot be used to put elements
+ * into a defined order as the return value when a != b is undefined, other
+ * than to be non-zero.
+ */
+int CRYPTO_memcmp(const volatile void *a, const volatile void *b, size_t len);
+
+/* BEGIN ERROR CODES */
+/*
+ * The following lines are auto generated by the script mkerr.pl. Any changes
+ * made after this point may be overwritten when the script is next run.
+ */
+void ERR_load_CRYPTO_strings(void);
+
+/* Error codes for the CRYPTO functions. */
+
+/* Function codes. */
+# define CRYPTO_F_CRYPTO_GET_EX_NEW_INDEX                 100
+# define CRYPTO_F_CRYPTO_GET_NEW_DYNLOCKID                103
+# define CRYPTO_F_CRYPTO_GET_NEW_LOCKID                   101
+# define CRYPTO_F_CRYPTO_SET_EX_DATA                      102
+# define CRYPTO_F_DEF_ADD_INDEX                           104
+# define CRYPTO_F_DEF_GET_CLASS                           105
+# define CRYPTO_F_FIPS_MODE_SET                           109
+# define CRYPTO_F_INT_DUP_EX_DATA                         106
+# define CRYPTO_F_INT_FREE_EX_DATA                        107
+# define CRYPTO_F_INT_NEW_EX_DATA                         108
+
+/* Reason codes. */
+# define CRYPTO_R_FIPS_MODE_NOT_SUPPORTED                 101
+# define CRYPTO_R_NO_DYNLOCK_CREATE_CALLBACK              100
+
+#ifdef  __cplusplus
+}
+#endif
+#endif

+ 257 - 0
libssh2/openssl/include/openssl/des.h

@@ -0,0 +1,257 @@
+/* crypto/des/des.h */
+/* Copyright (C) 1995-1997 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * 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 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. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    "This product includes cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``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 AUTHOR OR CONTRIBUTORS 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.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+#ifndef HEADER_NEW_DES_H
+# define HEADER_NEW_DES_H
+
+# include <openssl/e_os2.h>     /* OPENSSL_EXTERN, OPENSSL_NO_DES, DES_LONG
+                                 * (via openssl/opensslconf.h */
+
+# ifdef OPENSSL_NO_DES
+#  error DES is disabled.
+# endif
+
+# ifdef OPENSSL_BUILD_SHLIBCRYPTO
+#  undef OPENSSL_EXTERN
+#  define OPENSSL_EXTERN OPENSSL_EXPORT
+# endif
+
+#ifdef  __cplusplus
+extern "C" {
+#endif
+
+typedef unsigned char DES_cblock[8];
+typedef /* const */ unsigned char const_DES_cblock[8];
+/*
+ * With "const", gcc 2.8.1 on Solaris thinks that DES_cblock * and
+ * const_DES_cblock * are incompatible pointer types.
+ */
+
+typedef struct DES_ks {
+    union {
+        DES_cblock cblock;
+        /*
+         * make sure things are correct size on machines with 8 byte longs
+         */
+        DES_LONG deslong[2];
+    } ks[16];
+} DES_key_schedule;
+
+# ifndef OPENSSL_DISABLE_OLD_DES_SUPPORT
+#  ifndef OPENSSL_ENABLE_OLD_DES_SUPPORT
+#   define OPENSSL_ENABLE_OLD_DES_SUPPORT
+#  endif
+# endif
+
+# ifdef OPENSSL_ENABLE_OLD_DES_SUPPORT
+#  include <openssl/des_old.h>
+# endif
+
+# define DES_KEY_SZ      (sizeof(DES_cblock))
+# define DES_SCHEDULE_SZ (sizeof(DES_key_schedule))
+
+# define DES_ENCRYPT     1
+# define DES_DECRYPT     0
+
+# define DES_CBC_MODE    0
+# define DES_PCBC_MODE   1
+
+# define DES_ecb2_encrypt(i,o,k1,k2,e) \
+        DES_ecb3_encrypt((i),(o),(k1),(k2),(k1),(e))
+
+# define DES_ede2_cbc_encrypt(i,o,l,k1,k2,iv,e) \
+        DES_ede3_cbc_encrypt((i),(o),(l),(k1),(k2),(k1),(iv),(e))
+
+# define DES_ede2_cfb64_encrypt(i,o,l,k1,k2,iv,n,e) \
+        DES_ede3_cfb64_encrypt((i),(o),(l),(k1),(k2),(k1),(iv),(n),(e))
+
+# define DES_ede2_ofb64_encrypt(i,o,l,k1,k2,iv,n) \
+        DES_ede3_ofb64_encrypt((i),(o),(l),(k1),(k2),(k1),(iv),(n))
+
+OPENSSL_DECLARE_GLOBAL(int, DES_check_key); /* defaults to false */
+# define DES_check_key OPENSSL_GLOBAL_REF(DES_check_key)
+OPENSSL_DECLARE_GLOBAL(int, DES_rw_mode); /* defaults to DES_PCBC_MODE */
+# define DES_rw_mode OPENSSL_GLOBAL_REF(DES_rw_mode)
+
+const char *DES_options(void);
+void DES_ecb3_encrypt(const_DES_cblock *input, DES_cblock *output,
+                      DES_key_schedule *ks1, DES_key_schedule *ks2,
+                      DES_key_schedule *ks3, int enc);
+DES_LONG DES_cbc_cksum(const unsigned char *input, DES_cblock *output,
+                       long length, DES_key_schedule *schedule,
+                       const_DES_cblock *ivec);
+/* DES_cbc_encrypt does not update the IV!  Use DES_ncbc_encrypt instead. */
+void DES_cbc_encrypt(const unsigned char *input, unsigned char *output,
+                     long length, DES_key_schedule *schedule,
+                     DES_cblock *ivec, int enc);
+void DES_ncbc_encrypt(const unsigned char *input, unsigned char *output,
+                      long length, DES_key_schedule *schedule,
+                      DES_cblock *ivec, int enc);
+void DES_xcbc_encrypt(const unsigned char *input, unsigned char *output,
+                      long length, DES_key_schedule *schedule,
+                      DES_cblock *ivec, const_DES_cblock *inw,
+                      const_DES_cblock *outw, int enc);
+void DES_cfb_encrypt(const unsigned char *in, unsigned char *out, int numbits,
+                     long length, DES_key_schedule *schedule,
+                     DES_cblock *ivec, int enc);
+void DES_ecb_encrypt(const_DES_cblock *input, DES_cblock *output,
+                     DES_key_schedule *ks, int enc);
+
+/*
+ * This is the DES encryption function that gets called by just about every
+ * other DES routine in the library.  You should not use this function except
+ * to implement 'modes' of DES.  I say this because the functions that call
+ * this routine do the conversion from 'char *' to long, and this needs to be
+ * done to make sure 'non-aligned' memory access do not occur.  The
+ * characters are loaded 'little endian'. Data is a pointer to 2 unsigned
+ * long's and ks is the DES_key_schedule to use.  enc, is non zero specifies
+ * encryption, zero if decryption.
+ */
+void DES_encrypt1(DES_LONG *data, DES_key_schedule *ks, int enc);
+
+/*
+ * This functions is the same as DES_encrypt1() except that the DES initial
+ * permutation (IP) and final permutation (FP) have been left out.  As for
+ * DES_encrypt1(), you should not use this function. It is used by the
+ * routines in the library that implement triple DES. IP() DES_encrypt2()
+ * DES_encrypt2() DES_encrypt2() FP() is the same as DES_encrypt1()
+ * DES_encrypt1() DES_encrypt1() except faster :-).
+ */
+void DES_encrypt2(DES_LONG *data, DES_key_schedule *ks, int enc);
+
+void DES_encrypt3(DES_LONG *data, DES_key_schedule *ks1,
+                  DES_key_schedule *ks2, DES_key_schedule *ks3);
+void DES_decrypt3(DES_LONG *data, DES_key_schedule *ks1,
+                  DES_key_schedule *ks2, DES_key_schedule *ks3);
+void DES_ede3_cbc_encrypt(const unsigned char *input, unsigned char *output,
+                          long length,
+                          DES_key_schedule *ks1, DES_key_schedule *ks2,
+                          DES_key_schedule *ks3, DES_cblock *ivec, int enc);
+void DES_ede3_cbcm_encrypt(const unsigned char *in, unsigned char *out,
+                           long length,
+                           DES_key_schedule *ks1, DES_key_schedule *ks2,
+                           DES_key_schedule *ks3,
+                           DES_cblock *ivec1, DES_cblock *ivec2, int enc);
+void DES_ede3_cfb64_encrypt(const unsigned char *in, unsigned char *out,
+                            long length, DES_key_schedule *ks1,
+                            DES_key_schedule *ks2, DES_key_schedule *ks3,
+                            DES_cblock *ivec, int *num, int enc);
+void DES_ede3_cfb_encrypt(const unsigned char *in, unsigned char *out,
+                          int numbits, long length, DES_key_schedule *ks1,
+                          DES_key_schedule *ks2, DES_key_schedule *ks3,
+                          DES_cblock *ivec, int enc);
+void DES_ede3_ofb64_encrypt(const unsigned char *in, unsigned char *out,
+                            long length, DES_key_schedule *ks1,
+                            DES_key_schedule *ks2, DES_key_schedule *ks3,
+                            DES_cblock *ivec, int *num);
+# if 0
+void DES_xwhite_in2out(const_DES_cblock *DES_key, const_DES_cblock *in_white,
+                       DES_cblock *out_white);
+# endif
+
+int DES_enc_read(int fd, void *buf, int len, DES_key_schedule *sched,
+                 DES_cblock *iv);
+int DES_enc_write(int fd, const void *buf, int len, DES_key_schedule *sched,
+                  DES_cblock *iv);
+char *DES_fcrypt(const char *buf, const char *salt, char *ret);
+char *DES_crypt(const char *buf, const char *salt);
+void DES_ofb_encrypt(const unsigned char *in, unsigned char *out, int numbits,
+                     long length, DES_key_schedule *schedule,
+                     DES_cblock *ivec);
+void DES_pcbc_encrypt(const unsigned char *input, unsigned char *output,
+                      long length, DES_key_schedule *schedule,
+                      DES_cblock *ivec, int enc);
+DES_LONG DES_quad_cksum(const unsigned char *input, DES_cblock output[],
+                        long length, int out_count, DES_cblock *seed);
+int DES_random_key(DES_cblock *ret);
+void DES_set_odd_parity(DES_cblock *key);
+int DES_check_key_parity(const_DES_cblock *key);
+int DES_is_weak_key(const_DES_cblock *key);
+/*
+ * DES_set_key (= set_key = DES_key_sched = key_sched) calls
+ * DES_set_key_checked if global variable DES_check_key is set,
+ * DES_set_key_unchecked otherwise.
+ */
+int DES_set_key(const_DES_cblock *key, DES_key_schedule *schedule);
+int DES_key_sched(const_DES_cblock *key, DES_key_schedule *schedule);
+int DES_set_key_checked(const_DES_cblock *key, DES_key_schedule *schedule);
+void DES_set_key_unchecked(const_DES_cblock *key, DES_key_schedule *schedule);
+# ifdef OPENSSL_FIPS
+void private_DES_set_key_unchecked(const_DES_cblock *key,
+                                   DES_key_schedule *schedule);
+# endif
+void DES_string_to_key(const char *str, DES_cblock *key);
+void DES_string_to_2keys(const char *str, DES_cblock *key1, DES_cblock *key2);
+void DES_cfb64_encrypt(const unsigned char *in, unsigned char *out,
+                       long length, DES_key_schedule *schedule,
+                       DES_cblock *ivec, int *num, int enc);
+void DES_ofb64_encrypt(const unsigned char *in, unsigned char *out,
+                       long length, DES_key_schedule *schedule,
+                       DES_cblock *ivec, int *num);
+
+int DES_read_password(DES_cblock *key, const char *prompt, int verify);
+int DES_read_2passwords(DES_cblock *key1, DES_cblock *key2,
+                        const char *prompt, int verify);
+
+# define DES_fixup_key_parity DES_set_odd_parity
+
+#ifdef  __cplusplus
+}
+#endif
+
+#endif

+ 497 - 0
libssh2/openssl/include/openssl/des_old.h

@@ -0,0 +1,497 @@
+/* crypto/des/des_old.h */
+
+/*-
+ * WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING
+ *
+ * The function names in here are deprecated and are only present to
+ * provide an interface compatible with openssl 0.9.6 and older as
+ * well as libdes.  OpenSSL now provides functions where "des_" has
+ * been replaced with "DES_" in the names, to make it possible to
+ * make incompatible changes that are needed for C type security and
+ * other stuff.
+ *
+ * This include files has two compatibility modes:
+ *
+ *   - If OPENSSL_DES_LIBDES_COMPATIBILITY is defined, you get an API
+ *     that is compatible with libdes and SSLeay.
+ *   - If OPENSSL_DES_LIBDES_COMPATIBILITY isn't defined, you get an
+ *     API that is compatible with OpenSSL 0.9.5x to 0.9.6x.
+ *
+ * Note that these modes break earlier snapshots of OpenSSL, where
+ * libdes compatibility was the only available mode or (later on) the
+ * prefered compatibility mode.  However, after much consideration
+ * (and more or less violent discussions with external parties), it
+ * was concluded that OpenSSL should be compatible with earlier versions
+ * of itself before anything else.  Also, in all honesty, libdes is
+ * an old beast that shouldn't really be used any more.
+ *
+ * Please consider starting to use the DES_ functions rather than the
+ * des_ ones.  The des_ functions will disappear completely before
+ * OpenSSL 1.0!
+ *
+ * WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING
+ */
+
+/*
+ * Written by Richard Levitte (richard@levitte.org) for the OpenSSL project
+ * 2001.
+ */
+/* ====================================================================
+ * Copyright (c) 1998-2002 The OpenSSL 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. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    openssl-core@openssl.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED 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 OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS 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.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com).  This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+
+#ifndef HEADER_DES_H
+# define HEADER_DES_H
+
+# include <openssl/e_os2.h>     /* OPENSSL_EXTERN, OPENSSL_NO_DES, DES_LONG */
+
+# ifdef OPENSSL_NO_DES
+#  error DES is disabled.
+# endif
+
+# ifndef HEADER_NEW_DES_H
+#  error You must include des.h, not des_old.h directly.
+# endif
+
+# ifdef _KERBEROS_DES_H
+#  error <openssl/des_old.h> replaces <kerberos/des.h>.
+# endif
+
+# include <openssl/symhacks.h>
+
+# ifdef OPENSSL_BUILD_SHLIBCRYPTO
+#  undef OPENSSL_EXTERN
+#  define OPENSSL_EXTERN OPENSSL_EXPORT
+# endif
+
+#ifdef  __cplusplus
+extern "C" {
+#endif
+
+# ifdef _
+#  undef _
+# endif
+
+typedef unsigned char _ossl_old_des_cblock[8];
+typedef struct _ossl_old_des_ks_struct {
+    union {
+        _ossl_old_des_cblock _;
+        /*
+         * make sure things are correct size on machines with 8 byte longs
+         */
+        DES_LONG pad[2];
+    } ks;
+} _ossl_old_des_key_schedule[16];
+
+# ifndef OPENSSL_DES_LIBDES_COMPATIBILITY
+#  define des_cblock DES_cblock
+#  define const_des_cblock const_DES_cblock
+#  define des_key_schedule DES_key_schedule
+#  define des_ecb3_encrypt(i,o,k1,k2,k3,e)\
+        DES_ecb3_encrypt((i),(o),&(k1),&(k2),&(k3),(e))
+#  define des_ede3_cbc_encrypt(i,o,l,k1,k2,k3,iv,e)\
+        DES_ede3_cbc_encrypt((i),(o),(l),&(k1),&(k2),&(k3),(iv),(e))
+#  define des_ede3_cbcm_encrypt(i,o,l,k1,k2,k3,iv1,iv2,e)\
+        DES_ede3_cbcm_encrypt((i),(o),(l),&(k1),&(k2),&(k3),(iv1),(iv2),(e))
+#  define des_ede3_cfb64_encrypt(i,o,l,k1,k2,k3,iv,n,e)\
+        DES_ede3_cfb64_encrypt((i),(o),(l),&(k1),&(k2),&(k3),(iv),(n),(e))
+#  define des_ede3_ofb64_encrypt(i,o,l,k1,k2,k3,iv,n)\
+        DES_ede3_ofb64_encrypt((i),(o),(l),&(k1),&(k2),&(k3),(iv),(n))
+#  define des_options()\
+        DES_options()
+#  define des_cbc_cksum(i,o,l,k,iv)\
+        DES_cbc_cksum((i),(o),(l),&(k),(iv))
+#  define des_cbc_encrypt(i,o,l,k,iv,e)\
+        DES_cbc_encrypt((i),(o),(l),&(k),(iv),(e))
+#  define des_ncbc_encrypt(i,o,l,k,iv,e)\
+        DES_ncbc_encrypt((i),(o),(l),&(k),(iv),(e))
+#  define des_xcbc_encrypt(i,o,l,k,iv,inw,outw,e)\
+        DES_xcbc_encrypt((i),(o),(l),&(k),(iv),(inw),(outw),(e))
+#  define des_cfb_encrypt(i,o,n,l,k,iv,e)\
+        DES_cfb_encrypt((i),(o),(n),(l),&(k),(iv),(e))
+#  define des_ecb_encrypt(i,o,k,e)\
+        DES_ecb_encrypt((i),(o),&(k),(e))
+#  define des_encrypt1(d,k,e)\
+        DES_encrypt1((d),&(k),(e))
+#  define des_encrypt2(d,k,e)\
+        DES_encrypt2((d),&(k),(e))
+#  define des_encrypt3(d,k1,k2,k3)\
+        DES_encrypt3((d),&(k1),&(k2),&(k3))
+#  define des_decrypt3(d,k1,k2,k3)\
+        DES_decrypt3((d),&(k1),&(k2),&(k3))
+#  define des_xwhite_in2out(k,i,o)\
+        DES_xwhite_in2out((k),(i),(o))
+#  define des_enc_read(f,b,l,k,iv)\
+        DES_enc_read((f),(b),(l),&(k),(iv))
+#  define des_enc_write(f,b,l,k,iv)\
+        DES_enc_write((f),(b),(l),&(k),(iv))
+#  define des_fcrypt(b,s,r)\
+        DES_fcrypt((b),(s),(r))
+#  if 0
+#   define des_crypt(b,s)\
+        DES_crypt((b),(s))
+#   if !defined(PERL5) && !defined(__FreeBSD__) && !defined(NeXT) && !defined(__OpenBSD__)
+#    define crypt(b,s)\
+        DES_crypt((b),(s))
+#   endif
+#  endif
+#  define des_ofb_encrypt(i,o,n,l,k,iv)\
+        DES_ofb_encrypt((i),(o),(n),(l),&(k),(iv))
+#  define des_pcbc_encrypt(i,o,l,k,iv,e)\
+        DES_pcbc_encrypt((i),(o),(l),&(k),(iv),(e))
+#  define des_quad_cksum(i,o,l,c,s)\
+        DES_quad_cksum((i),(o),(l),(c),(s))
+#  define des_random_seed(k)\
+        _ossl_096_des_random_seed((k))
+#  define des_random_key(r)\
+        DES_random_key((r))
+#  define des_read_password(k,p,v) \
+        DES_read_password((k),(p),(v))
+#  define des_read_2passwords(k1,k2,p,v) \
+        DES_read_2passwords((k1),(k2),(p),(v))
+#  define des_set_odd_parity(k)\
+        DES_set_odd_parity((k))
+#  define des_check_key_parity(k)\
+        DES_check_key_parity((k))
+#  define des_is_weak_key(k)\
+        DES_is_weak_key((k))
+#  define des_set_key(k,ks)\
+        DES_set_key((k),&(ks))
+#  define des_key_sched(k,ks)\
+        DES_key_sched((k),&(ks))
+#  define des_set_key_checked(k,ks)\
+        DES_set_key_checked((k),&(ks))
+#  define des_set_key_unchecked(k,ks)\
+        DES_set_key_unchecked((k),&(ks))
+#  define des_string_to_key(s,k)\
+        DES_string_to_key((s),(k))
+#  define des_string_to_2keys(s,k1,k2)\
+        DES_string_to_2keys((s),(k1),(k2))
+#  define des_cfb64_encrypt(i,o,l,ks,iv,n,e)\
+        DES_cfb64_encrypt((i),(o),(l),&(ks),(iv),(n),(e))
+#  define des_ofb64_encrypt(i,o,l,ks,iv,n)\
+        DES_ofb64_encrypt((i),(o),(l),&(ks),(iv),(n))
+
+#  define des_ecb2_encrypt(i,o,k1,k2,e) \
+        des_ecb3_encrypt((i),(o),(k1),(k2),(k1),(e))
+
+#  define des_ede2_cbc_encrypt(i,o,l,k1,k2,iv,e) \
+        des_ede3_cbc_encrypt((i),(o),(l),(k1),(k2),(k1),(iv),(e))
+
+#  define des_ede2_cfb64_encrypt(i,o,l,k1,k2,iv,n,e) \
+        des_ede3_cfb64_encrypt((i),(o),(l),(k1),(k2),(k1),(iv),(n),(e))
+
+#  define des_ede2_ofb64_encrypt(i,o,l,k1,k2,iv,n) \
+        des_ede3_ofb64_encrypt((i),(o),(l),(k1),(k2),(k1),(iv),(n))
+
+#  define des_check_key DES_check_key
+#  define des_rw_mode DES_rw_mode
+# else                          /* libdes compatibility */
+/*
+ * Map all symbol names to _ossl_old_des_* form, so we avoid all clashes with
+ * libdes
+ */
+#  define des_cblock _ossl_old_des_cblock
+#  define des_key_schedule _ossl_old_des_key_schedule
+#  define des_ecb3_encrypt(i,o,k1,k2,k3,e)\
+        _ossl_old_des_ecb3_encrypt((i),(o),(k1),(k2),(k3),(e))
+#  define des_ede3_cbc_encrypt(i,o,l,k1,k2,k3,iv,e)\
+        _ossl_old_des_ede3_cbc_encrypt((i),(o),(l),(k1),(k2),(k3),(iv),(e))
+#  define des_ede3_cfb64_encrypt(i,o,l,k1,k2,k3,iv,n,e)\
+        _ossl_old_des_ede3_cfb64_encrypt((i),(o),(l),(k1),(k2),(k3),(iv),(n),(e))
+#  define des_ede3_ofb64_encrypt(i,o,l,k1,k2,k3,iv,n)\
+        _ossl_old_des_ede3_ofb64_encrypt((i),(o),(l),(k1),(k2),(k3),(iv),(n))
+#  define des_options()\
+        _ossl_old_des_options()
+#  define des_cbc_cksum(i,o,l,k,iv)\
+        _ossl_old_des_cbc_cksum((i),(o),(l),(k),(iv))
+#  define des_cbc_encrypt(i,o,l,k,iv,e)\
+        _ossl_old_des_cbc_encrypt((i),(o),(l),(k),(iv),(e))
+#  define des_ncbc_encrypt(i,o,l,k,iv,e)\
+        _ossl_old_des_ncbc_encrypt((i),(o),(l),(k),(iv),(e))
+#  define des_xcbc_encrypt(i,o,l,k,iv,inw,outw,e)\
+        _ossl_old_des_xcbc_encrypt((i),(o),(l),(k),(iv),(inw),(outw),(e))
+#  define des_cfb_encrypt(i,o,n,l,k,iv,e)\
+        _ossl_old_des_cfb_encrypt((i),(o),(n),(l),(k),(iv),(e))
+#  define des_ecb_encrypt(i,o,k,e)\
+        _ossl_old_des_ecb_encrypt((i),(o),(k),(e))
+#  define des_encrypt(d,k,e)\
+        _ossl_old_des_encrypt((d),(k),(e))
+#  define des_encrypt2(d,k,e)\
+        _ossl_old_des_encrypt2((d),(k),(e))
+#  define des_encrypt3(d,k1,k2,k3)\
+        _ossl_old_des_encrypt3((d),(k1),(k2),(k3))
+#  define des_decrypt3(d,k1,k2,k3)\
+        _ossl_old_des_decrypt3((d),(k1),(k2),(k3))
+#  define des_xwhite_in2out(k,i,o)\
+        _ossl_old_des_xwhite_in2out((k),(i),(o))
+#  define des_enc_read(f,b,l,k,iv)\
+        _ossl_old_des_enc_read((f),(b),(l),(k),(iv))
+#  define des_enc_write(f,b,l,k,iv)\
+        _ossl_old_des_enc_write((f),(b),(l),(k),(iv))
+#  define des_fcrypt(b,s,r)\
+        _ossl_old_des_fcrypt((b),(s),(r))
+#  define des_crypt(b,s)\
+        _ossl_old_des_crypt((b),(s))
+#  if 0
+#   define crypt(b,s)\
+        _ossl_old_crypt((b),(s))
+#  endif
+#  define des_ofb_encrypt(i,o,n,l,k,iv)\
+        _ossl_old_des_ofb_encrypt((i),(o),(n),(l),(k),(iv))
+#  define des_pcbc_encrypt(i,o,l,k,iv,e)\
+        _ossl_old_des_pcbc_encrypt((i),(o),(l),(k),(iv),(e))
+#  define des_quad_cksum(i,o,l,c,s)\
+        _ossl_old_des_quad_cksum((i),(o),(l),(c),(s))
+#  define des_random_seed(k)\
+        _ossl_old_des_random_seed((k))
+#  define des_random_key(r)\
+        _ossl_old_des_random_key((r))
+#  define des_read_password(k,p,v) \
+        _ossl_old_des_read_password((k),(p),(v))
+#  define des_read_2passwords(k1,k2,p,v) \
+        _ossl_old_des_read_2passwords((k1),(k2),(p),(v))
+#  define des_set_odd_parity(k)\
+        _ossl_old_des_set_odd_parity((k))
+#  define des_is_weak_key(k)\
+        _ossl_old_des_is_weak_key((k))
+#  define des_set_key(k,ks)\
+        _ossl_old_des_set_key((k),(ks))
+#  define des_key_sched(k,ks)\
+        _ossl_old_des_key_sched((k),(ks))
+#  define des_string_to_key(s,k)\
+        _ossl_old_des_string_to_key((s),(k))
+#  define des_string_to_2keys(s,k1,k2)\
+        _ossl_old_des_string_to_2keys((s),(k1),(k2))
+#  define des_cfb64_encrypt(i,o,l,ks,iv,n,e)\
+        _ossl_old_des_cfb64_encrypt((i),(o),(l),(ks),(iv),(n),(e))
+#  define des_ofb64_encrypt(i,o,l,ks,iv,n)\
+        _ossl_old_des_ofb64_encrypt((i),(o),(l),(ks),(iv),(n))
+
+#  define des_ecb2_encrypt(i,o,k1,k2,e) \
+        des_ecb3_encrypt((i),(o),(k1),(k2),(k1),(e))
+
+#  define des_ede2_cbc_encrypt(i,o,l,k1,k2,iv,e) \
+        des_ede3_cbc_encrypt((i),(o),(l),(k1),(k2),(k1),(iv),(e))
+
+#  define des_ede2_cfb64_encrypt(i,o,l,k1,k2,iv,n,e) \
+        des_ede3_cfb64_encrypt((i),(o),(l),(k1),(k2),(k1),(iv),(n),(e))
+
+#  define des_ede2_ofb64_encrypt(i,o,l,k1,k2,iv,n) \
+        des_ede3_ofb64_encrypt((i),(o),(l),(k1),(k2),(k1),(iv),(n))
+
+#  define des_check_key DES_check_key
+#  define des_rw_mode DES_rw_mode
+# endif
+
+const char *_ossl_old_des_options(void);
+void _ossl_old_des_ecb3_encrypt(_ossl_old_des_cblock *input,
+                                _ossl_old_des_cblock *output,
+                                _ossl_old_des_key_schedule ks1,
+                                _ossl_old_des_key_schedule ks2,
+                                _ossl_old_des_key_schedule ks3, int enc);
+DES_LONG _ossl_old_des_cbc_cksum(_ossl_old_des_cblock *input,
+                                 _ossl_old_des_cblock *output, long length,
+                                 _ossl_old_des_key_schedule schedule,
+                                 _ossl_old_des_cblock *ivec);
+void _ossl_old_des_cbc_encrypt(_ossl_old_des_cblock *input,
+                               _ossl_old_des_cblock *output, long length,
+                               _ossl_old_des_key_schedule schedule,
+                               _ossl_old_des_cblock *ivec, int enc);
+void _ossl_old_des_ncbc_encrypt(_ossl_old_des_cblock *input,
+                                _ossl_old_des_cblock *output, long length,
+                                _ossl_old_des_key_schedule schedule,
+                                _ossl_old_des_cblock *ivec, int enc);
+void _ossl_old_des_xcbc_encrypt(_ossl_old_des_cblock *input,
+                                _ossl_old_des_cblock *output, long length,
+                                _ossl_old_des_key_schedule schedule,
+                                _ossl_old_des_cblock *ivec,
+                                _ossl_old_des_cblock *inw,
+                                _ossl_old_des_cblock *outw, int enc);
+void _ossl_old_des_cfb_encrypt(unsigned char *in, unsigned char *out,
+                               int numbits, long length,
+                               _ossl_old_des_key_schedule schedule,
+                               _ossl_old_des_cblock *ivec, int enc);
+void _ossl_old_des_ecb_encrypt(_ossl_old_des_cblock *input,
+                               _ossl_old_des_cblock *output,
+                               _ossl_old_des_key_schedule ks, int enc);
+void _ossl_old_des_encrypt(DES_LONG *data, _ossl_old_des_key_schedule ks,
+                           int enc);
+void _ossl_old_des_encrypt2(DES_LONG *data, _ossl_old_des_key_schedule ks,
+                            int enc);
+void _ossl_old_des_encrypt3(DES_LONG *data, _ossl_old_des_key_schedule ks1,
+                            _ossl_old_des_key_schedule ks2,
+                            _ossl_old_des_key_schedule ks3);
+void _ossl_old_des_decrypt3(DES_LONG *data, _ossl_old_des_key_schedule ks1,
+                            _ossl_old_des_key_schedule ks2,
+                            _ossl_old_des_key_schedule ks3);
+void _ossl_old_des_ede3_cbc_encrypt(_ossl_old_des_cblock *input,
+                                    _ossl_old_des_cblock *output, long length,
+                                    _ossl_old_des_key_schedule ks1,
+                                    _ossl_old_des_key_schedule ks2,
+                                    _ossl_old_des_key_schedule ks3,
+                                    _ossl_old_des_cblock *ivec, int enc);
+void _ossl_old_des_ede3_cfb64_encrypt(unsigned char *in, unsigned char *out,
+                                      long length,
+                                      _ossl_old_des_key_schedule ks1,
+                                      _ossl_old_des_key_schedule ks2,
+                                      _ossl_old_des_key_schedule ks3,
+                                      _ossl_old_des_cblock *ivec, int *num,
+                                      int enc);
+void _ossl_old_des_ede3_ofb64_encrypt(unsigned char *in, unsigned char *out,
+                                      long length,
+                                      _ossl_old_des_key_schedule ks1,
+                                      _ossl_old_des_key_schedule ks2,
+                                      _ossl_old_des_key_schedule ks3,
+                                      _ossl_old_des_cblock *ivec, int *num);
+# if 0
+void _ossl_old_des_xwhite_in2out(_ossl_old_des_cblock (*des_key),
+                                 _ossl_old_des_cblock (*in_white),
+                                 _ossl_old_des_cblock (*out_white));
+# endif
+
+int _ossl_old_des_enc_read(int fd, char *buf, int len,
+                           _ossl_old_des_key_schedule sched,
+                           _ossl_old_des_cblock *iv);
+int _ossl_old_des_enc_write(int fd, char *buf, int len,
+                            _ossl_old_des_key_schedule sched,
+                            _ossl_old_des_cblock *iv);
+char *_ossl_old_des_fcrypt(const char *buf, const char *salt, char *ret);
+char *_ossl_old_des_crypt(const char *buf, const char *salt);
+# if !defined(PERL5) && !defined(NeXT)
+char *_ossl_old_crypt(const char *buf, const char *salt);
+# endif
+void _ossl_old_des_ofb_encrypt(unsigned char *in, unsigned char *out,
+                               int numbits, long length,
+                               _ossl_old_des_key_schedule schedule,
+                               _ossl_old_des_cblock *ivec);
+void _ossl_old_des_pcbc_encrypt(_ossl_old_des_cblock *input,
+                                _ossl_old_des_cblock *output, long length,
+                                _ossl_old_des_key_schedule schedule,
+                                _ossl_old_des_cblock *ivec, int enc);
+DES_LONG _ossl_old_des_quad_cksum(_ossl_old_des_cblock *input,
+                                  _ossl_old_des_cblock *output, long length,
+                                  int out_count, _ossl_old_des_cblock *seed);
+void _ossl_old_des_random_seed(_ossl_old_des_cblock key);
+void _ossl_old_des_random_key(_ossl_old_des_cblock ret);
+int _ossl_old_des_read_password(_ossl_old_des_cblock *key, const char *prompt,
+                                int verify);
+int _ossl_old_des_read_2passwords(_ossl_old_des_cblock *key1,
+                                  _ossl_old_des_cblock *key2,
+                                  const char *prompt, int verify);
+void _ossl_old_des_set_odd_parity(_ossl_old_des_cblock *key);
+int _ossl_old_des_is_weak_key(_ossl_old_des_cblock *key);
+int _ossl_old_des_set_key(_ossl_old_des_cblock *key,
+                          _ossl_old_des_key_schedule schedule);
+int _ossl_old_des_key_sched(_ossl_old_des_cblock *key,
+                            _ossl_old_des_key_schedule schedule);
+void _ossl_old_des_string_to_key(char *str, _ossl_old_des_cblock *key);
+void _ossl_old_des_string_to_2keys(char *str, _ossl_old_des_cblock *key1,
+                                   _ossl_old_des_cblock *key2);
+void _ossl_old_des_cfb64_encrypt(unsigned char *in, unsigned char *out,
+                                 long length,
+                                 _ossl_old_des_key_schedule schedule,
+                                 _ossl_old_des_cblock *ivec, int *num,
+                                 int enc);
+void _ossl_old_des_ofb64_encrypt(unsigned char *in, unsigned char *out,
+                                 long length,
+                                 _ossl_old_des_key_schedule schedule,
+                                 _ossl_old_des_cblock *ivec, int *num);
+
+void _ossl_096_des_random_seed(des_cblock *key);
+
+/*
+ * The following definitions provide compatibility with the MIT Kerberos
+ * library. The _ossl_old_des_key_schedule structure is not binary
+ * compatible.
+ */
+
+# define _KERBEROS_DES_H
+
+# define KRBDES_ENCRYPT DES_ENCRYPT
+# define KRBDES_DECRYPT DES_DECRYPT
+
+# ifdef KERBEROS
+#  define ENCRYPT DES_ENCRYPT
+#  define DECRYPT DES_DECRYPT
+# endif
+
+# ifndef NCOMPAT
+#  define C_Block des_cblock
+#  define Key_schedule des_key_schedule
+#  define KEY_SZ DES_KEY_SZ
+#  define string_to_key des_string_to_key
+#  define read_pw_string des_read_pw_string
+#  define random_key des_random_key
+#  define pcbc_encrypt des_pcbc_encrypt
+#  define set_key des_set_key
+#  define key_sched des_key_sched
+#  define ecb_encrypt des_ecb_encrypt
+#  define cbc_encrypt des_cbc_encrypt
+#  define ncbc_encrypt des_ncbc_encrypt
+#  define xcbc_encrypt des_xcbc_encrypt
+#  define cbc_cksum des_cbc_cksum
+#  define quad_cksum des_quad_cksum
+#  define check_parity des_check_key_parity
+# endif
+
+# define des_fixup_key_parity DES_fixup_key_parity
+
+#ifdef  __cplusplus
+}
+#endif
+
+/* for DES_read_pw_string et al */
+# include <openssl/ui_compat.h>
+
+#endif

+ 412 - 0
libssh2/openssl/include/openssl/dh.h

@@ -0,0 +1,412 @@
+/* crypto/dh/dh.h */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * 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 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. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    "This product includes cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``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 AUTHOR OR CONTRIBUTORS 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.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+#ifndef HEADER_DH_H
+# define HEADER_DH_H
+
+# include <openssl/e_os2.h>
+
+# ifdef OPENSSL_NO_DH
+#  error DH is disabled.
+# endif
+
+# ifndef OPENSSL_NO_BIO
+#  include <openssl/bio.h>
+# endif
+# include <openssl/ossl_typ.h>
+# ifndef OPENSSL_NO_DEPRECATED
+#  include <openssl/bn.h>
+# endif
+
+# ifndef OPENSSL_DH_MAX_MODULUS_BITS
+#  define OPENSSL_DH_MAX_MODULUS_BITS    10000
+# endif
+
+# define DH_FLAG_CACHE_MONT_P     0x01
+
+/*
+ * new with 0.9.7h; the built-in DH
+ * implementation now uses constant time
+ * modular exponentiation for secret exponents
+ * by default. This flag causes the
+ * faster variable sliding window method to
+ * be used for all exponents.
+ */
+# define DH_FLAG_NO_EXP_CONSTTIME 0x02
+
+/*
+ * If this flag is set the DH method is FIPS compliant and can be used in
+ * FIPS mode. This is set in the validated module method. If an application
+ * sets this flag in its own methods it is its reposibility to ensure the
+ * result is compliant.
+ */
+
+# define DH_FLAG_FIPS_METHOD                     0x0400
+
+/*
+ * If this flag is set the operations normally disabled in FIPS mode are
+ * permitted it is then the applications responsibility to ensure that the
+ * usage is compliant.
+ */
+
+# define DH_FLAG_NON_FIPS_ALLOW                  0x0400
+
+#ifdef  __cplusplus
+extern "C" {
+#endif
+
+/* Already defined in ossl_typ.h */
+/* typedef struct dh_st DH; */
+/* typedef struct dh_method DH_METHOD; */
+
+struct dh_method {
+    const char *name;
+    /* Methods here */
+    int (*generate_key) (DH *dh);
+    int (*compute_key) (unsigned char *key, const BIGNUM *pub_key, DH *dh);
+    /* Can be null */
+    int (*bn_mod_exp) (const DH *dh, BIGNUM *r, const BIGNUM *a,
+                       const BIGNUM *p, const BIGNUM *m, BN_CTX *ctx,
+                       BN_MONT_CTX *m_ctx);
+    int (*init) (DH *dh);
+    int (*finish) (DH *dh);
+    int flags;
+    char *app_data;
+    /* If this is non-NULL, it will be used to generate parameters */
+    int (*generate_params) (DH *dh, int prime_len, int generator,
+                            BN_GENCB *cb);
+};
+
+struct dh_st {
+    /*
+     * This first argument is used to pick up errors when a DH is passed
+     * instead of a EVP_PKEY
+     */
+    int pad;
+    int version;
+    BIGNUM *p;
+    BIGNUM *g;
+    long length;                /* optional */
+    BIGNUM *pub_key;            /* g^x % p */
+    BIGNUM *priv_key;           /* x */
+    int flags;
+    BN_MONT_CTX *method_mont_p;
+    /* Place holders if we want to do X9.42 DH */
+    BIGNUM *q;
+    BIGNUM *j;
+    unsigned char *seed;
+    int seedlen;
+    BIGNUM *counter;
+    int references;
+    CRYPTO_EX_DATA ex_data;
+    const DH_METHOD *meth;
+    ENGINE *engine;
+};
+
+# define DH_GENERATOR_2          2
+/* #define DH_GENERATOR_3       3 */
+# define DH_GENERATOR_5          5
+
+/* DH_check error codes */
+# define DH_CHECK_P_NOT_PRIME            0x01
+# define DH_CHECK_P_NOT_SAFE_PRIME       0x02
+# define DH_UNABLE_TO_CHECK_GENERATOR    0x04
+# define DH_NOT_SUITABLE_GENERATOR       0x08
+# define DH_CHECK_Q_NOT_PRIME            0x10
+# define DH_CHECK_INVALID_Q_VALUE        0x20
+# define DH_CHECK_INVALID_J_VALUE        0x40
+
+/* DH_check_pub_key error codes */
+# define DH_CHECK_PUBKEY_TOO_SMALL       0x01
+# define DH_CHECK_PUBKEY_TOO_LARGE       0x02
+# define DH_CHECK_PUBKEY_INVALID         0x04
+
+/*
+ * primes p where (p-1)/2 is prime too are called "safe"; we define this for
+ * backward compatibility:
+ */
+# define DH_CHECK_P_NOT_STRONG_PRIME     DH_CHECK_P_NOT_SAFE_PRIME
+
+# define d2i_DHparams_fp(fp,x) \
+    (DH *)ASN1_d2i_fp((char *(*)())DH_new, \
+                      (char *(*)())d2i_DHparams, \
+                      (fp), \
+                      (unsigned char **)(x))
+# define i2d_DHparams_fp(fp,x) \
+    ASN1_i2d_fp(i2d_DHparams,(fp), (unsigned char *)(x))
+# define d2i_DHparams_bio(bp,x) \
+    ASN1_d2i_bio_of(DH, DH_new, d2i_DHparams, bp, x)
+# define i2d_DHparams_bio(bp,x) \
+    ASN1_i2d_bio_of_const(DH,i2d_DHparams,bp,x)
+
+# define d2i_DHxparams_fp(fp,x) \
+    (DH *)ASN1_d2i_fp((char *(*)())DH_new, \
+                      (char *(*)())d2i_DHxparams, \
+                      (fp), \
+                      (unsigned char **)(x))
+# define i2d_DHxparams_fp(fp,x) \
+    ASN1_i2d_fp(i2d_DHxparams,(fp), (unsigned char *)(x))
+# define d2i_DHxparams_bio(bp,x) \
+    ASN1_d2i_bio_of(DH, DH_new, d2i_DHxparams, bp, x)
+# define i2d_DHxparams_bio(bp,x) \
+    ASN1_i2d_bio_of_const(DH, i2d_DHxparams, bp, x)
+
+DH *DHparams_dup(DH *);
+
+const DH_METHOD *DH_OpenSSL(void);
+
+void DH_set_default_method(const DH_METHOD *meth);
+const DH_METHOD *DH_get_default_method(void);
+int DH_set_method(DH *dh, const DH_METHOD *meth);
+DH *DH_new_method(ENGINE *engine);
+
+DH *DH_new(void);
+void DH_free(DH *dh);
+int DH_up_ref(DH *dh);
+int DH_size(const DH *dh);
+int DH_get_ex_new_index(long argl, void *argp, CRYPTO_EX_new *new_func,
+                        CRYPTO_EX_dup *dup_func, CRYPTO_EX_free *free_func);
+int DH_set_ex_data(DH *d, int idx, void *arg);
+void *DH_get_ex_data(DH *d, int idx);
+
+/* Deprecated version */
+# ifndef OPENSSL_NO_DEPRECATED
+DH *DH_generate_parameters(int prime_len, int generator,
+                           void (*callback) (int, int, void *), void *cb_arg);
+# endif                         /* !defined(OPENSSL_NO_DEPRECATED) */
+
+/* New version */
+int DH_generate_parameters_ex(DH *dh, int prime_len, int generator,
+                              BN_GENCB *cb);
+
+int DH_check(const DH *dh, int *codes);
+int DH_check_pub_key(const DH *dh, const BIGNUM *pub_key, int *codes);
+int DH_generate_key(DH *dh);
+int DH_compute_key(unsigned char *key, const BIGNUM *pub_key, DH *dh);
+int DH_compute_key_padded(unsigned char *key, const BIGNUM *pub_key, DH *dh);
+DH *d2i_DHparams(DH **a, const unsigned char **pp, long length);
+int i2d_DHparams(const DH *a, unsigned char **pp);
+DH *d2i_DHxparams(DH **a, const unsigned char **pp, long length);
+int i2d_DHxparams(const DH *a, unsigned char **pp);
+# ifndef OPENSSL_NO_FP_API
+int DHparams_print_fp(FILE *fp, const DH *x);
+# endif
+# ifndef OPENSSL_NO_BIO
+int DHparams_print(BIO *bp, const DH *x);
+# else
+int DHparams_print(char *bp, const DH *x);
+# endif
+
+/* RFC 5114 parameters */
+DH *DH_get_1024_160(void);
+DH *DH_get_2048_224(void);
+DH *DH_get_2048_256(void);
+
+# ifndef OPENSSL_NO_CMS
+/* RFC2631 KDF */
+int DH_KDF_X9_42(unsigned char *out, size_t outlen,
+                 const unsigned char *Z, size_t Zlen,
+                 ASN1_OBJECT *key_oid,
+                 const unsigned char *ukm, size_t ukmlen, const EVP_MD *md);
+# endif
+
+# define EVP_PKEY_CTX_set_dh_paramgen_prime_len(ctx, len) \
+        EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_DH, EVP_PKEY_OP_PARAMGEN, \
+                        EVP_PKEY_CTRL_DH_PARAMGEN_PRIME_LEN, len, NULL)
+
+# define EVP_PKEY_CTX_set_dh_paramgen_subprime_len(ctx, len) \
+        EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_DH, EVP_PKEY_OP_PARAMGEN, \
+                        EVP_PKEY_CTRL_DH_PARAMGEN_SUBPRIME_LEN, len, NULL)
+
+# define EVP_PKEY_CTX_set_dh_paramgen_type(ctx, typ) \
+        EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_DH, EVP_PKEY_OP_PARAMGEN, \
+                        EVP_PKEY_CTRL_DH_PARAMGEN_TYPE, typ, NULL)
+
+# define EVP_PKEY_CTX_set_dh_paramgen_generator(ctx, gen) \
+        EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_DH, EVP_PKEY_OP_PARAMGEN, \
+                        EVP_PKEY_CTRL_DH_PARAMGEN_GENERATOR, gen, NULL)
+
+# define EVP_PKEY_CTX_set_dh_rfc5114(ctx, gen) \
+        EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_DHX, EVP_PKEY_OP_PARAMGEN, \
+                        EVP_PKEY_CTRL_DH_RFC5114, gen, NULL)
+
+# define EVP_PKEY_CTX_set_dhx_rfc5114(ctx, gen) \
+        EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_DHX, EVP_PKEY_OP_PARAMGEN, \
+                        EVP_PKEY_CTRL_DH_RFC5114, gen, NULL)
+
+# define EVP_PKEY_CTX_set_dh_kdf_type(ctx, kdf) \
+        EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_DHX, \
+                                EVP_PKEY_OP_DERIVE, \
+                                EVP_PKEY_CTRL_DH_KDF_TYPE, kdf, NULL)
+
+# define EVP_PKEY_CTX_get_dh_kdf_type(ctx) \
+        EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_DHX, \
+                                EVP_PKEY_OP_DERIVE, \
+                                EVP_PKEY_CTRL_DH_KDF_TYPE, -2, NULL)
+
+# define EVP_PKEY_CTX_set0_dh_kdf_oid(ctx, oid) \
+        EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_DHX, \
+                                EVP_PKEY_OP_DERIVE, \
+                                EVP_PKEY_CTRL_DH_KDF_OID, 0, (void *)oid)
+
+# define EVP_PKEY_CTX_get0_dh_kdf_oid(ctx, poid) \
+        EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_DHX, \
+                                EVP_PKEY_OP_DERIVE, \
+                                EVP_PKEY_CTRL_GET_DH_KDF_OID, 0, (void *)poid)
+
+# define EVP_PKEY_CTX_set_dh_kdf_md(ctx, md) \
+        EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_DHX, \
+                                EVP_PKEY_OP_DERIVE, \
+                                EVP_PKEY_CTRL_DH_KDF_MD, 0, (void *)md)
+
+# define EVP_PKEY_CTX_get_dh_kdf_md(ctx, pmd) \
+        EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_DHX, \
+                                EVP_PKEY_OP_DERIVE, \
+                                EVP_PKEY_CTRL_GET_DH_KDF_MD, 0, (void *)pmd)
+
+# define EVP_PKEY_CTX_set_dh_kdf_outlen(ctx, len) \
+        EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_DHX, \
+                                EVP_PKEY_OP_DERIVE, \
+                                EVP_PKEY_CTRL_DH_KDF_OUTLEN, len, NULL)
+
+# define EVP_PKEY_CTX_get_dh_kdf_outlen(ctx, plen) \
+        EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_DHX, \
+                                EVP_PKEY_OP_DERIVE, \
+                        EVP_PKEY_CTRL_GET_DH_KDF_OUTLEN, 0, (void *)plen)
+
+# define EVP_PKEY_CTX_set0_dh_kdf_ukm(ctx, p, plen) \
+        EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_DHX, \
+                                EVP_PKEY_OP_DERIVE, \
+                                EVP_PKEY_CTRL_DH_KDF_UKM, plen, (void *)p)
+
+# define EVP_PKEY_CTX_get0_dh_kdf_ukm(ctx, p) \
+        EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_DHX, \
+                                EVP_PKEY_OP_DERIVE, \
+                                EVP_PKEY_CTRL_GET_DH_KDF_UKM, 0, (void *)p)
+
+# define EVP_PKEY_CTRL_DH_PARAMGEN_PRIME_LEN     (EVP_PKEY_ALG_CTRL + 1)
+# define EVP_PKEY_CTRL_DH_PARAMGEN_GENERATOR     (EVP_PKEY_ALG_CTRL + 2)
+# define EVP_PKEY_CTRL_DH_RFC5114                (EVP_PKEY_ALG_CTRL + 3)
+# define EVP_PKEY_CTRL_DH_PARAMGEN_SUBPRIME_LEN  (EVP_PKEY_ALG_CTRL + 4)
+# define EVP_PKEY_CTRL_DH_PARAMGEN_TYPE          (EVP_PKEY_ALG_CTRL + 5)
+# define EVP_PKEY_CTRL_DH_KDF_TYPE               (EVP_PKEY_ALG_CTRL + 6)
+# define EVP_PKEY_CTRL_DH_KDF_MD                 (EVP_PKEY_ALG_CTRL + 7)
+# define EVP_PKEY_CTRL_GET_DH_KDF_MD             (EVP_PKEY_ALG_CTRL + 8)
+# define EVP_PKEY_CTRL_DH_KDF_OUTLEN             (EVP_PKEY_ALG_CTRL + 9)
+# define EVP_PKEY_CTRL_GET_DH_KDF_OUTLEN         (EVP_PKEY_ALG_CTRL + 10)
+# define EVP_PKEY_CTRL_DH_KDF_UKM                (EVP_PKEY_ALG_CTRL + 11)
+# define EVP_PKEY_CTRL_GET_DH_KDF_UKM            (EVP_PKEY_ALG_CTRL + 12)
+# define EVP_PKEY_CTRL_DH_KDF_OID                (EVP_PKEY_ALG_CTRL + 13)
+# define EVP_PKEY_CTRL_GET_DH_KDF_OID            (EVP_PKEY_ALG_CTRL + 14)
+
+/* KDF types */
+# define EVP_PKEY_DH_KDF_NONE                            1
+# define EVP_PKEY_DH_KDF_X9_42                           2
+
+/* BEGIN ERROR CODES */
+/*
+ * The following lines are auto generated by the script mkerr.pl. Any changes
+ * made after this point may be overwritten when the script is next run.
+ */
+void ERR_load_DH_strings(void);
+
+/* Error codes for the DH functions. */
+
+/* Function codes. */
+# define DH_F_COMPUTE_KEY                                 102
+# define DH_F_DHPARAMS_PRINT_FP                           101
+# define DH_F_DH_BUILTIN_GENPARAMS                        106
+# define DH_F_DH_CMS_DECRYPT                              117
+# define DH_F_DH_CMS_SET_PEERKEY                          118
+# define DH_F_DH_CMS_SET_SHARED_INFO                      119
+# define DH_F_DH_COMPUTE_KEY                              114
+# define DH_F_DH_GENERATE_KEY                             115
+# define DH_F_DH_GENERATE_PARAMETERS_EX                   116
+# define DH_F_DH_NEW_METHOD                               105
+# define DH_F_DH_PARAM_DECODE                             107
+# define DH_F_DH_PRIV_DECODE                              110
+# define DH_F_DH_PRIV_ENCODE                              111
+# define DH_F_DH_PUB_DECODE                               108
+# define DH_F_DH_PUB_ENCODE                               109
+# define DH_F_DO_DH_PRINT                                 100
+# define DH_F_GENERATE_KEY                                103
+# define DH_F_GENERATE_PARAMETERS                         104
+# define DH_F_PKEY_DH_DERIVE                              112
+# define DH_F_PKEY_DH_KEYGEN                              113
+
+/* Reason codes. */
+# define DH_R_BAD_GENERATOR                               101
+# define DH_R_BN_DECODE_ERROR                             109
+# define DH_R_BN_ERROR                                    106
+# define DH_R_DECODE_ERROR                                104
+# define DH_R_INVALID_PUBKEY                              102
+# define DH_R_KDF_PARAMETER_ERROR                         112
+# define DH_R_KEYS_NOT_SET                                108
+# define DH_R_KEY_SIZE_TOO_SMALL                          110
+# define DH_R_MODULUS_TOO_LARGE                           103
+# define DH_R_NON_FIPS_METHOD                             111
+# define DH_R_NO_PARAMETERS_SET                           107
+# define DH_R_NO_PRIVATE_VALUE                            100
+# define DH_R_PARAMETER_ENCODING_ERROR                    105
+# define DH_R_PEER_KEY_ERROR                              113
+# define DH_R_SHARED_INFO_ERROR                           114
+
+#ifdef  __cplusplus
+}
+#endif
+#endif

+ 335 - 0
libssh2/openssl/include/openssl/dsa.h

@@ -0,0 +1,335 @@
+/* crypto/dsa/dsa.h */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * 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 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. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    "This product includes cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``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 AUTHOR OR CONTRIBUTORS 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.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+/*
+ * The DSS routines are based on patches supplied by
+ * Steven Schoch <schoch@sheba.arc.nasa.gov>.  He basically did the
+ * work and I have just tweaked them a little to fit into my
+ * stylistic vision for SSLeay :-) */
+
+#ifndef HEADER_DSA_H
+# define HEADER_DSA_H
+
+# include <openssl/e_os2.h>
+
+# ifdef OPENSSL_NO_DSA
+#  error DSA is disabled.
+# endif
+
+# ifndef OPENSSL_NO_BIO
+#  include <openssl/bio.h>
+# endif
+# include <openssl/crypto.h>
+# include <openssl/ossl_typ.h>
+
+# ifndef OPENSSL_NO_DEPRECATED
+#  include <openssl/bn.h>
+#  ifndef OPENSSL_NO_DH
+#   include <openssl/dh.h>
+#  endif
+# endif
+
+# ifndef OPENSSL_DSA_MAX_MODULUS_BITS
+#  define OPENSSL_DSA_MAX_MODULUS_BITS   10000
+# endif
+
+# define DSA_FLAG_CACHE_MONT_P   0x01
+/*
+ * new with 0.9.7h; the built-in DSA implementation now uses constant time
+ * modular exponentiation for secret exponents by default. This flag causes
+ * the faster variable sliding window method to be used for all exponents.
+ */
+# define DSA_FLAG_NO_EXP_CONSTTIME       0x02
+
+/*
+ * If this flag is set the DSA method is FIPS compliant and can be used in
+ * FIPS mode. This is set in the validated module method. If an application
+ * sets this flag in its own methods it is its reposibility to ensure the
+ * result is compliant.
+ */
+
+# define DSA_FLAG_FIPS_METHOD                    0x0400
+
+/*
+ * If this flag is set the operations normally disabled in FIPS mode are
+ * permitted it is then the applications responsibility to ensure that the
+ * usage is compliant.
+ */
+
+# define DSA_FLAG_NON_FIPS_ALLOW                 0x0400
+
+#ifdef  __cplusplus
+extern "C" {
+#endif
+
+/* Already defined in ossl_typ.h */
+/* typedef struct dsa_st DSA; */
+/* typedef struct dsa_method DSA_METHOD; */
+
+typedef struct DSA_SIG_st {
+    BIGNUM *r;
+    BIGNUM *s;
+} DSA_SIG;
+
+struct dsa_method {
+    const char *name;
+    DSA_SIG *(*dsa_do_sign) (const unsigned char *dgst, int dlen, DSA *dsa);
+    int (*dsa_sign_setup) (DSA *dsa, BN_CTX *ctx_in, BIGNUM **kinvp,
+                           BIGNUM **rp);
+    int (*dsa_do_verify) (const unsigned char *dgst, int dgst_len,
+                          DSA_SIG *sig, DSA *dsa);
+    int (*dsa_mod_exp) (DSA *dsa, BIGNUM *rr, BIGNUM *a1, BIGNUM *p1,
+                        BIGNUM *a2, BIGNUM *p2, BIGNUM *m, BN_CTX *ctx,
+                        BN_MONT_CTX *in_mont);
+    /* Can be null */
+    int (*bn_mod_exp) (DSA *dsa, BIGNUM *r, BIGNUM *a, const BIGNUM *p,
+                       const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *m_ctx);
+    int (*init) (DSA *dsa);
+    int (*finish) (DSA *dsa);
+    int flags;
+    char *app_data;
+    /* If this is non-NULL, it is used to generate DSA parameters */
+    int (*dsa_paramgen) (DSA *dsa, int bits,
+                         const unsigned char *seed, int seed_len,
+                         int *counter_ret, unsigned long *h_ret,
+                         BN_GENCB *cb);
+    /* If this is non-NULL, it is used to generate DSA keys */
+    int (*dsa_keygen) (DSA *dsa);
+};
+
+struct dsa_st {
+    /*
+     * This first variable is used to pick up errors where a DSA is passed
+     * instead of of a EVP_PKEY
+     */
+    int pad;
+    long version;
+    int write_params;
+    BIGNUM *p;
+    BIGNUM *q;                  /* == 20 */
+    BIGNUM *g;
+    BIGNUM *pub_key;            /* y public key */
+    BIGNUM *priv_key;           /* x private key */
+    BIGNUM *kinv;               /* Signing pre-calc */
+    BIGNUM *r;                  /* Signing pre-calc */
+    int flags;
+    /* Normally used to cache montgomery values */
+    BN_MONT_CTX *method_mont_p;
+    int references;
+    CRYPTO_EX_DATA ex_data;
+    const DSA_METHOD *meth;
+    /* functional reference if 'meth' is ENGINE-provided */
+    ENGINE *engine;
+};
+
+# define d2i_DSAparams_fp(fp,x) (DSA *)ASN1_d2i_fp((char *(*)())DSA_new, \
+                (char *(*)())d2i_DSAparams,(fp),(unsigned char **)(x))
+# define i2d_DSAparams_fp(fp,x) ASN1_i2d_fp(i2d_DSAparams,(fp), \
+                (unsigned char *)(x))
+# define d2i_DSAparams_bio(bp,x) ASN1_d2i_bio_of(DSA,DSA_new,d2i_DSAparams,bp,x)
+# define i2d_DSAparams_bio(bp,x) ASN1_i2d_bio_of_const(DSA,i2d_DSAparams,bp,x)
+
+DSA *DSAparams_dup(DSA *x);
+DSA_SIG *DSA_SIG_new(void);
+void DSA_SIG_free(DSA_SIG *a);
+int i2d_DSA_SIG(const DSA_SIG *a, unsigned char **pp);
+DSA_SIG *d2i_DSA_SIG(DSA_SIG **v, const unsigned char **pp, long length);
+
+DSA_SIG *DSA_do_sign(const unsigned char *dgst, int dlen, DSA *dsa);
+int DSA_do_verify(const unsigned char *dgst, int dgst_len,
+                  DSA_SIG *sig, DSA *dsa);
+
+const DSA_METHOD *DSA_OpenSSL(void);
+
+void DSA_set_default_method(const DSA_METHOD *);
+const DSA_METHOD *DSA_get_default_method(void);
+int DSA_set_method(DSA *dsa, const DSA_METHOD *);
+
+DSA *DSA_new(void);
+DSA *DSA_new_method(ENGINE *engine);
+void DSA_free(DSA *r);
+/* "up" the DSA object's reference count */
+int DSA_up_ref(DSA *r);
+int DSA_size(const DSA *);
+        /* next 4 return -1 on error */
+int DSA_sign_setup(DSA *dsa, BN_CTX *ctx_in, BIGNUM **kinvp, BIGNUM **rp);
+int DSA_sign(int type, const unsigned char *dgst, int dlen,
+             unsigned char *sig, unsigned int *siglen, DSA *dsa);
+int DSA_verify(int type, const unsigned char *dgst, int dgst_len,
+               const unsigned char *sigbuf, int siglen, DSA *dsa);
+int DSA_get_ex_new_index(long argl, void *argp, CRYPTO_EX_new *new_func,
+                         CRYPTO_EX_dup *dup_func, CRYPTO_EX_free *free_func);
+int DSA_set_ex_data(DSA *d, int idx, void *arg);
+void *DSA_get_ex_data(DSA *d, int idx);
+
+DSA *d2i_DSAPublicKey(DSA **a, const unsigned char **pp, long length);
+DSA *d2i_DSAPrivateKey(DSA **a, const unsigned char **pp, long length);
+DSA *d2i_DSAparams(DSA **a, const unsigned char **pp, long length);
+
+/* Deprecated version */
+# ifndef OPENSSL_NO_DEPRECATED
+DSA *DSA_generate_parameters(int bits,
+                             unsigned char *seed, int seed_len,
+                             int *counter_ret, unsigned long *h_ret, void
+                              (*callback) (int, int, void *), void *cb_arg);
+# endif                         /* !defined(OPENSSL_NO_DEPRECATED) */
+
+/* New version */
+int DSA_generate_parameters_ex(DSA *dsa, int bits,
+                               const unsigned char *seed, int seed_len,
+                               int *counter_ret, unsigned long *h_ret,
+                               BN_GENCB *cb);
+
+int DSA_generate_key(DSA *a);
+int i2d_DSAPublicKey(const DSA *a, unsigned char **pp);
+int i2d_DSAPrivateKey(const DSA *a, unsigned char **pp);
+int i2d_DSAparams(const DSA *a, unsigned char **pp);
+
+# ifndef OPENSSL_NO_BIO
+int DSAparams_print(BIO *bp, const DSA *x);
+int DSA_print(BIO *bp, const DSA *x, int off);
+# endif
+# ifndef OPENSSL_NO_FP_API
+int DSAparams_print_fp(FILE *fp, const DSA *x);
+int DSA_print_fp(FILE *bp, const DSA *x, int off);
+# endif
+
+# define DSS_prime_checks 64
+/*
+ * Primality test according to FIPS PUB 186-4, Appendix C.3. Since we only
+ * have one value here we set the number of checks to 64 which is the 128 bit
+ * security level that is the highest level and valid for creating a 3072 bit
+ * DSA key.
+ */
+# define DSA_is_prime(n, callback, cb_arg) \
+        BN_is_prime(n, DSS_prime_checks, callback, NULL, cb_arg)
+
+# ifndef OPENSSL_NO_DH
+/*
+ * Convert DSA structure (key or just parameters) into DH structure (be
+ * careful to avoid small subgroup attacks when using this!)
+ */
+DH *DSA_dup_DH(const DSA *r);
+# endif
+
+# define EVP_PKEY_CTX_set_dsa_paramgen_bits(ctx, nbits) \
+        EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_DSA, EVP_PKEY_OP_PARAMGEN, \
+                                EVP_PKEY_CTRL_DSA_PARAMGEN_BITS, nbits, NULL)
+
+# define EVP_PKEY_CTRL_DSA_PARAMGEN_BITS         (EVP_PKEY_ALG_CTRL + 1)
+# define EVP_PKEY_CTRL_DSA_PARAMGEN_Q_BITS       (EVP_PKEY_ALG_CTRL + 2)
+# define EVP_PKEY_CTRL_DSA_PARAMGEN_MD           (EVP_PKEY_ALG_CTRL + 3)
+
+/* BEGIN ERROR CODES */
+/*
+ * The following lines are auto generated by the script mkerr.pl. Any changes
+ * made after this point may be overwritten when the script is next run.
+ */
+void ERR_load_DSA_strings(void);
+
+/* Error codes for the DSA functions. */
+
+/* Function codes. */
+# define DSA_F_D2I_DSA_SIG                                110
+# define DSA_F_DO_DSA_PRINT                               104
+# define DSA_F_DSAPARAMS_PRINT                            100
+# define DSA_F_DSAPARAMS_PRINT_FP                         101
+# define DSA_F_DSA_BUILTIN_PARAMGEN2                      126
+# define DSA_F_DSA_DO_SIGN                                112
+# define DSA_F_DSA_DO_VERIFY                              113
+# define DSA_F_DSA_GENERATE_KEY                           124
+# define DSA_F_DSA_GENERATE_PARAMETERS_EX                 123
+# define DSA_F_DSA_NEW_METHOD                             103
+# define DSA_F_DSA_PARAM_DECODE                           119
+# define DSA_F_DSA_PRINT_FP                               105
+# define DSA_F_DSA_PRIV_DECODE                            115
+# define DSA_F_DSA_PRIV_ENCODE                            116
+# define DSA_F_DSA_PUB_DECODE                             117
+# define DSA_F_DSA_PUB_ENCODE                             118
+# define DSA_F_DSA_SIGN                                   106
+# define DSA_F_DSA_SIGN_SETUP                             107
+# define DSA_F_DSA_SIG_NEW                                109
+# define DSA_F_DSA_SIG_PRINT                              125
+# define DSA_F_DSA_VERIFY                                 108
+# define DSA_F_I2D_DSA_SIG                                111
+# define DSA_F_OLD_DSA_PRIV_DECODE                        122
+# define DSA_F_PKEY_DSA_CTRL                              120
+# define DSA_F_PKEY_DSA_CTRL_STR                          127
+# define DSA_F_PKEY_DSA_KEYGEN                            121
+# define DSA_F_SIG_CB                                     114
+
+/* Reason codes. */
+# define DSA_R_BAD_Q_VALUE                                102
+# define DSA_R_BN_DECODE_ERROR                            108
+# define DSA_R_BN_ERROR                                   109
+# define DSA_R_DATA_TOO_LARGE_FOR_KEY_SIZE                100
+# define DSA_R_DECODE_ERROR                               104
+# define DSA_R_INVALID_DIGEST_TYPE                        106
+# define DSA_R_INVALID_PARAMETERS                         112
+# define DSA_R_MISSING_PARAMETERS                         101
+# define DSA_R_MODULUS_TOO_LARGE                          103
+# define DSA_R_NEED_NEW_SETUP_VALUES                      110
+# define DSA_R_NON_FIPS_DSA_METHOD                        111
+# define DSA_R_NO_PARAMETERS_SET                          107
+# define DSA_R_PARAMETER_ENCODING_ERROR                   105
+# define DSA_R_Q_NOT_PRIME                                113
+
+#ifdef  __cplusplus
+}
+#endif
+#endif

+ 451 - 0
libssh2/openssl/include/openssl/dso.h

@@ -0,0 +1,451 @@
+/* dso.h */
+/*
+ * Written by Geoff Thorpe (geoff@geoffthorpe.net) for the OpenSSL project
+ * 2000.
+ */
+/* ====================================================================
+ * Copyright (c) 2000 The OpenSSL 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. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    licensing@OpenSSL.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED 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 OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS 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.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com).  This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+
+#ifndef HEADER_DSO_H
+# define HEADER_DSO_H
+
+# include <openssl/crypto.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* These values are used as commands to DSO_ctrl() */
+# define DSO_CTRL_GET_FLAGS      1
+# define DSO_CTRL_SET_FLAGS      2
+# define DSO_CTRL_OR_FLAGS       3
+
+/*
+ * By default, DSO_load() will translate the provided filename into a form
+ * typical for the platform (more specifically the DSO_METHOD) using the
+ * dso_name_converter function of the method. Eg. win32 will transform "blah"
+ * into "blah.dll", and dlfcn will transform it into "libblah.so". The
+ * behaviour can be overriden by setting the name_converter callback in the
+ * DSO object (using DSO_set_name_converter()). This callback could even
+ * utilise the DSO_METHOD's converter too if it only wants to override
+ * behaviour for one or two possible DSO methods. However, the following flag
+ * can be set in a DSO to prevent *any* native name-translation at all - eg.
+ * if the caller has prompted the user for a path to a driver library so the
+ * filename should be interpreted as-is.
+ */
+# define DSO_FLAG_NO_NAME_TRANSLATION            0x01
+/*
+ * An extra flag to give if only the extension should be added as
+ * translation.  This is obviously only of importance on Unix and other
+ * operating systems where the translation also may prefix the name with
+ * something, like 'lib', and ignored everywhere else. This flag is also
+ * ignored if DSO_FLAG_NO_NAME_TRANSLATION is used at the same time.
+ */
+# define DSO_FLAG_NAME_TRANSLATION_EXT_ONLY      0x02
+
+/*
+ * The following flag controls the translation of symbol names to upper case.
+ * This is currently only being implemented for OpenVMS.
+ */
+# define DSO_FLAG_UPCASE_SYMBOL                  0x10
+
+/*
+ * This flag loads the library with public symbols. Meaning: The exported
+ * symbols of this library are public to all libraries loaded after this
+ * library. At the moment only implemented in unix.
+ */
+# define DSO_FLAG_GLOBAL_SYMBOLS                 0x20
+
+typedef void (*DSO_FUNC_TYPE) (void);
+
+typedef struct dso_st DSO;
+
+/*
+ * The function prototype used for method functions (or caller-provided
+ * callbacks) that transform filenames. They are passed a DSO structure
+ * pointer (or NULL if they are to be used independantly of a DSO object) and
+ * a filename to transform. They should either return NULL (if there is an
+ * error condition) or a newly allocated string containing the transformed
+ * form that the caller will need to free with OPENSSL_free() when done.
+ */
+typedef char *(*DSO_NAME_CONVERTER_FUNC)(DSO *, const char *);
+/*
+ * The function prototype used for method functions (or caller-provided
+ * callbacks) that merge two file specifications. They are passed a DSO
+ * structure pointer (or NULL if they are to be used independantly of a DSO
+ * object) and two file specifications to merge. They should either return
+ * NULL (if there is an error condition) or a newly allocated string
+ * containing the result of merging that the caller will need to free with
+ * OPENSSL_free() when done. Here, merging means that bits and pieces are
+ * taken from each of the file specifications and added together in whatever
+ * fashion that is sensible for the DSO method in question.  The only rule
+ * that really applies is that if the two specification contain pieces of the
+ * same type, the copy from the first string takes priority.  One could see
+ * it as the first specification is the one given by the user and the second
+ * being a bunch of defaults to add on if they're missing in the first.
+ */
+typedef char *(*DSO_MERGER_FUNC)(DSO *, const char *, const char *);
+
+typedef struct dso_meth_st {
+    const char *name;
+    /*
+     * Loads a shared library, NB: new DSO_METHODs must ensure that a
+     * successful load populates the loaded_filename field, and likewise a
+     * successful unload OPENSSL_frees and NULLs it out.
+     */
+    int (*dso_load) (DSO *dso);
+    /* Unloads a shared library */
+    int (*dso_unload) (DSO *dso);
+    /* Binds a variable */
+    void *(*dso_bind_var) (DSO *dso, const char *symname);
+    /*
+     * Binds a function - assumes a return type of DSO_FUNC_TYPE. This should
+     * be cast to the real function prototype by the caller. Platforms that
+     * don't have compatible representations for different prototypes (this
+     * is possible within ANSI C) are highly unlikely to have shared
+     * libraries at all, let alone a DSO_METHOD implemented for them.
+     */
+    DSO_FUNC_TYPE (*dso_bind_func) (DSO *dso, const char *symname);
+/* I don't think this would actually be used in any circumstances. */
+# if 0
+    /* Unbinds a variable */
+    int (*dso_unbind_var) (DSO *dso, char *symname, void *symptr);
+    /* Unbinds a function */
+    int (*dso_unbind_func) (DSO *dso, char *symname, DSO_FUNC_TYPE symptr);
+# endif
+    /*
+     * The generic (yuck) "ctrl()" function. NB: Negative return values
+     * (rather than zero) indicate errors.
+     */
+    long (*dso_ctrl) (DSO *dso, int cmd, long larg, void *parg);
+    /*
+     * The default DSO_METHOD-specific function for converting filenames to a
+     * canonical native form.
+     */
+    DSO_NAME_CONVERTER_FUNC dso_name_converter;
+    /*
+     * The default DSO_METHOD-specific function for converting filenames to a
+     * canonical native form.
+     */
+    DSO_MERGER_FUNC dso_merger;
+    /* [De]Initialisation handlers. */
+    int (*init) (DSO *dso);
+    int (*finish) (DSO *dso);
+    /* Return pathname of the module containing location */
+    int (*pathbyaddr) (void *addr, char *path, int sz);
+    /* Perform global symbol lookup, i.e. among *all* modules */
+    void *(*globallookup) (const char *symname);
+} DSO_METHOD;
+
+/**********************************************************************/
+/* The low-level handle type used to refer to a loaded shared library */
+
+struct dso_st {
+    DSO_METHOD *meth;
+    /*
+     * Standard dlopen uses a (void *). Win32 uses a HANDLE. VMS doesn't use
+     * anything but will need to cache the filename for use in the dso_bind
+     * handler. All in all, let each method control its own destiny.
+     * "Handles" and such go in a STACK.
+     */
+    STACK_OF(void) *meth_data;
+    int references;
+    int flags;
+    /*
+     * For use by applications etc ... use this for your bits'n'pieces, don't
+     * touch meth_data!
+     */
+    CRYPTO_EX_DATA ex_data;
+    /*
+     * If this callback function pointer is set to non-NULL, then it will be
+     * used in DSO_load() in place of meth->dso_name_converter. NB: This
+     * should normally set using DSO_set_name_converter().
+     */
+    DSO_NAME_CONVERTER_FUNC name_converter;
+    /*
+     * If this callback function pointer is set to non-NULL, then it will be
+     * used in DSO_load() in place of meth->dso_merger. NB: This should
+     * normally set using DSO_set_merger().
+     */
+    DSO_MERGER_FUNC merger;
+    /*
+     * This is populated with (a copy of) the platform-independant filename
+     * used for this DSO.
+     */
+    char *filename;
+    /*
+     * This is populated with (a copy of) the translated filename by which
+     * the DSO was actually loaded. It is NULL iff the DSO is not currently
+     * loaded. NB: This is here because the filename translation process may
+     * involve a callback being invoked more than once not only to convert to
+     * a platform-specific form, but also to try different filenames in the
+     * process of trying to perform a load. As such, this variable can be
+     * used to indicate (a) whether this DSO structure corresponds to a
+     * loaded library or not, and (b) the filename with which it was actually
+     * loaded.
+     */
+    char *loaded_filename;
+};
+
+DSO *DSO_new(void);
+DSO *DSO_new_method(DSO_METHOD *method);
+int DSO_free(DSO *dso);
+int DSO_flags(DSO *dso);
+int DSO_up_ref(DSO *dso);
+long DSO_ctrl(DSO *dso, int cmd, long larg, void *parg);
+
+/*
+ * This function sets the DSO's name_converter callback. If it is non-NULL,
+ * then it will be used instead of the associated DSO_METHOD's function. If
+ * oldcb is non-NULL then it is set to the function pointer value being
+ * replaced. Return value is non-zero for success.
+ */
+int DSO_set_name_converter(DSO *dso, DSO_NAME_CONVERTER_FUNC cb,
+                           DSO_NAME_CONVERTER_FUNC *oldcb);
+/*
+ * These functions can be used to get/set the platform-independant filename
+ * used for a DSO. NB: set will fail if the DSO is already loaded.
+ */
+const char *DSO_get_filename(DSO *dso);
+int DSO_set_filename(DSO *dso, const char *filename);
+/*
+ * This function will invoke the DSO's name_converter callback to translate a
+ * filename, or if the callback isn't set it will instead use the DSO_METHOD's
+ * converter. If "filename" is NULL, the "filename" in the DSO itself will be
+ * used. If the DSO_FLAG_NO_NAME_TRANSLATION flag is set, then the filename is
+ * simply duplicated. NB: This function is usually called from within a
+ * DSO_METHOD during the processing of a DSO_load() call, and is exposed so
+ * that caller-created DSO_METHODs can do the same thing. A non-NULL return
+ * value will need to be OPENSSL_free()'d.
+ */
+char *DSO_convert_filename(DSO *dso, const char *filename);
+/*
+ * This function will invoke the DSO's merger callback to merge two file
+ * specifications, or if the callback isn't set it will instead use the
+ * DSO_METHOD's merger.  A non-NULL return value will need to be
+ * OPENSSL_free()'d.
+ */
+char *DSO_merge(DSO *dso, const char *filespec1, const char *filespec2);
+/*
+ * If the DSO is currently loaded, this returns the filename that it was
+ * loaded under, otherwise it returns NULL. So it is also useful as a test as
+ * to whether the DSO is currently loaded. NB: This will not necessarily
+ * return the same value as DSO_convert_filename(dso, dso->filename), because
+ * the DSO_METHOD's load function may have tried a variety of filenames (with
+ * and/or without the aid of the converters) before settling on the one it
+ * actually loaded.
+ */
+const char *DSO_get_loaded_filename(DSO *dso);
+
+void DSO_set_default_method(DSO_METHOD *meth);
+DSO_METHOD *DSO_get_default_method(void);
+DSO_METHOD *DSO_get_method(DSO *dso);
+DSO_METHOD *DSO_set_method(DSO *dso, DSO_METHOD *meth);
+
+/*
+ * The all-singing all-dancing load function, you normally pass NULL for the
+ * first and third parameters. Use DSO_up and DSO_free for subsequent
+ * reference count handling. Any flags passed in will be set in the
+ * constructed DSO after its init() function but before the load operation.
+ * If 'dso' is non-NULL, 'flags' is ignored.
+ */
+DSO *DSO_load(DSO *dso, const char *filename, DSO_METHOD *meth, int flags);
+
+/* This function binds to a variable inside a shared library. */
+void *DSO_bind_var(DSO *dso, const char *symname);
+
+/* This function binds to a function inside a shared library. */
+DSO_FUNC_TYPE DSO_bind_func(DSO *dso, const char *symname);
+
+/*
+ * This method is the default, but will beg, borrow, or steal whatever method
+ * should be the default on any particular platform (including
+ * DSO_METH_null() if necessary).
+ */
+DSO_METHOD *DSO_METHOD_openssl(void);
+
+/*
+ * This method is defined for all platforms - if a platform has no DSO
+ * support then this will be the only method!
+ */
+DSO_METHOD *DSO_METHOD_null(void);
+
+/*
+ * If DSO_DLFCN is defined, the standard dlfcn.h-style functions (dlopen,
+ * dlclose, dlsym, etc) will be used and incorporated into this method. If
+ * not, this method will return NULL.
+ */
+DSO_METHOD *DSO_METHOD_dlfcn(void);
+
+/*
+ * If DSO_DL is defined, the standard dl.h-style functions (shl_load,
+ * shl_unload, shl_findsym, etc) will be used and incorporated into this
+ * method. If not, this method will return NULL.
+ */
+DSO_METHOD *DSO_METHOD_dl(void);
+
+/* If WIN32 is defined, use DLLs. If not, return NULL. */
+DSO_METHOD *DSO_METHOD_win32(void);
+
+/* If VMS is defined, use shared images. If not, return NULL. */
+DSO_METHOD *DSO_METHOD_vms(void);
+
+/*
+ * This function writes null-terminated pathname of DSO module containing
+ * 'addr' into 'sz' large caller-provided 'path' and returns the number of
+ * characters [including trailing zero] written to it. If 'sz' is 0 or
+ * negative, 'path' is ignored and required amount of charachers [including
+ * trailing zero] to accomodate pathname is returned. If 'addr' is NULL, then
+ * pathname of cryptolib itself is returned. Negative or zero return value
+ * denotes error.
+ */
+int DSO_pathbyaddr(void *addr, char *path, int sz);
+
+/*
+ * This function should be used with caution! It looks up symbols in *all*
+ * loaded modules and if module gets unloaded by somebody else attempt to
+ * dereference the pointer is doomed to have fatal consequences. Primary
+ * usage for this function is to probe *core* system functionality, e.g.
+ * check if getnameinfo(3) is available at run-time without bothering about
+ * OS-specific details such as libc.so.versioning or where does it actually
+ * reside: in libc itself or libsocket.
+ */
+void *DSO_global_lookup(const char *name);
+
+/* If BeOS is defined, use shared images. If not, return NULL. */
+DSO_METHOD *DSO_METHOD_beos(void);
+
+/* BEGIN ERROR CODES */
+/*
+ * The following lines are auto generated by the script mkerr.pl. Any changes
+ * made after this point may be overwritten when the script is next run.
+ */
+void ERR_load_DSO_strings(void);
+
+/* Error codes for the DSO functions. */
+
+/* Function codes. */
+# define DSO_F_BEOS_BIND_FUNC                             144
+# define DSO_F_BEOS_BIND_VAR                              145
+# define DSO_F_BEOS_LOAD                                  146
+# define DSO_F_BEOS_NAME_CONVERTER                        147
+# define DSO_F_BEOS_UNLOAD                                148
+# define DSO_F_DLFCN_BIND_FUNC                            100
+# define DSO_F_DLFCN_BIND_VAR                             101
+# define DSO_F_DLFCN_LOAD                                 102
+# define DSO_F_DLFCN_MERGER                               130
+# define DSO_F_DLFCN_NAME_CONVERTER                       123
+# define DSO_F_DLFCN_UNLOAD                               103
+# define DSO_F_DL_BIND_FUNC                               104
+# define DSO_F_DL_BIND_VAR                                105
+# define DSO_F_DL_LOAD                                    106
+# define DSO_F_DL_MERGER                                  131
+# define DSO_F_DL_NAME_CONVERTER                          124
+# define DSO_F_DL_UNLOAD                                  107
+# define DSO_F_DSO_BIND_FUNC                              108
+# define DSO_F_DSO_BIND_VAR                               109
+# define DSO_F_DSO_CONVERT_FILENAME                       126
+# define DSO_F_DSO_CTRL                                   110
+# define DSO_F_DSO_FREE                                   111
+# define DSO_F_DSO_GET_FILENAME                           127
+# define DSO_F_DSO_GET_LOADED_FILENAME                    128
+# define DSO_F_DSO_GLOBAL_LOOKUP                          139
+# define DSO_F_DSO_LOAD                                   112
+# define DSO_F_DSO_MERGE                                  132
+# define DSO_F_DSO_NEW_METHOD                             113
+# define DSO_F_DSO_PATHBYADDR                             140
+# define DSO_F_DSO_SET_FILENAME                           129
+# define DSO_F_DSO_SET_NAME_CONVERTER                     122
+# define DSO_F_DSO_UP_REF                                 114
+# define DSO_F_GLOBAL_LOOKUP_FUNC                         138
+# define DSO_F_PATHBYADDR                                 137
+# define DSO_F_VMS_BIND_SYM                               115
+# define DSO_F_VMS_LOAD                                   116
+# define DSO_F_VMS_MERGER                                 133
+# define DSO_F_VMS_UNLOAD                                 117
+# define DSO_F_WIN32_BIND_FUNC                            118
+# define DSO_F_WIN32_BIND_VAR                             119
+# define DSO_F_WIN32_GLOBALLOOKUP                         142
+# define DSO_F_WIN32_GLOBALLOOKUP_FUNC                    143
+# define DSO_F_WIN32_JOINER                               135
+# define DSO_F_WIN32_LOAD                                 120
+# define DSO_F_WIN32_MERGER                               134
+# define DSO_F_WIN32_NAME_CONVERTER                       125
+# define DSO_F_WIN32_PATHBYADDR                           141
+# define DSO_F_WIN32_SPLITTER                             136
+# define DSO_F_WIN32_UNLOAD                               121
+
+/* Reason codes. */
+# define DSO_R_CTRL_FAILED                                100
+# define DSO_R_DSO_ALREADY_LOADED                         110
+# define DSO_R_EMPTY_FILE_STRUCTURE                       113
+# define DSO_R_FAILURE                                    114
+# define DSO_R_FILENAME_TOO_BIG                           101
+# define DSO_R_FINISH_FAILED                              102
+# define DSO_R_INCORRECT_FILE_SYNTAX                      115
+# define DSO_R_LOAD_FAILED                                103
+# define DSO_R_NAME_TRANSLATION_FAILED                    109
+# define DSO_R_NO_FILENAME                                111
+# define DSO_R_NO_FILE_SPECIFICATION                      116
+# define DSO_R_NULL_HANDLE                                104
+# define DSO_R_SET_FILENAME_FAILED                        112
+# define DSO_R_STACK_ERROR                                105
+# define DSO_R_SYM_FAILURE                                106
+# define DSO_R_UNLOAD_FAILED                              107
+# define DSO_R_UNSUPPORTED                                108
+
+#ifdef  __cplusplus
+}
+#endif
+#endif

+ 272 - 0
libssh2/openssl/include/openssl/dtls1.h

@@ -0,0 +1,272 @@
+/* ssl/dtls1.h */
+/*
+ * DTLS implementation written by Nagendra Modadugu
+ * (nagendra@cs.stanford.edu) for the OpenSSL project 2005.
+ */
+/* ====================================================================
+ * Copyright (c) 1999-2005 The OpenSSL 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. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    openssl-core@OpenSSL.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED 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 OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS 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.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com).  This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+
+#ifndef HEADER_DTLS1_H
+# define HEADER_DTLS1_H
+
+# include <openssl/buffer.h>
+# include <openssl/pqueue.h>
+# ifdef OPENSSL_SYS_VMS
+#  include <resource.h>
+#  include <sys/timeb.h>
+# endif
+# ifdef OPENSSL_SYS_WIN32
+/* Needed for struct timeval */
+#  include <winsock.h>
+# elif defined(OPENSSL_SYS_NETWARE) && !defined(_WINSOCK2API_)
+#  include <sys/timeval.h>
+# else
+#  if defined(OPENSSL_SYS_VXWORKS)
+#   include <sys/times.h>
+#  else
+#   include <sys/time.h>
+#  endif
+# endif
+
+#ifdef  __cplusplus
+extern "C" {
+#endif
+
+# define DTLS1_VERSION                   0xFEFF
+# define DTLS1_2_VERSION                 0xFEFD
+# define DTLS_MAX_VERSION                DTLS1_2_VERSION
+# define DTLS1_VERSION_MAJOR             0xFE
+
+# define DTLS1_BAD_VER                   0x0100
+
+/* Special value for method supporting multiple versions */
+# define DTLS_ANY_VERSION                0x1FFFF
+
+# if 0
+/* this alert description is not specified anywhere... */
+#  define DTLS1_AD_MISSING_HANDSHAKE_MESSAGE    110
+# endif
+
+/* lengths of messages */
+# define DTLS1_COOKIE_LENGTH                     256
+
+# define DTLS1_RT_HEADER_LENGTH                  13
+
+# define DTLS1_HM_HEADER_LENGTH                  12
+
+# define DTLS1_HM_BAD_FRAGMENT                   -2
+# define DTLS1_HM_FRAGMENT_RETRY                 -3
+
+# define DTLS1_CCS_HEADER_LENGTH                  1
+
+# ifdef DTLS1_AD_MISSING_HANDSHAKE_MESSAGE
+#  define DTLS1_AL_HEADER_LENGTH                   7
+# else
+#  define DTLS1_AL_HEADER_LENGTH                   2
+# endif
+
+# ifndef OPENSSL_NO_SSL_INTERN
+
+#  ifndef OPENSSL_NO_SCTP
+#   define DTLS1_SCTP_AUTH_LABEL   "EXPORTER_DTLS_OVER_SCTP"
+#  endif
+
+/* Max MTU overhead we know about so far is 40 for IPv6 + 8 for UDP */
+#  define DTLS1_MAX_MTU_OVERHEAD                   48
+
+typedef struct dtls1_bitmap_st {
+    unsigned long map;          /* track 32 packets on 32-bit systems and 64
+                                 * - on 64-bit systems */
+    unsigned char max_seq_num[8]; /* max record number seen so far, 64-bit
+                                   * value in big-endian encoding */
+} DTLS1_BITMAP;
+
+struct dtls1_retransmit_state {
+    EVP_CIPHER_CTX *enc_write_ctx; /* cryptographic state */
+    EVP_MD_CTX *write_hash;     /* used for mac generation */
+#  ifndef OPENSSL_NO_COMP
+    COMP_CTX *compress;         /* compression */
+#  else
+    char *compress;
+#  endif
+    SSL_SESSION *session;
+    unsigned short epoch;
+};
+
+struct hm_header_st {
+    unsigned char type;
+    unsigned long msg_len;
+    unsigned short seq;
+    unsigned long frag_off;
+    unsigned long frag_len;
+    unsigned int is_ccs;
+    struct dtls1_retransmit_state saved_retransmit_state;
+};
+
+struct ccs_header_st {
+    unsigned char type;
+    unsigned short seq;
+};
+
+struct dtls1_timeout_st {
+    /* Number of read timeouts so far */
+    unsigned int read_timeouts;
+    /* Number of write timeouts so far */
+    unsigned int write_timeouts;
+    /* Number of alerts received so far */
+    unsigned int num_alerts;
+};
+
+typedef struct record_pqueue_st {
+    unsigned short epoch;
+    pqueue q;
+} record_pqueue;
+
+typedef struct hm_fragment_st {
+    struct hm_header_st msg_header;
+    unsigned char *fragment;
+    unsigned char *reassembly;
+} hm_fragment;
+
+typedef struct dtls1_state_st {
+    unsigned int send_cookie;
+    unsigned char cookie[DTLS1_COOKIE_LENGTH];
+    unsigned char rcvd_cookie[DTLS1_COOKIE_LENGTH];
+    unsigned int cookie_len;
+    /*
+     * The current data and handshake epoch.  This is initially
+     * undefined, and starts at zero once the initial handshake is
+     * completed
+     */
+    unsigned short r_epoch;
+    unsigned short w_epoch;
+    /* records being received in the current epoch */
+    DTLS1_BITMAP bitmap;
+    /* renegotiation starts a new set of sequence numbers */
+    DTLS1_BITMAP next_bitmap;
+    /* handshake message numbers */
+    unsigned short handshake_write_seq;
+    unsigned short next_handshake_write_seq;
+    unsigned short handshake_read_seq;
+    /* save last sequence number for retransmissions */
+    unsigned char last_write_sequence[8];
+    /* Received handshake records (processed and unprocessed) */
+    record_pqueue unprocessed_rcds;
+    record_pqueue processed_rcds;
+    /* Buffered handshake messages */
+    pqueue buffered_messages;
+    /* Buffered (sent) handshake records */
+    pqueue sent_messages;
+    /*
+     * Buffered application records. Only for records between CCS and
+     * Finished to prevent either protocol violation or unnecessary message
+     * loss.
+     */
+    record_pqueue buffered_app_data;
+    /* Is set when listening for new connections with dtls1_listen() */
+    unsigned int listen;
+    unsigned int link_mtu;      /* max on-the-wire DTLS packet size */
+    unsigned int mtu;           /* max DTLS packet size */
+    struct hm_header_st w_msg_hdr;
+    struct hm_header_st r_msg_hdr;
+    struct dtls1_timeout_st timeout;
+    /*
+     * Indicates when the last handshake msg or heartbeat sent will timeout
+     */
+    struct timeval next_timeout;
+    /* Timeout duration */
+    unsigned short timeout_duration;
+    /*
+     * storage for Alert/Handshake protocol data received but not yet
+     * processed by ssl3_read_bytes:
+     */
+    unsigned char alert_fragment[DTLS1_AL_HEADER_LENGTH];
+    unsigned int alert_fragment_len;
+    unsigned char handshake_fragment[DTLS1_HM_HEADER_LENGTH];
+    unsigned int handshake_fragment_len;
+    unsigned int retransmitting;
+    /*
+     * Set when the handshake is ready to process peer's ChangeCipherSpec message.
+     * Cleared after the message has been processed.
+     */
+    unsigned int change_cipher_spec_ok;
+#  ifndef OPENSSL_NO_SCTP
+    /* used when SSL_ST_XX_FLUSH is entered */
+    int next_state;
+    int shutdown_received;
+#  endif
+} DTLS1_STATE;
+
+typedef struct dtls1_record_data_st {
+    unsigned char *packet;
+    unsigned int packet_length;
+    SSL3_BUFFER rbuf;
+    SSL3_RECORD rrec;
+#  ifndef OPENSSL_NO_SCTP
+    struct bio_dgram_sctp_rcvinfo recordinfo;
+#  endif
+} DTLS1_RECORD_DATA;
+
+# endif
+
+/* Timeout multipliers (timeout slice is defined in apps/timeouts.h */
+# define DTLS1_TMO_READ_COUNT                      2
+# define DTLS1_TMO_WRITE_COUNT                     2
+
+# define DTLS1_TMO_ALERT_COUNT                     12
+
+#ifdef  __cplusplus
+}
+#endif
+#endif

+ 328 - 0
libssh2/openssl/include/openssl/e_os2.h

@@ -0,0 +1,328 @@
+/* e_os2.h */
+/* ====================================================================
+ * Copyright (c) 1998-2000 The OpenSSL 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. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    openssl-core@openssl.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED 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 OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS 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.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com).  This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+
+#include <openssl/opensslconf.h>
+
+#ifndef HEADER_E_OS2_H
+# define HEADER_E_OS2_H
+
+#ifdef  __cplusplus
+extern "C" {
+#endif
+
+/******************************************************************************
+ * Detect operating systems.  This probably needs completing.
+ * The result is that at least one OPENSSL_SYS_os macro should be defined.
+ * However, if none is defined, Unix is assumed.
+ **/
+
+# define OPENSSL_SYS_UNIX
+
+/* ---------------------- Macintosh, before MacOS X ----------------------- */
+# if defined(__MWERKS__) && defined(macintosh) || defined(OPENSSL_SYSNAME_MAC)
+#  undef OPENSSL_SYS_UNIX
+#  define OPENSSL_SYS_MACINTOSH_CLASSIC
+# endif
+
+/* ---------------------- NetWare ----------------------------------------- */
+# if defined(NETWARE) || defined(OPENSSL_SYSNAME_NETWARE)
+#  undef OPENSSL_SYS_UNIX
+#  define OPENSSL_SYS_NETWARE
+# endif
+
+/* --------------------- Microsoft operating systems ---------------------- */
+
+/*
+ * Note that MSDOS actually denotes 32-bit environments running on top of
+ * MS-DOS, such as DJGPP one.
+ */
+# if defined(OPENSSL_SYSNAME_MSDOS)
+#  undef OPENSSL_SYS_UNIX
+#  define OPENSSL_SYS_MSDOS
+# endif
+
+/*
+ * For 32 bit environment, there seems to be the CygWin environment and then
+ * all the others that try to do the same thing Microsoft does...
+ */
+# if defined(OPENSSL_SYSNAME_UWIN)
+#  undef OPENSSL_SYS_UNIX
+#  define OPENSSL_SYS_WIN32_UWIN
+# else
+#  if defined(__CYGWIN__) || defined(OPENSSL_SYSNAME_CYGWIN)
+#   undef OPENSSL_SYS_UNIX
+#   define OPENSSL_SYS_WIN32_CYGWIN
+#  else
+#   if defined(_WIN32) || defined(OPENSSL_SYSNAME_WIN32)
+#    undef OPENSSL_SYS_UNIX
+#    define OPENSSL_SYS_WIN32
+#   endif
+#   if defined(_WIN64) || defined(OPENSSL_SYSNAME_WIN64)
+#    undef OPENSSL_SYS_UNIX
+#    if !defined(OPENSSL_SYS_WIN64)
+#     define OPENSSL_SYS_WIN64
+#    endif
+#   endif
+#   if defined(OPENSSL_SYSNAME_WINNT)
+#    undef OPENSSL_SYS_UNIX
+#    define OPENSSL_SYS_WINNT
+#   endif
+#   if defined(OPENSSL_SYSNAME_WINCE)
+#    undef OPENSSL_SYS_UNIX
+#    define OPENSSL_SYS_WINCE
+#   endif
+#  endif
+# endif
+
+/* Anything that tries to look like Microsoft is "Windows" */
+# if defined(OPENSSL_SYS_WIN32) || defined(OPENSSL_SYS_WIN64) || defined(OPENSSL_SYS_WINNT) || defined(OPENSSL_SYS_WINCE)
+#  undef OPENSSL_SYS_UNIX
+#  define OPENSSL_SYS_WINDOWS
+#  ifndef OPENSSL_SYS_MSDOS
+#   define OPENSSL_SYS_MSDOS
+#  endif
+# endif
+
+/*
+ * DLL settings.  This part is a bit tough, because it's up to the
+ * application implementor how he or she will link the application, so it
+ * requires some macro to be used.
+ */
+# ifdef OPENSSL_SYS_WINDOWS
+#  ifndef OPENSSL_OPT_WINDLL
+#   if defined(_WINDLL)         /* This is used when building OpenSSL to
+                                 * indicate that DLL linkage should be used */
+#    define OPENSSL_OPT_WINDLL
+#   endif
+#  endif
+# endif
+
+/* ------------------------------- OpenVMS -------------------------------- */
+# if defined(__VMS) || defined(VMS) || defined(OPENSSL_SYSNAME_VMS)
+#  undef OPENSSL_SYS_UNIX
+#  define OPENSSL_SYS_VMS
+#  if defined(__DECC)
+#   define OPENSSL_SYS_VMS_DECC
+#  elif defined(__DECCXX)
+#   define OPENSSL_SYS_VMS_DECC
+#   define OPENSSL_SYS_VMS_DECCXX
+#  else
+#   define OPENSSL_SYS_VMS_NODECC
+#  endif
+# endif
+
+/* -------------------------------- OS/2 ---------------------------------- */
+# if defined(__EMX__) || defined(__OS2__)
+#  undef OPENSSL_SYS_UNIX
+#  define OPENSSL_SYS_OS2
+# endif
+
+/* -------------------------------- Unix ---------------------------------- */
+# ifdef OPENSSL_SYS_UNIX
+#  if defined(linux) || defined(__linux__) || defined(OPENSSL_SYSNAME_LINUX)
+#   define OPENSSL_SYS_LINUX
+#  endif
+#  ifdef OPENSSL_SYSNAME_MPE
+#   define OPENSSL_SYS_MPE
+#  endif
+#  ifdef OPENSSL_SYSNAME_SNI
+#   define OPENSSL_SYS_SNI
+#  endif
+#  ifdef OPENSSL_SYSNAME_ULTRASPARC
+#   define OPENSSL_SYS_ULTRASPARC
+#  endif
+#  ifdef OPENSSL_SYSNAME_NEWS4
+#   define OPENSSL_SYS_NEWS4
+#  endif
+#  ifdef OPENSSL_SYSNAME_MACOSX
+#   define OPENSSL_SYS_MACOSX
+#  endif
+#  ifdef OPENSSL_SYSNAME_MACOSX_RHAPSODY
+#   define OPENSSL_SYS_MACOSX_RHAPSODY
+#   define OPENSSL_SYS_MACOSX
+#  endif
+#  ifdef OPENSSL_SYSNAME_SUNOS
+#   define OPENSSL_SYS_SUNOS
+#  endif
+#  if defined(_CRAY) || defined(OPENSSL_SYSNAME_CRAY)
+#   define OPENSSL_SYS_CRAY
+#  endif
+#  if defined(_AIX) || defined(OPENSSL_SYSNAME_AIX)
+#   define OPENSSL_SYS_AIX
+#  endif
+# endif
+
+/* -------------------------------- VOS ----------------------------------- */
+# if defined(__VOS__) || defined(OPENSSL_SYSNAME_VOS)
+#  define OPENSSL_SYS_VOS
+#  ifdef __HPPA__
+#   define OPENSSL_SYS_VOS_HPPA
+#  endif
+#  ifdef __IA32__
+#   define OPENSSL_SYS_VOS_IA32
+#  endif
+# endif
+
+/* ------------------------------ VxWorks --------------------------------- */
+# ifdef OPENSSL_SYSNAME_VXWORKS
+#  define OPENSSL_SYS_VXWORKS
+# endif
+
+/* -------------------------------- BeOS ---------------------------------- */
+# if defined(__BEOS__)
+#  define OPENSSL_SYS_BEOS
+#  include <sys/socket.h>
+#  if defined(BONE_VERSION)
+#   define OPENSSL_SYS_BEOS_BONE
+#  else
+#   define OPENSSL_SYS_BEOS_R5
+#  endif
+# endif
+
+/**
+ * That's it for OS-specific stuff
+ *****************************************************************************/
+
+/* Specials for I/O an exit */
+# ifdef OPENSSL_SYS_MSDOS
+#  define OPENSSL_UNISTD_IO <io.h>
+#  define OPENSSL_DECLARE_EXIT extern void exit(int);
+# else
+#  define OPENSSL_UNISTD_IO OPENSSL_UNISTD
+#  define OPENSSL_DECLARE_EXIT  /* declared in unistd.h */
+# endif
+
+/*-
+ * Definitions of OPENSSL_GLOBAL and OPENSSL_EXTERN, to define and declare
+ * certain global symbols that, with some compilers under VMS, have to be
+ * defined and declared explicitely with globaldef and globalref.
+ * Definitions of OPENSSL_EXPORT and OPENSSL_IMPORT, to define and declare
+ * DLL exports and imports for compilers under Win32.  These are a little
+ * more complicated to use.  Basically, for any library that exports some
+ * global variables, the following code must be present in the header file
+ * that declares them, before OPENSSL_EXTERN is used:
+ *
+ * #ifdef SOME_BUILD_FLAG_MACRO
+ * # undef OPENSSL_EXTERN
+ * # define OPENSSL_EXTERN OPENSSL_EXPORT
+ * #endif
+ *
+ * The default is to have OPENSSL_EXPORT, OPENSSL_IMPORT and OPENSSL_GLOBAL
+ * have some generally sensible values, and for OPENSSL_EXTERN to have the
+ * value OPENSSL_IMPORT.
+ */
+
+# if defined(OPENSSL_SYS_VMS_NODECC)
+#  define OPENSSL_EXPORT globalref
+#  define OPENSSL_IMPORT globalref
+#  define OPENSSL_GLOBAL globaldef
+# elif defined(OPENSSL_SYS_WINDOWS) && defined(OPENSSL_OPT_WINDLL)
+#  define OPENSSL_EXPORT extern __declspec(dllexport)
+#  define OPENSSL_IMPORT extern __declspec(dllimport)
+#  define OPENSSL_GLOBAL
+# else
+#  define OPENSSL_EXPORT extern
+#  define OPENSSL_IMPORT extern
+#  define OPENSSL_GLOBAL
+# endif
+# define OPENSSL_EXTERN OPENSSL_IMPORT
+
+/*-
+ * Macros to allow global variables to be reached through function calls when
+ * required (if a shared library version requires it, for example.
+ * The way it's done allows definitions like this:
+ *
+ *      // in foobar.c
+ *      OPENSSL_IMPLEMENT_GLOBAL(int,foobar,0)
+ *      // in foobar.h
+ *      OPENSSL_DECLARE_GLOBAL(int,foobar);
+ *      #define foobar OPENSSL_GLOBAL_REF(foobar)
+ */
+# ifdef OPENSSL_EXPORT_VAR_AS_FUNCTION
+#  define OPENSSL_IMPLEMENT_GLOBAL(type,name,value)                      \
+        type *_shadow_##name(void)                                      \
+        { static type _hide_##name=value; return &_hide_##name; }
+#  define OPENSSL_DECLARE_GLOBAL(type,name) type *_shadow_##name(void)
+#  define OPENSSL_GLOBAL_REF(name) (*(_shadow_##name()))
+# else
+#  define OPENSSL_IMPLEMENT_GLOBAL(type,name,value) OPENSSL_GLOBAL type _shadow_##name=value;
+#  define OPENSSL_DECLARE_GLOBAL(type,name) OPENSSL_EXPORT type _shadow_##name
+#  define OPENSSL_GLOBAL_REF(name) _shadow_##name
+# endif
+
+# if defined(OPENSSL_SYS_MACINTOSH_CLASSIC) && macintosh==1 && !defined(MAC_OS_GUSI_SOURCE)
+#  define ossl_ssize_t long
+# endif
+
+# ifdef OPENSSL_SYS_MSDOS
+#  define ossl_ssize_t long
+# endif
+
+# if defined(NeXT) || defined(OPENSSL_SYS_NEWS4) || defined(OPENSSL_SYS_SUNOS)
+#  define ssize_t int
+# endif
+
+# if defined(__ultrix) && !defined(ssize_t)
+#  define ossl_ssize_t int
+# endif
+
+# ifndef ossl_ssize_t
+#  define ossl_ssize_t ssize_t
+# endif
+
+#ifdef  __cplusplus
+}
+#endif
+#endif

+ 26 - 0
libssh2/openssl/include/openssl/ebcdic.h

@@ -0,0 +1,26 @@
+/* crypto/ebcdic.h */
+
+#ifndef HEADER_EBCDIC_H
+# define HEADER_EBCDIC_H
+
+# include <sys/types.h>
+
+#ifdef  __cplusplus
+extern "C" {
+#endif
+
+/* Avoid name clashes with other applications */
+# define os_toascii   _openssl_os_toascii
+# define os_toebcdic  _openssl_os_toebcdic
+# define ebcdic2ascii _openssl_ebcdic2ascii
+# define ascii2ebcdic _openssl_ascii2ebcdic
+
+extern const unsigned char os_toascii[256];
+extern const unsigned char os_toebcdic[256];
+void *ebcdic2ascii(void *dest, const void *srce, size_t count);
+void *ascii2ebcdic(void *dest, const void *srce, size_t count);
+
+#ifdef  __cplusplus
+}
+#endif
+#endif

+ 1284 - 0
libssh2/openssl/include/openssl/ec.h

@@ -0,0 +1,1284 @@
+/* crypto/ec/ec.h */
+/*
+ * Originally written by Bodo Moeller for the OpenSSL project.
+ */
+/**
+ * \file crypto/ec/ec.h Include file for the OpenSSL EC functions
+ * \author Originally written by Bodo Moeller for the OpenSSL project
+ */
+/* ====================================================================
+ * Copyright (c) 1998-2019 The OpenSSL 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. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    openssl-core@openssl.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED 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 OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS 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.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com).  This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+/* ====================================================================
+ * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED.
+ *
+ * Portions of the attached software ("Contribution") are developed by
+ * SUN MICROSYSTEMS, INC., and are contributed to the OpenSSL project.
+ *
+ * The Contribution is licensed pursuant to the OpenSSL open source
+ * license provided above.
+ *
+ * The elliptic curve binary polynomial software is originally written by
+ * Sheueling Chang Shantz and Douglas Stebila of Sun Microsystems Laboratories.
+ *
+ */
+
+#ifndef HEADER_EC_H
+# define HEADER_EC_H
+
+# include <openssl/opensslconf.h>
+
+# ifdef OPENSSL_NO_EC
+#  error EC is disabled.
+# endif
+
+# include <openssl/asn1.h>
+# include <openssl/symhacks.h>
+# ifndef OPENSSL_NO_DEPRECATED
+#  include <openssl/bn.h>
+# endif
+
+# ifdef  __cplusplus
+extern "C" {
+# elif defined(__SUNPRO_C)
+#  if __SUNPRO_C >= 0x520
+#   pragma error_messages (off,E_ARRAY_OF_INCOMPLETE_NONAME,E_ARRAY_OF_INCOMPLETE)
+#  endif
+# endif
+
+# ifndef OPENSSL_ECC_MAX_FIELD_BITS
+#  define OPENSSL_ECC_MAX_FIELD_BITS 661
+# endif
+
+/** Enum for the point conversion form as defined in X9.62 (ECDSA)
+ *  for the encoding of a elliptic curve point (x,y) */
+typedef enum {
+        /** the point is encoded as z||x, where the octet z specifies
+         *  which solution of the quadratic equation y is  */
+    POINT_CONVERSION_COMPRESSED = 2,
+        /** the point is encoded as z||x||y, where z is the octet 0x04  */
+    POINT_CONVERSION_UNCOMPRESSED = 4,
+        /** the point is encoded as z||x||y, where the octet z specifies
+         *  which solution of the quadratic equation y is  */
+    POINT_CONVERSION_HYBRID = 6
+} point_conversion_form_t;
+
+typedef struct ec_method_st EC_METHOD;
+
+typedef struct ec_group_st
+    /*-
+     EC_METHOD *meth;
+     -- field definition
+     -- curve coefficients
+     -- optional generator with associated information (order, cofactor)
+     -- optional extra data (precomputed table for fast computation of multiples of generator)
+     -- ASN1 stuff
+    */
+    EC_GROUP;
+
+typedef struct ec_point_st EC_POINT;
+
+/********************************************************************/
+/*               EC_METHODs for curves over GF(p)                   */
+/********************************************************************/
+
+/** Returns the basic GFp ec methods which provides the basis for the
+ *  optimized methods.
+ *  \return  EC_METHOD object
+ */
+const EC_METHOD *EC_GFp_simple_method(void);
+
+/** Returns GFp methods using montgomery multiplication.
+ *  \return  EC_METHOD object
+ */
+const EC_METHOD *EC_GFp_mont_method(void);
+
+/** Returns GFp methods using optimized methods for NIST recommended curves
+ *  \return  EC_METHOD object
+ */
+const EC_METHOD *EC_GFp_nist_method(void);
+
+# ifndef OPENSSL_NO_EC_NISTP_64_GCC_128
+/** Returns 64-bit optimized methods for nistp224
+ *  \return  EC_METHOD object
+ */
+const EC_METHOD *EC_GFp_nistp224_method(void);
+
+/** Returns 64-bit optimized methods for nistp256
+ *  \return  EC_METHOD object
+ */
+const EC_METHOD *EC_GFp_nistp256_method(void);
+
+/** Returns 64-bit optimized methods for nistp521
+ *  \return  EC_METHOD object
+ */
+const EC_METHOD *EC_GFp_nistp521_method(void);
+# endif
+
+# ifndef OPENSSL_NO_EC2M
+/********************************************************************/
+/*           EC_METHOD for curves over GF(2^m)                      */
+/********************************************************************/
+
+/** Returns the basic GF2m ec method
+ *  \return  EC_METHOD object
+ */
+const EC_METHOD *EC_GF2m_simple_method(void);
+
+# endif
+
+/********************************************************************/
+/*                   EC_GROUP functions                             */
+/********************************************************************/
+
+/** Creates a new EC_GROUP object
+ *  \param   meth  EC_METHOD to use
+ *  \return  newly created EC_GROUP object or NULL in case of an error.
+ */
+EC_GROUP *EC_GROUP_new(const EC_METHOD *meth);
+
+/** Frees a EC_GROUP object
+ *  \param  group  EC_GROUP object to be freed.
+ */
+void EC_GROUP_free(EC_GROUP *group);
+
+/** Clears and frees a EC_GROUP object
+ *  \param  group  EC_GROUP object to be cleared and freed.
+ */
+void EC_GROUP_clear_free(EC_GROUP *group);
+
+/** Copies EC_GROUP objects. Note: both EC_GROUPs must use the same EC_METHOD.
+ *  \param  dst  destination EC_GROUP object
+ *  \param  src  source EC_GROUP object
+ *  \return 1 on success and 0 if an error occurred.
+ */
+int EC_GROUP_copy(EC_GROUP *dst, const EC_GROUP *src);
+
+/** Creates a new EC_GROUP object and copies the copies the content
+ *  form src to the newly created EC_KEY object
+ *  \param  src  source EC_GROUP object
+ *  \return newly created EC_GROUP object or NULL in case of an error.
+ */
+EC_GROUP *EC_GROUP_dup(const EC_GROUP *src);
+
+/** Returns the EC_METHOD of the EC_GROUP object.
+ *  \param  group  EC_GROUP object
+ *  \return EC_METHOD used in this EC_GROUP object.
+ */
+const EC_METHOD *EC_GROUP_method_of(const EC_GROUP *group);
+
+/** Returns the field type of the EC_METHOD.
+ *  \param  meth  EC_METHOD object
+ *  \return NID of the underlying field type OID.
+ */
+int EC_METHOD_get_field_type(const EC_METHOD *meth);
+
+/** Sets the generator and it's order/cofactor of a EC_GROUP object.
+ *  \param  group      EC_GROUP object
+ *  \param  generator  EC_POINT object with the generator.
+ *  \param  order      the order of the group generated by the generator.
+ *  \param  cofactor   the index of the sub-group generated by the generator
+ *                     in the group of all points on the elliptic curve.
+ *  \return 1 on success and 0 if an error occured
+ */
+int EC_GROUP_set_generator(EC_GROUP *group, const EC_POINT *generator,
+                           const BIGNUM *order, const BIGNUM *cofactor);
+
+/** Returns the generator of a EC_GROUP object.
+ *  \param  group  EC_GROUP object
+ *  \return the currently used generator (possibly NULL).
+ */
+const EC_POINT *EC_GROUP_get0_generator(const EC_GROUP *group);
+
+/** Returns the montgomery data for order(Generator)
+ *  \param  group  EC_GROUP object
+ *  \return the currently used generator (possibly NULL).
+*/
+BN_MONT_CTX *EC_GROUP_get_mont_data(const EC_GROUP *group);
+
+/** Gets the order of a EC_GROUP
+ *  \param  group  EC_GROUP object
+ *  \param  order  BIGNUM to which the order is copied
+ *  \param  ctx    BN_CTX object (optional)
+ *  \return 1 on success and 0 if an error occured
+ */
+int EC_GROUP_get_order(const EC_GROUP *group, BIGNUM *order, BN_CTX *ctx);
+
+/** Gets the cofactor of a EC_GROUP
+ *  \param  group     EC_GROUP object
+ *  \param  cofactor  BIGNUM to which the cofactor is copied
+ *  \param  ctx       BN_CTX object (optional)
+ *  \return 1 on success and 0 if an error occured
+ */
+int EC_GROUP_get_cofactor(const EC_GROUP *group, BIGNUM *cofactor,
+                          BN_CTX *ctx);
+
+/** Sets the name of a EC_GROUP object
+ *  \param  group  EC_GROUP object
+ *  \param  nid    NID of the curve name OID
+ */
+void EC_GROUP_set_curve_name(EC_GROUP *group, int nid);
+
+/** Returns the curve name of a EC_GROUP object
+ *  \param  group  EC_GROUP object
+ *  \return NID of the curve name OID or 0 if not set.
+ */
+int EC_GROUP_get_curve_name(const EC_GROUP *group);
+
+void EC_GROUP_set_asn1_flag(EC_GROUP *group, int flag);
+int EC_GROUP_get_asn1_flag(const EC_GROUP *group);
+
+void EC_GROUP_set_point_conversion_form(EC_GROUP *group,
+                                        point_conversion_form_t form);
+point_conversion_form_t EC_GROUP_get_point_conversion_form(const EC_GROUP *);
+
+unsigned char *EC_GROUP_get0_seed(const EC_GROUP *x);
+size_t EC_GROUP_get_seed_len(const EC_GROUP *);
+size_t EC_GROUP_set_seed(EC_GROUP *, const unsigned char *, size_t len);
+
+/** Sets the parameter of a ec over GFp defined by y^2 = x^3 + a*x + b
+ *  \param  group  EC_GROUP object
+ *  \param  p      BIGNUM with the prime number
+ *  \param  a      BIGNUM with parameter a of the equation
+ *  \param  b      BIGNUM with parameter b of the equation
+ *  \param  ctx    BN_CTX object (optional)
+ *  \return 1 on success and 0 if an error occured
+ */
+int EC_GROUP_set_curve_GFp(EC_GROUP *group, const BIGNUM *p, const BIGNUM *a,
+                           const BIGNUM *b, BN_CTX *ctx);
+
+/** Gets the parameter of the ec over GFp defined by y^2 = x^3 + a*x + b
+ *  \param  group  EC_GROUP object
+ *  \param  p      BIGNUM for the prime number
+ *  \param  a      BIGNUM for parameter a of the equation
+ *  \param  b      BIGNUM for parameter b of the equation
+ *  \param  ctx    BN_CTX object (optional)
+ *  \return 1 on success and 0 if an error occured
+ */
+int EC_GROUP_get_curve_GFp(const EC_GROUP *group, BIGNUM *p, BIGNUM *a,
+                           BIGNUM *b, BN_CTX *ctx);
+
+# ifndef OPENSSL_NO_EC2M
+/** Sets the parameter of a ec over GF2m defined by y^2 + x*y = x^3 + a*x^2 + b
+ *  \param  group  EC_GROUP object
+ *  \param  p      BIGNUM with the polynomial defining the underlying field
+ *  \param  a      BIGNUM with parameter a of the equation
+ *  \param  b      BIGNUM with parameter b of the equation
+ *  \param  ctx    BN_CTX object (optional)
+ *  \return 1 on success and 0 if an error occured
+ */
+int EC_GROUP_set_curve_GF2m(EC_GROUP *group, const BIGNUM *p, const BIGNUM *a,
+                            const BIGNUM *b, BN_CTX *ctx);
+
+/** Gets the parameter of the ec over GF2m defined by y^2 + x*y = x^3 + a*x^2 + b
+ *  \param  group  EC_GROUP object
+ *  \param  p      BIGNUM for the polynomial defining the underlying field
+ *  \param  a      BIGNUM for parameter a of the equation
+ *  \param  b      BIGNUM for parameter b of the equation
+ *  \param  ctx    BN_CTX object (optional)
+ *  \return 1 on success and 0 if an error occured
+ */
+int EC_GROUP_get_curve_GF2m(const EC_GROUP *group, BIGNUM *p, BIGNUM *a,
+                            BIGNUM *b, BN_CTX *ctx);
+# endif
+/** Returns the number of bits needed to represent a field element
+ *  \param  group  EC_GROUP object
+ *  \return number of bits needed to represent a field element
+ */
+int EC_GROUP_get_degree(const EC_GROUP *group);
+
+/** Checks whether the parameter in the EC_GROUP define a valid ec group
+ *  \param  group  EC_GROUP object
+ *  \param  ctx    BN_CTX object (optional)
+ *  \return 1 if group is a valid ec group and 0 otherwise
+ */
+int EC_GROUP_check(const EC_GROUP *group, BN_CTX *ctx);
+
+/** Checks whether the discriminant of the elliptic curve is zero or not
+ *  \param  group  EC_GROUP object
+ *  \param  ctx    BN_CTX object (optional)
+ *  \return 1 if the discriminant is not zero and 0 otherwise
+ */
+int EC_GROUP_check_discriminant(const EC_GROUP *group, BN_CTX *ctx);
+
+/** Compares two EC_GROUP objects
+ *  \param  a    first EC_GROUP object
+ *  \param  b    second EC_GROUP object
+ *  \param  ctx  BN_CTX object (optional)
+ *  \return 0 if both groups are equal and 1 otherwise
+ */
+int EC_GROUP_cmp(const EC_GROUP *a, const EC_GROUP *b, BN_CTX *ctx);
+
+/*
+ * EC_GROUP_new_GF*() calls EC_GROUP_new() and EC_GROUP_set_GF*() after
+ * choosing an appropriate EC_METHOD
+ */
+
+/** Creates a new EC_GROUP object with the specified parameters defined
+ *  over GFp (defined by the equation y^2 = x^3 + a*x + b)
+ *  \param  p    BIGNUM with the prime number
+ *  \param  a    BIGNUM with the parameter a of the equation
+ *  \param  b    BIGNUM with the parameter b of the equation
+ *  \param  ctx  BN_CTX object (optional)
+ *  \return newly created EC_GROUP object with the specified parameters
+ */
+EC_GROUP *EC_GROUP_new_curve_GFp(const BIGNUM *p, const BIGNUM *a,
+                                 const BIGNUM *b, BN_CTX *ctx);
+# ifndef OPENSSL_NO_EC2M
+/** Creates a new EC_GROUP object with the specified parameters defined
+ *  over GF2m (defined by the equation y^2 + x*y = x^3 + a*x^2 + b)
+ *  \param  p    BIGNUM with the polynomial defining the underlying field
+ *  \param  a    BIGNUM with the parameter a of the equation
+ *  \param  b    BIGNUM with the parameter b of the equation
+ *  \param  ctx  BN_CTX object (optional)
+ *  \return newly created EC_GROUP object with the specified parameters
+ */
+EC_GROUP *EC_GROUP_new_curve_GF2m(const BIGNUM *p, const BIGNUM *a,
+                                  const BIGNUM *b, BN_CTX *ctx);
+# endif
+/** Creates a EC_GROUP object with a curve specified by a NID
+ *  \param  nid  NID of the OID of the curve name
+ *  \return newly created EC_GROUP object with specified curve or NULL
+ *          if an error occurred
+ */
+EC_GROUP *EC_GROUP_new_by_curve_name(int nid);
+
+/********************************************************************/
+/*               handling of internal curves                        */
+/********************************************************************/
+
+typedef struct {
+    int nid;
+    const char *comment;
+} EC_builtin_curve;
+
+/*
+ * EC_builtin_curves(EC_builtin_curve *r, size_t size) returns number of all
+ * available curves or zero if a error occurred. In case r ist not zero
+ * nitems EC_builtin_curve structures are filled with the data of the first
+ * nitems internal groups
+ */
+size_t EC_get_builtin_curves(EC_builtin_curve *r, size_t nitems);
+
+const char *EC_curve_nid2nist(int nid);
+int EC_curve_nist2nid(const char *name);
+
+/********************************************************************/
+/*                    EC_POINT functions                            */
+/********************************************************************/
+
+/** Creates a new EC_POINT object for the specified EC_GROUP
+ *  \param  group  EC_GROUP the underlying EC_GROUP object
+ *  \return newly created EC_POINT object or NULL if an error occurred
+ */
+EC_POINT *EC_POINT_new(const EC_GROUP *group);
+
+/** Frees a EC_POINT object
+ *  \param  point  EC_POINT object to be freed
+ */
+void EC_POINT_free(EC_POINT *point);
+
+/** Clears and frees a EC_POINT object
+ *  \param  point  EC_POINT object to be cleared and freed
+ */
+void EC_POINT_clear_free(EC_POINT *point);
+
+/** Copies EC_POINT object
+ *  \param  dst  destination EC_POINT object
+ *  \param  src  source EC_POINT object
+ *  \return 1 on success and 0 if an error occured
+ */
+int EC_POINT_copy(EC_POINT *dst, const EC_POINT *src);
+
+/** Creates a new EC_POINT object and copies the content of the supplied
+ *  EC_POINT
+ *  \param  src    source EC_POINT object
+ *  \param  group  underlying the EC_GROUP object
+ *  \return newly created EC_POINT object or NULL if an error occurred
+ */
+EC_POINT *EC_POINT_dup(const EC_POINT *src, const EC_GROUP *group);
+
+/** Returns the EC_METHOD used in EC_POINT object
+ *  \param  point  EC_POINT object
+ *  \return the EC_METHOD used
+ */
+const EC_METHOD *EC_POINT_method_of(const EC_POINT *point);
+
+/** Sets a point to infinity (neutral element)
+ *  \param  group  underlying EC_GROUP object
+ *  \param  point  EC_POINT to set to infinity
+ *  \return 1 on success and 0 if an error occured
+ */
+int EC_POINT_set_to_infinity(const EC_GROUP *group, EC_POINT *point);
+
+/** Sets the jacobian projective coordinates of a EC_POINT over GFp
+ *  \param  group  underlying EC_GROUP object
+ *  \param  p      EC_POINT object
+ *  \param  x      BIGNUM with the x-coordinate
+ *  \param  y      BIGNUM with the y-coordinate
+ *  \param  z      BIGNUM with the z-coordinate
+ *  \param  ctx    BN_CTX object (optional)
+ *  \return 1 on success and 0 if an error occured
+ */
+int EC_POINT_set_Jprojective_coordinates_GFp(const EC_GROUP *group,
+                                             EC_POINT *p, const BIGNUM *x,
+                                             const BIGNUM *y, const BIGNUM *z,
+                                             BN_CTX *ctx);
+
+/** Gets the jacobian projective coordinates of a EC_POINT over GFp
+ *  \param  group  underlying EC_GROUP object
+ *  \param  p      EC_POINT object
+ *  \param  x      BIGNUM for the x-coordinate
+ *  \param  y      BIGNUM for the y-coordinate
+ *  \param  z      BIGNUM for the z-coordinate
+ *  \param  ctx    BN_CTX object (optional)
+ *  \return 1 on success and 0 if an error occured
+ */
+int EC_POINT_get_Jprojective_coordinates_GFp(const EC_GROUP *group,
+                                             const EC_POINT *p, BIGNUM *x,
+                                             BIGNUM *y, BIGNUM *z,
+                                             BN_CTX *ctx);
+
+/** Sets the affine coordinates of a EC_POINT over GFp
+ *  \param  group  underlying EC_GROUP object
+ *  \param  p      EC_POINT object
+ *  \param  x      BIGNUM with the x-coordinate
+ *  \param  y      BIGNUM with the y-coordinate
+ *  \param  ctx    BN_CTX object (optional)
+ *  \return 1 on success and 0 if an error occured
+ */
+int EC_POINT_set_affine_coordinates_GFp(const EC_GROUP *group, EC_POINT *p,
+                                        const BIGNUM *x, const BIGNUM *y,
+                                        BN_CTX *ctx);
+
+/** Gets the affine coordinates of a EC_POINT over GFp
+ *  \param  group  underlying EC_GROUP object
+ *  \param  p      EC_POINT object
+ *  \param  x      BIGNUM for the x-coordinate
+ *  \param  y      BIGNUM for the y-coordinate
+ *  \param  ctx    BN_CTX object (optional)
+ *  \return 1 on success and 0 if an error occured
+ */
+int EC_POINT_get_affine_coordinates_GFp(const EC_GROUP *group,
+                                        const EC_POINT *p, BIGNUM *x,
+                                        BIGNUM *y, BN_CTX *ctx);
+
+/** Sets the x9.62 compressed coordinates of a EC_POINT over GFp
+ *  \param  group  underlying EC_GROUP object
+ *  \param  p      EC_POINT object
+ *  \param  x      BIGNUM with x-coordinate
+ *  \param  y_bit  integer with the y-Bit (either 0 or 1)
+ *  \param  ctx    BN_CTX object (optional)
+ *  \return 1 on success and 0 if an error occured
+ */
+int EC_POINT_set_compressed_coordinates_GFp(const EC_GROUP *group,
+                                            EC_POINT *p, const BIGNUM *x,
+                                            int y_bit, BN_CTX *ctx);
+# ifndef OPENSSL_NO_EC2M
+/** Sets the affine coordinates of a EC_POINT over GF2m
+ *  \param  group  underlying EC_GROUP object
+ *  \param  p      EC_POINT object
+ *  \param  x      BIGNUM with the x-coordinate
+ *  \param  y      BIGNUM with the y-coordinate
+ *  \param  ctx    BN_CTX object (optional)
+ *  \return 1 on success and 0 if an error occured
+ */
+int EC_POINT_set_affine_coordinates_GF2m(const EC_GROUP *group, EC_POINT *p,
+                                         const BIGNUM *x, const BIGNUM *y,
+                                         BN_CTX *ctx);
+
+/** Gets the affine coordinates of a EC_POINT over GF2m
+ *  \param  group  underlying EC_GROUP object
+ *  \param  p      EC_POINT object
+ *  \param  x      BIGNUM for the x-coordinate
+ *  \param  y      BIGNUM for the y-coordinate
+ *  \param  ctx    BN_CTX object (optional)
+ *  \return 1 on success and 0 if an error occured
+ */
+int EC_POINT_get_affine_coordinates_GF2m(const EC_GROUP *group,
+                                         const EC_POINT *p, BIGNUM *x,
+                                         BIGNUM *y, BN_CTX *ctx);
+
+/** Sets the x9.62 compressed coordinates of a EC_POINT over GF2m
+ *  \param  group  underlying EC_GROUP object
+ *  \param  p      EC_POINT object
+ *  \param  x      BIGNUM with x-coordinate
+ *  \param  y_bit  integer with the y-Bit (either 0 or 1)
+ *  \param  ctx    BN_CTX object (optional)
+ *  \return 1 on success and 0 if an error occured
+ */
+int EC_POINT_set_compressed_coordinates_GF2m(const EC_GROUP *group,
+                                             EC_POINT *p, const BIGNUM *x,
+                                             int y_bit, BN_CTX *ctx);
+# endif
+/** Encodes a EC_POINT object to a octet string
+ *  \param  group  underlying EC_GROUP object
+ *  \param  p      EC_POINT object
+ *  \param  form   point conversion form
+ *  \param  buf    memory buffer for the result. If NULL the function returns
+ *                 required buffer size.
+ *  \param  len    length of the memory buffer
+ *  \param  ctx    BN_CTX object (optional)
+ *  \return the length of the encoded octet string or 0 if an error occurred
+ */
+size_t EC_POINT_point2oct(const EC_GROUP *group, const EC_POINT *p,
+                          point_conversion_form_t form,
+                          unsigned char *buf, size_t len, BN_CTX *ctx);
+
+/** Decodes a EC_POINT from a octet string
+ *  \param  group  underlying EC_GROUP object
+ *  \param  p      EC_POINT object
+ *  \param  buf    memory buffer with the encoded ec point
+ *  \param  len    length of the encoded ec point
+ *  \param  ctx    BN_CTX object (optional)
+ *  \return 1 on success and 0 if an error occured
+ */
+int EC_POINT_oct2point(const EC_GROUP *group, EC_POINT *p,
+                       const unsigned char *buf, size_t len, BN_CTX *ctx);
+
+/* other interfaces to point2oct/oct2point: */
+BIGNUM *EC_POINT_point2bn(const EC_GROUP *, const EC_POINT *,
+                          point_conversion_form_t form, BIGNUM *, BN_CTX *);
+EC_POINT *EC_POINT_bn2point(const EC_GROUP *, const BIGNUM *,
+                            EC_POINT *, BN_CTX *);
+char *EC_POINT_point2hex(const EC_GROUP *, const EC_POINT *,
+                         point_conversion_form_t form, BN_CTX *);
+EC_POINT *EC_POINT_hex2point(const EC_GROUP *, const char *,
+                             EC_POINT *, BN_CTX *);
+
+/********************************************************************/
+/*         functions for doing EC_POINT arithmetic                  */
+/********************************************************************/
+
+/** Computes the sum of two EC_POINT
+ *  \param  group  underlying EC_GROUP object
+ *  \param  r      EC_POINT object for the result (r = a + b)
+ *  \param  a      EC_POINT object with the first summand
+ *  \param  b      EC_POINT object with the second summand
+ *  \param  ctx    BN_CTX object (optional)
+ *  \return 1 on success and 0 if an error occured
+ */
+int EC_POINT_add(const EC_GROUP *group, EC_POINT *r, const EC_POINT *a,
+                 const EC_POINT *b, BN_CTX *ctx);
+
+/** Computes the double of a EC_POINT
+ *  \param  group  underlying EC_GROUP object
+ *  \param  r      EC_POINT object for the result (r = 2 * a)
+ *  \param  a      EC_POINT object
+ *  \param  ctx    BN_CTX object (optional)
+ *  \return 1 on success and 0 if an error occured
+ */
+int EC_POINT_dbl(const EC_GROUP *group, EC_POINT *r, const EC_POINT *a,
+                 BN_CTX *ctx);
+
+/** Computes the inverse of a EC_POINT
+ *  \param  group  underlying EC_GROUP object
+ *  \param  a      EC_POINT object to be inverted (it's used for the result as well)
+ *  \param  ctx    BN_CTX object (optional)
+ *  \return 1 on success and 0 if an error occured
+ */
+int EC_POINT_invert(const EC_GROUP *group, EC_POINT *a, BN_CTX *ctx);
+
+/** Checks whether the point is the neutral element of the group
+ *  \param  group  the underlying EC_GROUP object
+ *  \param  p      EC_POINT object
+ *  \return 1 if the point is the neutral element and 0 otherwise
+ */
+int EC_POINT_is_at_infinity(const EC_GROUP *group, const EC_POINT *p);
+
+/** Checks whether the point is on the curve
+ *  \param  group  underlying EC_GROUP object
+ *  \param  point  EC_POINT object to check
+ *  \param  ctx    BN_CTX object (optional)
+ *  \return 1 if point if on the curve and 0 otherwise
+ */
+int EC_POINT_is_on_curve(const EC_GROUP *group, const EC_POINT *point,
+                         BN_CTX *ctx);
+
+/** Compares two EC_POINTs
+ *  \param  group  underlying EC_GROUP object
+ *  \param  a      first EC_POINT object
+ *  \param  b      second EC_POINT object
+ *  \param  ctx    BN_CTX object (optional)
+ *  \return 0 if both points are equal and a value != 0 otherwise
+ */
+int EC_POINT_cmp(const EC_GROUP *group, const EC_POINT *a, const EC_POINT *b,
+                 BN_CTX *ctx);
+
+int EC_POINT_make_affine(const EC_GROUP *group, EC_POINT *point, BN_CTX *ctx);
+int EC_POINTs_make_affine(const EC_GROUP *group, size_t num,
+                          EC_POINT *points[], BN_CTX *ctx);
+
+/** Computes r = generator * n sum_{i=0}^{num-1} p[i] * m[i]
+ *  \param  group  underlying EC_GROUP object
+ *  \param  r      EC_POINT object for the result
+ *  \param  n      BIGNUM with the multiplier for the group generator (optional)
+ *  \param  num    number futher summands
+ *  \param  p      array of size num of EC_POINT objects
+ *  \param  m      array of size num of BIGNUM objects
+ *  \param  ctx    BN_CTX object (optional)
+ *  \return 1 on success and 0 if an error occured
+ */
+int EC_POINTs_mul(const EC_GROUP *group, EC_POINT *r, const BIGNUM *n,
+                  size_t num, const EC_POINT *p[], const BIGNUM *m[],
+                  BN_CTX *ctx);
+
+/** Computes r = generator * n + q * m
+ *  \param  group  underlying EC_GROUP object
+ *  \param  r      EC_POINT object for the result
+ *  \param  n      BIGNUM with the multiplier for the group generator (optional)
+ *  \param  q      EC_POINT object with the first factor of the second summand
+ *  \param  m      BIGNUM with the second factor of the second summand
+ *  \param  ctx    BN_CTX object (optional)
+ *  \return 1 on success and 0 if an error occured
+ */
+int EC_POINT_mul(const EC_GROUP *group, EC_POINT *r, const BIGNUM *n,
+                 const EC_POINT *q, const BIGNUM *m, BN_CTX *ctx);
+
+/** Stores multiples of generator for faster point multiplication
+ *  \param  group  EC_GROUP object
+ *  \param  ctx    BN_CTX object (optional)
+ *  \return 1 on success and 0 if an error occured
+ */
+int EC_GROUP_precompute_mult(EC_GROUP *group, BN_CTX *ctx);
+
+/** Reports whether a precomputation has been done
+ *  \param  group  EC_GROUP object
+ *  \return 1 if a pre-computation has been done and 0 otherwise
+ */
+int EC_GROUP_have_precompute_mult(const EC_GROUP *group);
+
+/********************************************************************/
+/*                       ASN1 stuff                                 */
+/********************************************************************/
+
+/*
+ * EC_GROUP_get_basis_type() returns the NID of the basis type used to
+ * represent the field elements
+ */
+int EC_GROUP_get_basis_type(const EC_GROUP *);
+# ifndef OPENSSL_NO_EC2M
+int EC_GROUP_get_trinomial_basis(const EC_GROUP *, unsigned int *k);
+int EC_GROUP_get_pentanomial_basis(const EC_GROUP *, unsigned int *k1,
+                                   unsigned int *k2, unsigned int *k3);
+# endif
+
+# define OPENSSL_EC_NAMED_CURVE  0x001
+
+typedef struct ecpk_parameters_st ECPKPARAMETERS;
+
+EC_GROUP *d2i_ECPKParameters(EC_GROUP **, const unsigned char **in, long len);
+int i2d_ECPKParameters(const EC_GROUP *, unsigned char **out);
+
+# define d2i_ECPKParameters_bio(bp,x) ASN1_d2i_bio_of(EC_GROUP,NULL,d2i_ECPKParameters,bp,x)
+# define i2d_ECPKParameters_bio(bp,x) ASN1_i2d_bio_of_const(EC_GROUP,i2d_ECPKParameters,bp,x)
+# define d2i_ECPKParameters_fp(fp,x) (EC_GROUP *)ASN1_d2i_fp(NULL, \
+                (char *(*)())d2i_ECPKParameters,(fp),(unsigned char **)(x))
+# define i2d_ECPKParameters_fp(fp,x) ASN1_i2d_fp(i2d_ECPKParameters,(fp), \
+                (unsigned char *)(x))
+
+# ifndef OPENSSL_NO_BIO
+int ECPKParameters_print(BIO *bp, const EC_GROUP *x, int off);
+# endif
+# ifndef OPENSSL_NO_FP_API
+int ECPKParameters_print_fp(FILE *fp, const EC_GROUP *x, int off);
+# endif
+
+/********************************************************************/
+/*                      EC_KEY functions                            */
+/********************************************************************/
+
+typedef struct ec_key_st EC_KEY;
+
+/* some values for the encoding_flag */
+# define EC_PKEY_NO_PARAMETERS   0x001
+# define EC_PKEY_NO_PUBKEY       0x002
+
+/* some values for the flags field */
+# define EC_FLAG_NON_FIPS_ALLOW  0x1
+# define EC_FLAG_FIPS_CHECKED    0x2
+
+/** Creates a new EC_KEY object.
+ *  \return EC_KEY object or NULL if an error occurred.
+ */
+EC_KEY *EC_KEY_new(void);
+
+int EC_KEY_get_flags(const EC_KEY *key);
+
+void EC_KEY_set_flags(EC_KEY *key, int flags);
+
+void EC_KEY_clear_flags(EC_KEY *key, int flags);
+
+/** Creates a new EC_KEY object using a named curve as underlying
+ *  EC_GROUP object.
+ *  \param  nid  NID of the named curve.
+ *  \return EC_KEY object or NULL if an error occurred.
+ */
+EC_KEY *EC_KEY_new_by_curve_name(int nid);
+
+/** Frees a EC_KEY object.
+ *  \param  key  EC_KEY object to be freed.
+ */
+void EC_KEY_free(EC_KEY *key);
+
+/** Copies a EC_KEY object.
+ *  \param  dst  destination EC_KEY object
+ *  \param  src  src EC_KEY object
+ *  \return dst or NULL if an error occurred.
+ */
+EC_KEY *EC_KEY_copy(EC_KEY *dst, const EC_KEY *src);
+
+/** Creates a new EC_KEY object and copies the content from src to it.
+ *  \param  src  the source EC_KEY object
+ *  \return newly created EC_KEY object or NULL if an error occurred.
+ */
+EC_KEY *EC_KEY_dup(const EC_KEY *src);
+
+/** Increases the internal reference count of a EC_KEY object.
+ *  \param  key  EC_KEY object
+ *  \return 1 on success and 0 if an error occurred.
+ */
+int EC_KEY_up_ref(EC_KEY *key);
+
+/** Returns the EC_GROUP object of a EC_KEY object
+ *  \param  key  EC_KEY object
+ *  \return the EC_GROUP object (possibly NULL).
+ */
+const EC_GROUP *EC_KEY_get0_group(const EC_KEY *key);
+
+/** Sets the EC_GROUP of a EC_KEY object.
+ *  \param  key    EC_KEY object
+ *  \param  group  EC_GROUP to use in the EC_KEY object (note: the EC_KEY
+ *                 object will use an own copy of the EC_GROUP).
+ *  \return 1 on success and 0 if an error occurred.
+ */
+int EC_KEY_set_group(EC_KEY *key, const EC_GROUP *group);
+
+/** Returns the private key of a EC_KEY object.
+ *  \param  key  EC_KEY object
+ *  \return a BIGNUM with the private key (possibly NULL).
+ */
+const BIGNUM *EC_KEY_get0_private_key(const EC_KEY *key);
+
+/** Sets the private key of a EC_KEY object.
+ *  \param  key  EC_KEY object
+ *  \param  prv  BIGNUM with the private key (note: the EC_KEY object
+ *               will use an own copy of the BIGNUM).
+ *  \return 1 on success and 0 if an error occurred.
+ */
+int EC_KEY_set_private_key(EC_KEY *key, const BIGNUM *prv);
+
+/** Returns the public key of a EC_KEY object.
+ *  \param  key  the EC_KEY object
+ *  \return a EC_POINT object with the public key (possibly NULL)
+ */
+const EC_POINT *EC_KEY_get0_public_key(const EC_KEY *key);
+
+/** Sets the public key of a EC_KEY object.
+ *  \param  key  EC_KEY object
+ *  \param  pub  EC_POINT object with the public key (note: the EC_KEY object
+ *               will use an own copy of the EC_POINT object).
+ *  \return 1 on success and 0 if an error occurred.
+ */
+int EC_KEY_set_public_key(EC_KEY *key, const EC_POINT *pub);
+
+unsigned EC_KEY_get_enc_flags(const EC_KEY *key);
+void EC_KEY_set_enc_flags(EC_KEY *eckey, unsigned int flags);
+point_conversion_form_t EC_KEY_get_conv_form(const EC_KEY *key);
+void EC_KEY_set_conv_form(EC_KEY *eckey, point_conversion_form_t cform);
+/* functions to set/get method specific data  */
+void *EC_KEY_get_key_method_data(EC_KEY *key,
+                                 void *(*dup_func) (void *),
+                                 void (*free_func) (void *),
+                                 void (*clear_free_func) (void *));
+/** Sets the key method data of an EC_KEY object, if none has yet been set.
+ *  \param  key              EC_KEY object
+ *  \param  data             opaque data to install.
+ *  \param  dup_func         a function that duplicates |data|.
+ *  \param  free_func        a function that frees |data|.
+ *  \param  clear_free_func  a function that wipes and frees |data|.
+ *  \return the previously set data pointer, or NULL if |data| was inserted.
+ */
+void *EC_KEY_insert_key_method_data(EC_KEY *key, void *data,
+                                    void *(*dup_func) (void *),
+                                    void (*free_func) (void *),
+                                    void (*clear_free_func) (void *));
+/* wrapper functions for the underlying EC_GROUP object */
+void EC_KEY_set_asn1_flag(EC_KEY *eckey, int asn1_flag);
+
+/** Creates a table of pre-computed multiples of the generator to
+ *  accelerate further EC_KEY operations.
+ *  \param  key  EC_KEY object
+ *  \param  ctx  BN_CTX object (optional)
+ *  \return 1 on success and 0 if an error occurred.
+ */
+int EC_KEY_precompute_mult(EC_KEY *key, BN_CTX *ctx);
+
+/** Creates a new ec private (and optional a new public) key.
+ *  \param  key  EC_KEY object
+ *  \return 1 on success and 0 if an error occurred.
+ */
+int EC_KEY_generate_key(EC_KEY *key);
+
+/** Verifies that a private and/or public key is valid.
+ *  \param  key  the EC_KEY object
+ *  \return 1 on success and 0 otherwise.
+ */
+int EC_KEY_check_key(const EC_KEY *key);
+
+/** Sets a public key from affine coordindates performing
+ *  neccessary NIST PKV tests.
+ *  \param  key  the EC_KEY object
+ *  \param  x    public key x coordinate
+ *  \param  y    public key y coordinate
+ *  \return 1 on success and 0 otherwise.
+ */
+int EC_KEY_set_public_key_affine_coordinates(EC_KEY *key, BIGNUM *x,
+                                             BIGNUM *y);
+
+/********************************************************************/
+/*        de- and encoding functions for SEC1 ECPrivateKey          */
+/********************************************************************/
+
+/** Decodes a private key from a memory buffer.
+ *  \param  key  a pointer to a EC_KEY object which should be used (or NULL)
+ *  \param  in   pointer to memory with the DER encoded private key
+ *  \param  len  length of the DER encoded private key
+ *  \return the decoded private key or NULL if an error occurred.
+ */
+EC_KEY *d2i_ECPrivateKey(EC_KEY **key, const unsigned char **in, long len);
+
+/** Encodes a private key object and stores the result in a buffer.
+ *  \param  key  the EC_KEY object to encode
+ *  \param  out  the buffer for the result (if NULL the function returns number
+ *               of bytes needed).
+ *  \return 1 on success and 0 if an error occurred.
+ */
+int i2d_ECPrivateKey(EC_KEY *key, unsigned char **out);
+
+/********************************************************************/
+/*        de- and encoding functions for EC parameters              */
+/********************************************************************/
+
+/** Decodes ec parameter from a memory buffer.
+ *  \param  key  a pointer to a EC_KEY object which should be used (or NULL)
+ *  \param  in   pointer to memory with the DER encoded ec parameters
+ *  \param  len  length of the DER encoded ec parameters
+ *  \return a EC_KEY object with the decoded parameters or NULL if an error
+ *          occurred.
+ */
+EC_KEY *d2i_ECParameters(EC_KEY **key, const unsigned char **in, long len);
+
+/** Encodes ec parameter and stores the result in a buffer.
+ *  \param  key  the EC_KEY object with ec paramters to encode
+ *  \param  out  the buffer for the result (if NULL the function returns number
+ *               of bytes needed).
+ *  \return 1 on success and 0 if an error occurred.
+ */
+int i2d_ECParameters(EC_KEY *key, unsigned char **out);
+
+/********************************************************************/
+/*         de- and encoding functions for EC public key             */
+/*         (octet string, not DER -- hence 'o2i' and 'i2o')         */
+/********************************************************************/
+
+/** Decodes a ec public key from a octet string.
+ *  \param  key  a pointer to a EC_KEY object which should be used
+ *  \param  in   memory buffer with the encoded public key
+ *  \param  len  length of the encoded public key
+ *  \return EC_KEY object with decoded public key or NULL if an error
+ *          occurred.
+ */
+EC_KEY *o2i_ECPublicKey(EC_KEY **key, const unsigned char **in, long len);
+
+/** Encodes a ec public key in an octet string.
+ *  \param  key  the EC_KEY object with the public key
+ *  \param  out  the buffer for the result (if NULL the function returns number
+ *               of bytes needed).
+ *  \return 1 on success and 0 if an error occurred
+ */
+int i2o_ECPublicKey(EC_KEY *key, unsigned char **out);
+
+# ifndef OPENSSL_NO_BIO
+/** Prints out the ec parameters on human readable form.
+ *  \param  bp   BIO object to which the information is printed
+ *  \param  key  EC_KEY object
+ *  \return 1 on success and 0 if an error occurred
+ */
+int ECParameters_print(BIO *bp, const EC_KEY *key);
+
+/** Prints out the contents of a EC_KEY object
+ *  \param  bp   BIO object to which the information is printed
+ *  \param  key  EC_KEY object
+ *  \param  off  line offset
+ *  \return 1 on success and 0 if an error occurred
+ */
+int EC_KEY_print(BIO *bp, const EC_KEY *key, int off);
+
+# endif
+# ifndef OPENSSL_NO_FP_API
+/** Prints out the ec parameters on human readable form.
+ *  \param  fp   file descriptor to which the information is printed
+ *  \param  key  EC_KEY object
+ *  \return 1 on success and 0 if an error occurred
+ */
+int ECParameters_print_fp(FILE *fp, const EC_KEY *key);
+
+/** Prints out the contents of a EC_KEY object
+ *  \param  fp   file descriptor to which the information is printed
+ *  \param  key  EC_KEY object
+ *  \param  off  line offset
+ *  \return 1 on success and 0 if an error occurred
+ */
+int EC_KEY_print_fp(FILE *fp, const EC_KEY *key, int off);
+
+# endif
+
+# define ECParameters_dup(x) ASN1_dup_of(EC_KEY,i2d_ECParameters,d2i_ECParameters,x)
+
+# ifndef __cplusplus
+#  if defined(__SUNPRO_C)
+#   if __SUNPRO_C >= 0x520
+#    pragma error_messages (default,E_ARRAY_OF_INCOMPLETE_NONAME,E_ARRAY_OF_INCOMPLETE)
+#   endif
+#  endif
+# endif
+
+# define EVP_PKEY_CTX_set_ec_paramgen_curve_nid(ctx, nid) \
+        EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_EC, \
+                                EVP_PKEY_OP_PARAMGEN|EVP_PKEY_OP_KEYGEN, \
+                                EVP_PKEY_CTRL_EC_PARAMGEN_CURVE_NID, nid, NULL)
+
+# define EVP_PKEY_CTX_set_ec_param_enc(ctx, flag) \
+        EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_EC, \
+                                EVP_PKEY_OP_PARAMGEN|EVP_PKEY_OP_KEYGEN, \
+                                EVP_PKEY_CTRL_EC_PARAM_ENC, flag, NULL)
+
+# define EVP_PKEY_CTX_set_ecdh_cofactor_mode(ctx, flag) \
+        EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_EC, \
+                                EVP_PKEY_OP_DERIVE, \
+                                EVP_PKEY_CTRL_EC_ECDH_COFACTOR, flag, NULL)
+
+# define EVP_PKEY_CTX_get_ecdh_cofactor_mode(ctx) \
+        EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_EC, \
+                                EVP_PKEY_OP_DERIVE, \
+                                EVP_PKEY_CTRL_EC_ECDH_COFACTOR, -2, NULL)
+
+# define EVP_PKEY_CTX_set_ecdh_kdf_type(ctx, kdf) \
+        EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_EC, \
+                                EVP_PKEY_OP_DERIVE, \
+                                EVP_PKEY_CTRL_EC_KDF_TYPE, kdf, NULL)
+
+# define EVP_PKEY_CTX_get_ecdh_kdf_type(ctx) \
+        EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_EC, \
+                                EVP_PKEY_OP_DERIVE, \
+                                EVP_PKEY_CTRL_EC_KDF_TYPE, -2, NULL)
+
+# define EVP_PKEY_CTX_set_ecdh_kdf_md(ctx, md) \
+        EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_EC, \
+                                EVP_PKEY_OP_DERIVE, \
+                                EVP_PKEY_CTRL_EC_KDF_MD, 0, (void *)md)
+
+# define EVP_PKEY_CTX_get_ecdh_kdf_md(ctx, pmd) \
+        EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_EC, \
+                                EVP_PKEY_OP_DERIVE, \
+                                EVP_PKEY_CTRL_GET_EC_KDF_MD, 0, (void *)pmd)
+
+# define EVP_PKEY_CTX_set_ecdh_kdf_outlen(ctx, len) \
+        EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_EC, \
+                                EVP_PKEY_OP_DERIVE, \
+                                EVP_PKEY_CTRL_EC_KDF_OUTLEN, len, NULL)
+
+# define EVP_PKEY_CTX_get_ecdh_kdf_outlen(ctx, plen) \
+        EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_EC, \
+                                EVP_PKEY_OP_DERIVE, \
+                        EVP_PKEY_CTRL_GET_EC_KDF_OUTLEN, 0, (void *)plen)
+
+# define EVP_PKEY_CTX_set0_ecdh_kdf_ukm(ctx, p, plen) \
+        EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_EC, \
+                                EVP_PKEY_OP_DERIVE, \
+                                EVP_PKEY_CTRL_EC_KDF_UKM, plen, (void *)p)
+
+# define EVP_PKEY_CTX_get0_ecdh_kdf_ukm(ctx, p) \
+        EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_EC, \
+                                EVP_PKEY_OP_DERIVE, \
+                                EVP_PKEY_CTRL_GET_EC_KDF_UKM, 0, (void *)p)
+
+# define EVP_PKEY_CTRL_EC_PARAMGEN_CURVE_NID             (EVP_PKEY_ALG_CTRL + 1)
+# define EVP_PKEY_CTRL_EC_PARAM_ENC                      (EVP_PKEY_ALG_CTRL + 2)
+# define EVP_PKEY_CTRL_EC_ECDH_COFACTOR                  (EVP_PKEY_ALG_CTRL + 3)
+# define EVP_PKEY_CTRL_EC_KDF_TYPE                       (EVP_PKEY_ALG_CTRL + 4)
+# define EVP_PKEY_CTRL_EC_KDF_MD                         (EVP_PKEY_ALG_CTRL + 5)
+# define EVP_PKEY_CTRL_GET_EC_KDF_MD                     (EVP_PKEY_ALG_CTRL + 6)
+# define EVP_PKEY_CTRL_EC_KDF_OUTLEN                     (EVP_PKEY_ALG_CTRL + 7)
+# define EVP_PKEY_CTRL_GET_EC_KDF_OUTLEN                 (EVP_PKEY_ALG_CTRL + 8)
+# define EVP_PKEY_CTRL_EC_KDF_UKM                        (EVP_PKEY_ALG_CTRL + 9)
+# define EVP_PKEY_CTRL_GET_EC_KDF_UKM                    (EVP_PKEY_ALG_CTRL + 10)
+/* KDF types */
+# define EVP_PKEY_ECDH_KDF_NONE                          1
+# define EVP_PKEY_ECDH_KDF_X9_62                         2
+
+/* BEGIN ERROR CODES */
+/*
+ * The following lines are auto generated by the script mkerr.pl. Any changes
+ * made after this point may be overwritten when the script is next run.
+ */
+
+void ERR_load_EC_strings(void);
+
+/* Error codes for the EC functions. */
+
+/* Function codes. */
+# define EC_F_BN_TO_FELEM                                 224
+# define EC_F_COMPUTE_WNAF                                143
+# define EC_F_D2I_ECPARAMETERS                            144
+# define EC_F_D2I_ECPKPARAMETERS                          145
+# define EC_F_D2I_ECPRIVATEKEY                            146
+# define EC_F_DO_EC_KEY_PRINT                             221
+# define EC_F_ECDH_CMS_DECRYPT                            238
+# define EC_F_ECDH_CMS_SET_SHARED_INFO                    239
+# define EC_F_ECKEY_PARAM2TYPE                            223
+# define EC_F_ECKEY_PARAM_DECODE                          212
+# define EC_F_ECKEY_PRIV_DECODE                           213
+# define EC_F_ECKEY_PRIV_ENCODE                           214
+# define EC_F_ECKEY_PUB_DECODE                            215
+# define EC_F_ECKEY_PUB_ENCODE                            216
+# define EC_F_ECKEY_TYPE2PARAM                            220
+# define EC_F_ECPARAMETERS_PRINT                          147
+# define EC_F_ECPARAMETERS_PRINT_FP                       148
+# define EC_F_ECPKPARAMETERS_PRINT                        149
+# define EC_F_ECPKPARAMETERS_PRINT_FP                     150
+# define EC_F_ECP_NISTZ256_GET_AFFINE                     240
+# define EC_F_ECP_NISTZ256_MULT_PRECOMPUTE                243
+# define EC_F_ECP_NISTZ256_POINTS_MUL                     241
+# define EC_F_ECP_NISTZ256_PRE_COMP_NEW                   244
+# define EC_F_ECP_NISTZ256_SET_WORDS                      245
+# define EC_F_ECP_NISTZ256_WINDOWED_MUL                   242
+# define EC_F_ECP_NIST_MOD_192                            203
+# define EC_F_ECP_NIST_MOD_224                            204
+# define EC_F_ECP_NIST_MOD_256                            205
+# define EC_F_ECP_NIST_MOD_521                            206
+# define EC_F_EC_ASN1_GROUP2CURVE                         153
+# define EC_F_EC_ASN1_GROUP2FIELDID                       154
+# define EC_F_EC_ASN1_GROUP2PARAMETERS                    155
+# define EC_F_EC_ASN1_GROUP2PKPARAMETERS                  156
+# define EC_F_EC_ASN1_PARAMETERS2GROUP                    157
+# define EC_F_EC_ASN1_PKPARAMETERS2GROUP                  158
+# define EC_F_EC_EX_DATA_SET_DATA                         211
+# define EC_F_EC_GF2M_MONTGOMERY_POINT_MULTIPLY           208
+# define EC_F_EC_GF2M_SIMPLE_GROUP_CHECK_DISCRIMINANT     159
+# define EC_F_EC_GF2M_SIMPLE_GROUP_SET_CURVE              195
+# define EC_F_EC_GF2M_SIMPLE_OCT2POINT                    160
+# define EC_F_EC_GF2M_SIMPLE_POINT2OCT                    161
+# define EC_F_EC_GF2M_SIMPLE_POINT_GET_AFFINE_COORDINATES 162
+# define EC_F_EC_GF2M_SIMPLE_POINT_SET_AFFINE_COORDINATES 163
+# define EC_F_EC_GF2M_SIMPLE_SET_COMPRESSED_COORDINATES   164
+# define EC_F_EC_GFP_MONT_FIELD_DECODE                    133
+# define EC_F_EC_GFP_MONT_FIELD_ENCODE                    134
+# define EC_F_EC_GFP_MONT_FIELD_MUL                       131
+# define EC_F_EC_GFP_MONT_FIELD_SET_TO_ONE                209
+# define EC_F_EC_GFP_MONT_FIELD_SQR                       132
+# define EC_F_EC_GFP_MONT_GROUP_SET_CURVE                 189
+# define EC_F_EC_GFP_MONT_GROUP_SET_CURVE_GFP             135
+# define EC_F_EC_GFP_NISTP224_GROUP_SET_CURVE             225
+# define EC_F_EC_GFP_NISTP224_POINTS_MUL                  228
+# define EC_F_EC_GFP_NISTP224_POINT_GET_AFFINE_COORDINATES 226
+# define EC_F_EC_GFP_NISTP256_GROUP_SET_CURVE             230
+# define EC_F_EC_GFP_NISTP256_POINTS_MUL                  231
+# define EC_F_EC_GFP_NISTP256_POINT_GET_AFFINE_COORDINATES 232
+# define EC_F_EC_GFP_NISTP521_GROUP_SET_CURVE             233
+# define EC_F_EC_GFP_NISTP521_POINTS_MUL                  234
+# define EC_F_EC_GFP_NISTP521_POINT_GET_AFFINE_COORDINATES 235
+# define EC_F_EC_GFP_NIST_FIELD_MUL                       200
+# define EC_F_EC_GFP_NIST_FIELD_SQR                       201
+# define EC_F_EC_GFP_NIST_GROUP_SET_CURVE                 202
+# define EC_F_EC_GFP_SIMPLE_GROUP_CHECK_DISCRIMINANT      165
+# define EC_F_EC_GFP_SIMPLE_GROUP_SET_CURVE               166
+# define EC_F_EC_GFP_SIMPLE_GROUP_SET_CURVE_GFP           100
+# define EC_F_EC_GFP_SIMPLE_GROUP_SET_GENERATOR           101
+# define EC_F_EC_GFP_SIMPLE_MAKE_AFFINE                   102
+# define EC_F_EC_GFP_SIMPLE_OCT2POINT                     103
+# define EC_F_EC_GFP_SIMPLE_POINT2OCT                     104
+# define EC_F_EC_GFP_SIMPLE_POINTS_MAKE_AFFINE            137
+# define EC_F_EC_GFP_SIMPLE_POINT_GET_AFFINE_COORDINATES  167
+# define EC_F_EC_GFP_SIMPLE_POINT_GET_AFFINE_COORDINATES_GFP 105
+# define EC_F_EC_GFP_SIMPLE_POINT_SET_AFFINE_COORDINATES  168
+# define EC_F_EC_GFP_SIMPLE_POINT_SET_AFFINE_COORDINATES_GFP 128
+# define EC_F_EC_GFP_SIMPLE_SET_COMPRESSED_COORDINATES    169
+# define EC_F_EC_GFP_SIMPLE_SET_COMPRESSED_COORDINATES_GFP 129
+# define EC_F_EC_GROUP_CHECK                              170
+# define EC_F_EC_GROUP_CHECK_DISCRIMINANT                 171
+# define EC_F_EC_GROUP_COPY                               106
+# define EC_F_EC_GROUP_GET0_GENERATOR                     139
+# define EC_F_EC_GROUP_GET_COFACTOR                       140
+# define EC_F_EC_GROUP_GET_CURVE_GF2M                     172
+# define EC_F_EC_GROUP_GET_CURVE_GFP                      130
+# define EC_F_EC_GROUP_GET_DEGREE                         173
+# define EC_F_EC_GROUP_GET_ORDER                          141
+# define EC_F_EC_GROUP_GET_PENTANOMIAL_BASIS              193
+# define EC_F_EC_GROUP_GET_TRINOMIAL_BASIS                194
+# define EC_F_EC_GROUP_NEW                                108
+# define EC_F_EC_GROUP_NEW_BY_CURVE_NAME                  174
+# define EC_F_EC_GROUP_NEW_FROM_DATA                      175
+# define EC_F_EC_GROUP_PRECOMPUTE_MULT                    142
+# define EC_F_EC_GROUP_SET_CURVE_GF2M                     176
+# define EC_F_EC_GROUP_SET_CURVE_GFP                      109
+# define EC_F_EC_GROUP_SET_EXTRA_DATA                     110
+# define EC_F_EC_GROUP_SET_GENERATOR                      111
+# define EC_F_EC_KEY_CHECK_KEY                            177
+# define EC_F_EC_KEY_COPY                                 178
+# define EC_F_EC_KEY_GENERATE_KEY                         179
+# define EC_F_EC_KEY_NEW                                  182
+# define EC_F_EC_KEY_PRINT                                180
+# define EC_F_EC_KEY_PRINT_FP                             181
+# define EC_F_EC_KEY_SET_PUBLIC_KEY_AFFINE_COORDINATES    229
+# define EC_F_EC_POINTS_MAKE_AFFINE                       136
+# define EC_F_EC_POINT_ADD                                112
+# define EC_F_EC_POINT_CMP                                113
+# define EC_F_EC_POINT_COPY                               114
+# define EC_F_EC_POINT_DBL                                115
+# define EC_F_EC_POINT_GET_AFFINE_COORDINATES_GF2M        183
+# define EC_F_EC_POINT_GET_AFFINE_COORDINATES_GFP         116
+# define EC_F_EC_POINT_GET_JPROJECTIVE_COORDINATES_GFP    117
+# define EC_F_EC_POINT_INVERT                             210
+# define EC_F_EC_POINT_IS_AT_INFINITY                     118
+# define EC_F_EC_POINT_IS_ON_CURVE                        119
+# define EC_F_EC_POINT_MAKE_AFFINE                        120
+# define EC_F_EC_POINT_MUL                                184
+# define EC_F_EC_POINT_NEW                                121
+# define EC_F_EC_POINT_OCT2POINT                          122
+# define EC_F_EC_POINT_POINT2OCT                          123
+# define EC_F_EC_POINT_SET_AFFINE_COORDINATES_GF2M        185
+# define EC_F_EC_POINT_SET_AFFINE_COORDINATES_GFP         124
+# define EC_F_EC_POINT_SET_COMPRESSED_COORDINATES_GF2M    186
+# define EC_F_EC_POINT_SET_COMPRESSED_COORDINATES_GFP     125
+# define EC_F_EC_POINT_SET_JPROJECTIVE_COORDINATES_GFP    126
+# define EC_F_EC_POINT_SET_TO_INFINITY                    127
+# define EC_F_EC_PRE_COMP_DUP                             207
+# define EC_F_EC_PRE_COMP_NEW                             196
+# define EC_F_EC_WNAF_MUL                                 187
+# define EC_F_EC_WNAF_PRECOMPUTE_MULT                     188
+# define EC_F_I2D_ECPARAMETERS                            190
+# define EC_F_I2D_ECPKPARAMETERS                          191
+# define EC_F_I2D_ECPRIVATEKEY                            192
+# define EC_F_I2O_ECPUBLICKEY                             151
+# define EC_F_NISTP224_PRE_COMP_NEW                       227
+# define EC_F_NISTP256_PRE_COMP_NEW                       236
+# define EC_F_NISTP521_PRE_COMP_NEW                       237
+# define EC_F_O2I_ECPUBLICKEY                             152
+# define EC_F_OLD_EC_PRIV_DECODE                          222
+# define EC_F_PKEY_EC_CTRL                                197
+# define EC_F_PKEY_EC_CTRL_STR                            198
+# define EC_F_PKEY_EC_DERIVE                              217
+# define EC_F_PKEY_EC_KEYGEN                              199
+# define EC_F_PKEY_EC_PARAMGEN                            219
+# define EC_F_PKEY_EC_SIGN                                218
+
+/* Reason codes. */
+# define EC_R_ASN1_ERROR                                  115
+# define EC_R_ASN1_UNKNOWN_FIELD                          116
+# define EC_R_BIGNUM_OUT_OF_RANGE                         144
+# define EC_R_BUFFER_TOO_SMALL                            100
+# define EC_R_COORDINATES_OUT_OF_RANGE                    146
+# define EC_R_D2I_ECPKPARAMETERS_FAILURE                  117
+# define EC_R_DECODE_ERROR                                142
+# define EC_R_DISCRIMINANT_IS_ZERO                        118
+# define EC_R_EC_GROUP_NEW_BY_NAME_FAILURE                119
+# define EC_R_FIELD_TOO_LARGE                             143
+# define EC_R_GF2M_NOT_SUPPORTED                          147
+# define EC_R_GROUP2PKPARAMETERS_FAILURE                  120
+# define EC_R_I2D_ECPKPARAMETERS_FAILURE                  121
+# define EC_R_INCOMPATIBLE_OBJECTS                        101
+# define EC_R_INVALID_ARGUMENT                            112
+# define EC_R_INVALID_COMPRESSED_POINT                    110
+# define EC_R_INVALID_COMPRESSION_BIT                     109
+# define EC_R_INVALID_CURVE                               141
+# define EC_R_INVALID_DIGEST                              151
+# define EC_R_INVALID_DIGEST_TYPE                         138
+# define EC_R_INVALID_ENCODING                            102
+# define EC_R_INVALID_FIELD                               103
+# define EC_R_INVALID_FORM                                104
+# define EC_R_INVALID_GROUP_ORDER                         122
+# define EC_R_INVALID_PENTANOMIAL_BASIS                   132
+# define EC_R_INVALID_PRIVATE_KEY                         123
+# define EC_R_INVALID_TRINOMIAL_BASIS                     137
+# define EC_R_KDF_PARAMETER_ERROR                         148
+# define EC_R_KEYS_NOT_SET                                140
+# define EC_R_MISSING_PARAMETERS                          124
+# define EC_R_MISSING_PRIVATE_KEY                         125
+# define EC_R_NOT_A_NIST_PRIME                            135
+# define EC_R_NOT_A_SUPPORTED_NIST_PRIME                  136
+# define EC_R_NOT_IMPLEMENTED                             126
+# define EC_R_NOT_INITIALIZED                             111
+# define EC_R_NO_FIELD_MOD                                133
+# define EC_R_NO_PARAMETERS_SET                           139
+# define EC_R_PASSED_NULL_PARAMETER                       134
+# define EC_R_PEER_KEY_ERROR                              149
+# define EC_R_PKPARAMETERS2GROUP_FAILURE                  127
+# define EC_R_POINT_AT_INFINITY                           106
+# define EC_R_POINT_IS_NOT_ON_CURVE                       107
+# define EC_R_SHARED_INFO_ERROR                           150
+# define EC_R_SLOT_FULL                                   108
+# define EC_R_UNDEFINED_GENERATOR                         113
+# define EC_R_UNDEFINED_ORDER                             128
+# define EC_R_UNKNOWN_COFACTOR                            152
+# define EC_R_UNKNOWN_GROUP                               129
+# define EC_R_UNKNOWN_ORDER                               114
+# define EC_R_UNSUPPORTED_FIELD                           131
+# define EC_R_WRONG_CURVE_PARAMETERS                      145
+# define EC_R_WRONG_ORDER                                 130
+
+# ifdef  __cplusplus
+}
+# endif
+#endif

+ 134 - 0
libssh2/openssl/include/openssl/ecdh.h

@@ -0,0 +1,134 @@
+/* crypto/ecdh/ecdh.h */
+/* ====================================================================
+ * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED.
+ *
+ * The Elliptic Curve Public-Key Crypto Library (ECC Code) included
+ * herein is developed by SUN MICROSYSTEMS, INC., and is contributed
+ * to the OpenSSL project.
+ *
+ * The ECC Code is licensed pursuant to the OpenSSL open source
+ * license provided below.
+ *
+ * The ECDH software is originally written by Douglas Stebila of
+ * Sun Microsystems Laboratories.
+ *
+ */
+/* ====================================================================
+ * Copyright (c) 2000-2002 The OpenSSL 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. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    licensing@OpenSSL.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED 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 OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS 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.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com).  This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+#ifndef HEADER_ECDH_H
+# define HEADER_ECDH_H
+
+# include <openssl/opensslconf.h>
+
+# ifdef OPENSSL_NO_ECDH
+#  error ECDH is disabled.
+# endif
+
+# include <openssl/ec.h>
+# include <openssl/ossl_typ.h>
+# ifndef OPENSSL_NO_DEPRECATED
+#  include <openssl/bn.h>
+# endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+# define EC_FLAG_COFACTOR_ECDH   0x1000
+
+const ECDH_METHOD *ECDH_OpenSSL(void);
+
+void ECDH_set_default_method(const ECDH_METHOD *);
+const ECDH_METHOD *ECDH_get_default_method(void);
+int ECDH_set_method(EC_KEY *, const ECDH_METHOD *);
+
+int ECDH_compute_key(void *out, size_t outlen, const EC_POINT *pub_key,
+                     EC_KEY *ecdh, void *(*KDF) (const void *in, size_t inlen,
+                                                 void *out, size_t *outlen));
+
+int ECDH_get_ex_new_index(long argl, void *argp, CRYPTO_EX_new
+                          *new_func, CRYPTO_EX_dup *dup_func,
+                          CRYPTO_EX_free *free_func);
+int ECDH_set_ex_data(EC_KEY *d, int idx, void *arg);
+void *ECDH_get_ex_data(EC_KEY *d, int idx);
+
+int ECDH_KDF_X9_62(unsigned char *out, size_t outlen,
+                   const unsigned char *Z, size_t Zlen,
+                   const unsigned char *sinfo, size_t sinfolen,
+                   const EVP_MD *md);
+
+/* BEGIN ERROR CODES */
+/*
+ * The following lines are auto generated by the script mkerr.pl. Any changes
+ * made after this point may be overwritten when the script is next run.
+ */
+void ERR_load_ECDH_strings(void);
+
+/* Error codes for the ECDH functions. */
+
+/* Function codes. */
+# define ECDH_F_ECDH_CHECK                                102
+# define ECDH_F_ECDH_COMPUTE_KEY                          100
+# define ECDH_F_ECDH_DATA_NEW_METHOD                      101
+
+/* Reason codes. */
+# define ECDH_R_KDF_FAILED                                102
+# define ECDH_R_NON_FIPS_METHOD                           103
+# define ECDH_R_NO_PRIVATE_VALUE                          100
+# define ECDH_R_POINT_ARITHMETIC_FAILURE                  101
+
+#ifdef  __cplusplus
+}
+#endif
+#endif

+ 335 - 0
libssh2/openssl/include/openssl/ecdsa.h

@@ -0,0 +1,335 @@
+/* crypto/ecdsa/ecdsa.h */
+/**
+ * \file   crypto/ecdsa/ecdsa.h Include file for the OpenSSL ECDSA functions
+ * \author Written by Nils Larsch for the OpenSSL project
+ */
+/* ====================================================================
+ * Copyright (c) 2000-2005 The OpenSSL 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. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    licensing@OpenSSL.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED 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 OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS 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.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com).  This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+#ifndef HEADER_ECDSA_H
+# define HEADER_ECDSA_H
+
+# include <openssl/opensslconf.h>
+
+# ifdef OPENSSL_NO_ECDSA
+#  error ECDSA is disabled.
+# endif
+
+# include <openssl/ec.h>
+# include <openssl/ossl_typ.h>
+# ifndef OPENSSL_NO_DEPRECATED
+#  include <openssl/bn.h>
+# endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef struct ECDSA_SIG_st {
+    BIGNUM *r;
+    BIGNUM *s;
+} ECDSA_SIG;
+
+/** Allocates and initialize a ECDSA_SIG structure
+ *  \return pointer to a ECDSA_SIG structure or NULL if an error occurred
+ */
+ECDSA_SIG *ECDSA_SIG_new(void);
+
+/** frees a ECDSA_SIG structure
+ *  \param  sig  pointer to the ECDSA_SIG structure
+ */
+void ECDSA_SIG_free(ECDSA_SIG *sig);
+
+/** DER encode content of ECDSA_SIG object (note: this function modifies *pp
+ *  (*pp += length of the DER encoded signature)).
+ *  \param  sig  pointer to the ECDSA_SIG object
+ *  \param  pp   pointer to a unsigned char pointer for the output or NULL
+ *  \return the length of the DER encoded ECDSA_SIG object or 0
+ */
+int i2d_ECDSA_SIG(const ECDSA_SIG *sig, unsigned char **pp);
+
+/** Decodes a DER encoded ECDSA signature (note: this function changes *pp
+ *  (*pp += len)).
+ *  \param  sig  pointer to ECDSA_SIG pointer (may be NULL)
+ *  \param  pp   memory buffer with the DER encoded signature
+ *  \param  len  length of the buffer
+ *  \return pointer to the decoded ECDSA_SIG structure (or NULL)
+ */
+ECDSA_SIG *d2i_ECDSA_SIG(ECDSA_SIG **sig, const unsigned char **pp, long len);
+
+/** Computes the ECDSA signature of the given hash value using
+ *  the supplied private key and returns the created signature.
+ *  \param  dgst      pointer to the hash value
+ *  \param  dgst_len  length of the hash value
+ *  \param  eckey     EC_KEY object containing a private EC key
+ *  \return pointer to a ECDSA_SIG structure or NULL if an error occurred
+ */
+ECDSA_SIG *ECDSA_do_sign(const unsigned char *dgst, int dgst_len,
+                         EC_KEY *eckey);
+
+/** Computes ECDSA signature of a given hash value using the supplied
+ *  private key (note: sig must point to ECDSA_size(eckey) bytes of memory).
+ *  \param  dgst     pointer to the hash value to sign
+ *  \param  dgstlen  length of the hash value
+ *  \param  kinv     BIGNUM with a pre-computed inverse k (optional)
+ *  \param  rp       BIGNUM with a pre-computed rp value (optioanl),
+ *                   see ECDSA_sign_setup
+ *  \param  eckey    EC_KEY object containing a private EC key
+ *  \return pointer to a ECDSA_SIG structure or NULL if an error occurred
+ */
+ECDSA_SIG *ECDSA_do_sign_ex(const unsigned char *dgst, int dgstlen,
+                            const BIGNUM *kinv, const BIGNUM *rp,
+                            EC_KEY *eckey);
+
+/** Verifies that the supplied signature is a valid ECDSA
+ *  signature of the supplied hash value using the supplied public key.
+ *  \param  dgst      pointer to the hash value
+ *  \param  dgst_len  length of the hash value
+ *  \param  sig       ECDSA_SIG structure
+ *  \param  eckey     EC_KEY object containing a public EC key
+ *  \return 1 if the signature is valid, 0 if the signature is invalid
+ *          and -1 on error
+ */
+int ECDSA_do_verify(const unsigned char *dgst, int dgst_len,
+                    const ECDSA_SIG *sig, EC_KEY *eckey);
+
+const ECDSA_METHOD *ECDSA_OpenSSL(void);
+
+/** Sets the default ECDSA method
+ *  \param  meth  new default ECDSA_METHOD
+ */
+void ECDSA_set_default_method(const ECDSA_METHOD *meth);
+
+/** Returns the default ECDSA method
+ *  \return pointer to ECDSA_METHOD structure containing the default method
+ */
+const ECDSA_METHOD *ECDSA_get_default_method(void);
+
+/** Sets method to be used for the ECDSA operations
+ *  \param  eckey  EC_KEY object
+ *  \param  meth   new method
+ *  \return 1 on success and 0 otherwise
+ */
+int ECDSA_set_method(EC_KEY *eckey, const ECDSA_METHOD *meth);
+
+/** Returns the maximum length of the DER encoded signature
+ *  \param  eckey  EC_KEY object
+ *  \return numbers of bytes required for the DER encoded signature
+ */
+int ECDSA_size(const EC_KEY *eckey);
+
+/** Precompute parts of the signing operation
+ *  \param  eckey  EC_KEY object containing a private EC key
+ *  \param  ctx    BN_CTX object (optional)
+ *  \param  kinv   BIGNUM pointer for the inverse of k
+ *  \param  rp     BIGNUM pointer for x coordinate of k * generator
+ *  \return 1 on success and 0 otherwise
+ */
+int ECDSA_sign_setup(EC_KEY *eckey, BN_CTX *ctx, BIGNUM **kinv, BIGNUM **rp);
+
+/** Computes ECDSA signature of a given hash value using the supplied
+ *  private key (note: sig must point to ECDSA_size(eckey) bytes of memory).
+ *  \param  type     this parameter is ignored
+ *  \param  dgst     pointer to the hash value to sign
+ *  \param  dgstlen  length of the hash value
+ *  \param  sig      memory for the DER encoded created signature
+ *  \param  siglen   pointer to the length of the returned signature
+ *  \param  eckey    EC_KEY object containing a private EC key
+ *  \return 1 on success and 0 otherwise
+ */
+int ECDSA_sign(int type, const unsigned char *dgst, int dgstlen,
+               unsigned char *sig, unsigned int *siglen, EC_KEY *eckey);
+
+/** Computes ECDSA signature of a given hash value using the supplied
+ *  private key (note: sig must point to ECDSA_size(eckey) bytes of memory).
+ *  \param  type     this parameter is ignored
+ *  \param  dgst     pointer to the hash value to sign
+ *  \param  dgstlen  length of the hash value
+ *  \param  sig      buffer to hold the DER encoded signature
+ *  \param  siglen   pointer to the length of the returned signature
+ *  \param  kinv     BIGNUM with a pre-computed inverse k (optional)
+ *  \param  rp       BIGNUM with a pre-computed rp value (optioanl),
+ *                   see ECDSA_sign_setup
+ *  \param  eckey    EC_KEY object containing a private EC key
+ *  \return 1 on success and 0 otherwise
+ */
+int ECDSA_sign_ex(int type, const unsigned char *dgst, int dgstlen,
+                  unsigned char *sig, unsigned int *siglen,
+                  const BIGNUM *kinv, const BIGNUM *rp, EC_KEY *eckey);
+
+/** Verifies that the given signature is valid ECDSA signature
+ *  of the supplied hash value using the specified public key.
+ *  \param  type     this parameter is ignored
+ *  \param  dgst     pointer to the hash value
+ *  \param  dgstlen  length of the hash value
+ *  \param  sig      pointer to the DER encoded signature
+ *  \param  siglen   length of the DER encoded signature
+ *  \param  eckey    EC_KEY object containing a public EC key
+ *  \return 1 if the signature is valid, 0 if the signature is invalid
+ *          and -1 on error
+ */
+int ECDSA_verify(int type, const unsigned char *dgst, int dgstlen,
+                 const unsigned char *sig, int siglen, EC_KEY *eckey);
+
+/* the standard ex_data functions */
+int ECDSA_get_ex_new_index(long argl, void *argp, CRYPTO_EX_new
+                           *new_func, CRYPTO_EX_dup *dup_func,
+                           CRYPTO_EX_free *free_func);
+int ECDSA_set_ex_data(EC_KEY *d, int idx, void *arg);
+void *ECDSA_get_ex_data(EC_KEY *d, int idx);
+
+/** Allocates and initialize a ECDSA_METHOD structure
+ *  \param ecdsa_method pointer to ECDSA_METHOD to copy.  (May be NULL)
+ *  \return pointer to a ECDSA_METHOD structure or NULL if an error occurred
+ */
+
+ECDSA_METHOD *ECDSA_METHOD_new(const ECDSA_METHOD *ecdsa_method);
+
+/** frees a ECDSA_METHOD structure
+ *  \param  ecdsa_method  pointer to the ECDSA_METHOD structure
+ */
+void ECDSA_METHOD_free(ECDSA_METHOD *ecdsa_method);
+
+/**  Sets application specific data in the ECDSA_METHOD
+ *   \param  ecdsa_method pointer to existing ECDSA_METHOD
+ *   \param  app application specific data to set
+ */
+
+void ECDSA_METHOD_set_app_data(ECDSA_METHOD *ecdsa_method, void *app);
+
+/** Returns application specific data from a ECDSA_METHOD structure
+ *  \param ecdsa_method pointer to ECDSA_METHOD structure
+ *  \return pointer to application specific data.
+ */
+
+void *ECDSA_METHOD_get_app_data(ECDSA_METHOD *ecdsa_method);
+
+/**  Set the ECDSA_do_sign function in the ECDSA_METHOD
+ *   \param  ecdsa_method  pointer to existing ECDSA_METHOD
+ *   \param  ecdsa_do_sign a funtion of type ECDSA_do_sign
+ */
+
+void ECDSA_METHOD_set_sign(ECDSA_METHOD *ecdsa_method,
+                           ECDSA_SIG *(*ecdsa_do_sign) (const unsigned char
+                                                        *dgst, int dgst_len,
+                                                        const BIGNUM *inv,
+                                                        const BIGNUM *rp,
+                                                        EC_KEY *eckey));
+
+/**  Set the  ECDSA_sign_setup function in the ECDSA_METHOD
+ *   \param  ecdsa_method  pointer to existing ECDSA_METHOD
+ *   \param  ecdsa_sign_setup a funtion of type ECDSA_sign_setup
+ */
+
+void ECDSA_METHOD_set_sign_setup(ECDSA_METHOD *ecdsa_method,
+                                 int (*ecdsa_sign_setup) (EC_KEY *eckey,
+                                                          BN_CTX *ctx,
+                                                          BIGNUM **kinv,
+                                                          BIGNUM **r));
+
+/**  Set the ECDSA_do_verify function in the ECDSA_METHOD
+ *   \param  ecdsa_method  pointer to existing ECDSA_METHOD
+ *   \param  ecdsa_do_verify a funtion of type ECDSA_do_verify
+ */
+
+void ECDSA_METHOD_set_verify(ECDSA_METHOD *ecdsa_method,
+                             int (*ecdsa_do_verify) (const unsigned char
+                                                     *dgst, int dgst_len,
+                                                     const ECDSA_SIG *sig,
+                                                     EC_KEY *eckey));
+
+void ECDSA_METHOD_set_flags(ECDSA_METHOD *ecdsa_method, int flags);
+
+/**  Set the flags field in the ECDSA_METHOD
+ *   \param  ecdsa_method  pointer to existing ECDSA_METHOD
+ *   \param  flags flags value to set
+ */
+
+void ECDSA_METHOD_set_name(ECDSA_METHOD *ecdsa_method, char *name);
+
+/**  Set the name field in the ECDSA_METHOD
+ *   \param  ecdsa_method  pointer to existing ECDSA_METHOD
+ *   \param  name name to set
+ */
+
+/* BEGIN ERROR CODES */
+/*
+ * The following lines are auto generated by the script mkerr.pl. Any changes
+ * made after this point may be overwritten when the script is next run.
+ */
+void ERR_load_ECDSA_strings(void);
+
+/* Error codes for the ECDSA functions. */
+
+/* Function codes. */
+# define ECDSA_F_ECDSA_CHECK                              104
+# define ECDSA_F_ECDSA_DATA_NEW_METHOD                    100
+# define ECDSA_F_ECDSA_DO_SIGN                            101
+# define ECDSA_F_ECDSA_DO_VERIFY                          102
+# define ECDSA_F_ECDSA_METHOD_NEW                         105
+# define ECDSA_F_ECDSA_SIGN_SETUP                         103
+
+/* Reason codes. */
+# define ECDSA_R_BAD_SIGNATURE                            100
+# define ECDSA_R_DATA_TOO_LARGE_FOR_KEY_SIZE              101
+# define ECDSA_R_ERR_EC_LIB                               102
+# define ECDSA_R_MISSING_PARAMETERS                       103
+# define ECDSA_R_NEED_NEW_SETUP_VALUES                    106
+# define ECDSA_R_NON_FIPS_METHOD                          107
+# define ECDSA_R_RANDOM_NUMBER_GENERATION_FAILED          104
+# define ECDSA_R_SIGNATURE_MALLOC_FAILED                  105
+
+#ifdef  __cplusplus
+}
+#endif
+#endif

+ 960 - 0
libssh2/openssl/include/openssl/engine.h

@@ -0,0 +1,960 @@
+/* openssl/engine.h */
+/*
+ * Written by Geoff Thorpe (geoff@geoffthorpe.net) for the OpenSSL project
+ * 2000.
+ */
+/* ====================================================================
+ * Copyright (c) 1999-2004 The OpenSSL 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. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    licensing@OpenSSL.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED 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 OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS 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.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com).  This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+/* ====================================================================
+ * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED.
+ * ECDH support in OpenSSL originally developed by
+ * SUN MICROSYSTEMS, INC., and contributed to the OpenSSL project.
+ */
+
+#ifndef HEADER_ENGINE_H
+# define HEADER_ENGINE_H
+
+# include <openssl/opensslconf.h>
+
+# ifdef OPENSSL_NO_ENGINE
+#  error ENGINE is disabled.
+# endif
+
+# ifndef OPENSSL_NO_DEPRECATED
+#  include <openssl/bn.h>
+#  ifndef OPENSSL_NO_RSA
+#   include <openssl/rsa.h>
+#  endif
+#  ifndef OPENSSL_NO_DSA
+#   include <openssl/dsa.h>
+#  endif
+#  ifndef OPENSSL_NO_DH
+#   include <openssl/dh.h>
+#  endif
+#  ifndef OPENSSL_NO_ECDH
+#   include <openssl/ecdh.h>
+#  endif
+#  ifndef OPENSSL_NO_ECDSA
+#   include <openssl/ecdsa.h>
+#  endif
+#  include <openssl/rand.h>
+#  include <openssl/ui.h>
+#  include <openssl/err.h>
+# endif
+
+# include <openssl/ossl_typ.h>
+# include <openssl/symhacks.h>
+
+# include <openssl/x509.h>
+
+#ifdef  __cplusplus
+extern "C" {
+#endif
+
+/*
+ * These flags are used to control combinations of algorithm (methods) by
+ * bitwise "OR"ing.
+ */
+# define ENGINE_METHOD_RSA               (unsigned int)0x0001
+# define ENGINE_METHOD_DSA               (unsigned int)0x0002
+# define ENGINE_METHOD_DH                (unsigned int)0x0004
+# define ENGINE_METHOD_RAND              (unsigned int)0x0008
+# define ENGINE_METHOD_ECDH              (unsigned int)0x0010
+# define ENGINE_METHOD_ECDSA             (unsigned int)0x0020
+# define ENGINE_METHOD_CIPHERS           (unsigned int)0x0040
+# define ENGINE_METHOD_DIGESTS           (unsigned int)0x0080
+# define ENGINE_METHOD_STORE             (unsigned int)0x0100
+# define ENGINE_METHOD_PKEY_METHS        (unsigned int)0x0200
+# define ENGINE_METHOD_PKEY_ASN1_METHS   (unsigned int)0x0400
+/* Obvious all-or-nothing cases. */
+# define ENGINE_METHOD_ALL               (unsigned int)0xFFFF
+# define ENGINE_METHOD_NONE              (unsigned int)0x0000
+
+/*
+ * This(ese) flag(s) controls behaviour of the ENGINE_TABLE mechanism used
+ * internally to control registration of ENGINE implementations, and can be
+ * set by ENGINE_set_table_flags(). The "NOINIT" flag prevents attempts to
+ * initialise registered ENGINEs if they are not already initialised.
+ */
+# define ENGINE_TABLE_FLAG_NOINIT        (unsigned int)0x0001
+
+/* ENGINE flags that can be set by ENGINE_set_flags(). */
+/* Not used */
+/* #define ENGINE_FLAGS_MALLOCED        0x0001 */
+
+/*
+ * This flag is for ENGINEs that wish to handle the various 'CMD'-related
+ * control commands on their own. Without this flag, ENGINE_ctrl() handles
+ * these control commands on behalf of the ENGINE using their "cmd_defns"
+ * data.
+ */
+# define ENGINE_FLAGS_MANUAL_CMD_CTRL    (int)0x0002
+
+/*
+ * This flag is for ENGINEs who return new duplicate structures when found
+ * via "ENGINE_by_id()". When an ENGINE must store state (eg. if
+ * ENGINE_ctrl() commands are called in sequence as part of some stateful
+ * process like key-generation setup and execution), it can set this flag -
+ * then each attempt to obtain the ENGINE will result in it being copied into
+ * a new structure. Normally, ENGINEs don't declare this flag so
+ * ENGINE_by_id() just increments the existing ENGINE's structural reference
+ * count.
+ */
+# define ENGINE_FLAGS_BY_ID_COPY         (int)0x0004
+
+/*
+ * This flag if for an ENGINE that does not want its methods registered as
+ * part of ENGINE_register_all_complete() for example if the methods are not
+ * usable as default methods.
+ */
+
+# define ENGINE_FLAGS_NO_REGISTER_ALL    (int)0x0008
+
+/*
+ * ENGINEs can support their own command types, and these flags are used in
+ * ENGINE_CTRL_GET_CMD_FLAGS to indicate to the caller what kind of input
+ * each command expects. Currently only numeric and string input is
+ * supported. If a control command supports none of the _NUMERIC, _STRING, or
+ * _NO_INPUT options, then it is regarded as an "internal" control command -
+ * and not for use in config setting situations. As such, they're not
+ * available to the ENGINE_ctrl_cmd_string() function, only raw ENGINE_ctrl()
+ * access. Changes to this list of 'command types' should be reflected
+ * carefully in ENGINE_cmd_is_executable() and ENGINE_ctrl_cmd_string().
+ */
+
+/* accepts a 'long' input value (3rd parameter to ENGINE_ctrl) */
+# define ENGINE_CMD_FLAG_NUMERIC         (unsigned int)0x0001
+/*
+ * accepts string input (cast from 'void*' to 'const char *', 4th parameter
+ * to ENGINE_ctrl)
+ */
+# define ENGINE_CMD_FLAG_STRING          (unsigned int)0x0002
+/*
+ * Indicates that the control command takes *no* input. Ie. the control
+ * command is unparameterised.
+ */
+# define ENGINE_CMD_FLAG_NO_INPUT        (unsigned int)0x0004
+/*
+ * Indicates that the control command is internal. This control command won't
+ * be shown in any output, and is only usable through the ENGINE_ctrl_cmd()
+ * function.
+ */
+# define ENGINE_CMD_FLAG_INTERNAL        (unsigned int)0x0008
+
+/*
+ * NB: These 3 control commands are deprecated and should not be used.
+ * ENGINEs relying on these commands should compile conditional support for
+ * compatibility (eg. if these symbols are defined) but should also migrate
+ * the same functionality to their own ENGINE-specific control functions that
+ * can be "discovered" by calling applications. The fact these control
+ * commands wouldn't be "executable" (ie. usable by text-based config)
+ * doesn't change the fact that application code can find and use them
+ * without requiring per-ENGINE hacking.
+ */
+
+/*
+ * These flags are used to tell the ctrl function what should be done. All
+ * command numbers are shared between all engines, even if some don't make
+ * sense to some engines.  In such a case, they do nothing but return the
+ * error ENGINE_R_CTRL_COMMAND_NOT_IMPLEMENTED.
+ */
+# define ENGINE_CTRL_SET_LOGSTREAM               1
+# define ENGINE_CTRL_SET_PASSWORD_CALLBACK       2
+# define ENGINE_CTRL_HUP                         3/* Close and reinitialise
+                                                   * any handles/connections
+                                                   * etc. */
+# define ENGINE_CTRL_SET_USER_INTERFACE          4/* Alternative to callback */
+# define ENGINE_CTRL_SET_CALLBACK_DATA           5/* User-specific data, used
+                                                   * when calling the password
+                                                   * callback and the user
+                                                   * interface */
+# define ENGINE_CTRL_LOAD_CONFIGURATION          6/* Load a configuration,
+                                                   * given a string that
+                                                   * represents a file name
+                                                   * or so */
+# define ENGINE_CTRL_LOAD_SECTION                7/* Load data from a given
+                                                   * section in the already
+                                                   * loaded configuration */
+
+/*
+ * These control commands allow an application to deal with an arbitrary
+ * engine in a dynamic way. Warn: Negative return values indicate errors FOR
+ * THESE COMMANDS because zero is used to indicate 'end-of-list'. Other
+ * commands, including ENGINE-specific command types, return zero for an
+ * error. An ENGINE can choose to implement these ctrl functions, and can
+ * internally manage things however it chooses - it does so by setting the
+ * ENGINE_FLAGS_MANUAL_CMD_CTRL flag (using ENGINE_set_flags()). Otherwise
+ * the ENGINE_ctrl() code handles this on the ENGINE's behalf using the
+ * cmd_defns data (set using ENGINE_set_cmd_defns()). This means an ENGINE's
+ * ctrl() handler need only implement its own commands - the above "meta"
+ * commands will be taken care of.
+ */
+
+/*
+ * Returns non-zero if the supplied ENGINE has a ctrl() handler. If "not",
+ * then all the remaining control commands will return failure, so it is
+ * worth checking this first if the caller is trying to "discover" the
+ * engine's capabilities and doesn't want errors generated unnecessarily.
+ */
+# define ENGINE_CTRL_HAS_CTRL_FUNCTION           10
+/*
+ * Returns a positive command number for the first command supported by the
+ * engine. Returns zero if no ctrl commands are supported.
+ */
+# define ENGINE_CTRL_GET_FIRST_CMD_TYPE          11
+/*
+ * The 'long' argument specifies a command implemented by the engine, and the
+ * return value is the next command supported, or zero if there are no more.
+ */
+# define ENGINE_CTRL_GET_NEXT_CMD_TYPE           12
+/*
+ * The 'void*' argument is a command name (cast from 'const char *'), and the
+ * return value is the command that corresponds to it.
+ */
+# define ENGINE_CTRL_GET_CMD_FROM_NAME           13
+/*
+ * The next two allow a command to be converted into its corresponding string
+ * form. In each case, the 'long' argument supplies the command. In the
+ * NAME_LEN case, the return value is the length of the command name (not
+ * counting a trailing EOL). In the NAME case, the 'void*' argument must be a
+ * string buffer large enough, and it will be populated with the name of the
+ * command (WITH a trailing EOL).
+ */
+# define ENGINE_CTRL_GET_NAME_LEN_FROM_CMD       14
+# define ENGINE_CTRL_GET_NAME_FROM_CMD           15
+/* The next two are similar but give a "short description" of a command. */
+# define ENGINE_CTRL_GET_DESC_LEN_FROM_CMD       16
+# define ENGINE_CTRL_GET_DESC_FROM_CMD           17
+/*
+ * With this command, the return value is the OR'd combination of
+ * ENGINE_CMD_FLAG_*** values that indicate what kind of input a given
+ * engine-specific ctrl command expects.
+ */
+# define ENGINE_CTRL_GET_CMD_FLAGS               18
+
+/*
+ * ENGINE implementations should start the numbering of their own control
+ * commands from this value. (ie. ENGINE_CMD_BASE, ENGINE_CMD_BASE + 1, etc).
+ */
+# define ENGINE_CMD_BASE                         200
+
+/*
+ * NB: These 2 nCipher "chil" control commands are deprecated, and their
+ * functionality is now available through ENGINE-specific control commands
+ * (exposed through the above-mentioned 'CMD'-handling). Code using these 2
+ * commands should be migrated to the more general command handling before
+ * these are removed.
+ */
+
+/* Flags specific to the nCipher "chil" engine */
+# define ENGINE_CTRL_CHIL_SET_FORKCHECK          100
+        /*
+         * Depending on the value of the (long)i argument, this sets or
+         * unsets the SimpleForkCheck flag in the CHIL API to enable or
+         * disable checking and workarounds for applications that fork().
+         */
+# define ENGINE_CTRL_CHIL_NO_LOCKING             101
+        /*
+         * This prevents the initialisation function from providing mutex
+         * callbacks to the nCipher library.
+         */
+
+/*
+ * If an ENGINE supports its own specific control commands and wishes the
+ * framework to handle the above 'ENGINE_CMD_***'-manipulation commands on
+ * its behalf, it should supply a null-terminated array of ENGINE_CMD_DEFN
+ * entries to ENGINE_set_cmd_defns(). It should also implement a ctrl()
+ * handler that supports the stated commands (ie. the "cmd_num" entries as
+ * described by the array). NB: The array must be ordered in increasing order
+ * of cmd_num. "null-terminated" means that the last ENGINE_CMD_DEFN element
+ * has cmd_num set to zero and/or cmd_name set to NULL.
+ */
+typedef struct ENGINE_CMD_DEFN_st {
+    unsigned int cmd_num;       /* The command number */
+    const char *cmd_name;       /* The command name itself */
+    const char *cmd_desc;       /* A short description of the command */
+    unsigned int cmd_flags;     /* The input the command expects */
+} ENGINE_CMD_DEFN;
+
+/* Generic function pointer */
+typedef int (*ENGINE_GEN_FUNC_PTR) (void);
+/* Generic function pointer taking no arguments */
+typedef int (*ENGINE_GEN_INT_FUNC_PTR) (ENGINE *);
+/* Specific control function pointer */
+typedef int (*ENGINE_CTRL_FUNC_PTR) (ENGINE *, int, long, void *,
+                                     void (*f) (void));
+/* Generic load_key function pointer */
+typedef EVP_PKEY *(*ENGINE_LOAD_KEY_PTR)(ENGINE *, const char *,
+                                         UI_METHOD *ui_method,
+                                         void *callback_data);
+typedef int (*ENGINE_SSL_CLIENT_CERT_PTR) (ENGINE *, SSL *ssl,
+                                           STACK_OF(X509_NAME) *ca_dn,
+                                           X509 **pcert, EVP_PKEY **pkey,
+                                           STACK_OF(X509) **pother,
+                                           UI_METHOD *ui_method,
+                                           void *callback_data);
+/*-
+ * These callback types are for an ENGINE's handler for cipher and digest logic.
+ * These handlers have these prototypes;
+ *   int foo(ENGINE *e, const EVP_CIPHER **cipher, const int **nids, int nid);
+ *   int foo(ENGINE *e, const EVP_MD **digest, const int **nids, int nid);
+ * Looking at how to implement these handlers in the case of cipher support, if
+ * the framework wants the EVP_CIPHER for 'nid', it will call;
+ *   foo(e, &p_evp_cipher, NULL, nid);    (return zero for failure)
+ * If the framework wants a list of supported 'nid's, it will call;
+ *   foo(e, NULL, &p_nids, 0); (returns number of 'nids' or -1 for error)
+ */
+/*
+ * Returns to a pointer to the array of supported cipher 'nid's. If the
+ * second parameter is non-NULL it is set to the size of the returned array.
+ */
+typedef int (*ENGINE_CIPHERS_PTR) (ENGINE *, const EVP_CIPHER **,
+                                   const int **, int);
+typedef int (*ENGINE_DIGESTS_PTR) (ENGINE *, const EVP_MD **, const int **,
+                                   int);
+typedef int (*ENGINE_PKEY_METHS_PTR) (ENGINE *, EVP_PKEY_METHOD **,
+                                      const int **, int);
+typedef int (*ENGINE_PKEY_ASN1_METHS_PTR) (ENGINE *, EVP_PKEY_ASN1_METHOD **,
+                                           const int **, int);
+/*
+ * STRUCTURE functions ... all of these functions deal with pointers to
+ * ENGINE structures where the pointers have a "structural reference". This
+ * means that their reference is to allowed access to the structure but it
+ * does not imply that the structure is functional. To simply increment or
+ * decrement the structural reference count, use ENGINE_by_id and
+ * ENGINE_free. NB: This is not required when iterating using ENGINE_get_next
+ * as it will automatically decrement the structural reference count of the
+ * "current" ENGINE and increment the structural reference count of the
+ * ENGINE it returns (unless it is NULL).
+ */
+
+/* Get the first/last "ENGINE" type available. */
+ENGINE *ENGINE_get_first(void);
+ENGINE *ENGINE_get_last(void);
+/* Iterate to the next/previous "ENGINE" type (NULL = end of the list). */
+ENGINE *ENGINE_get_next(ENGINE *e);
+ENGINE *ENGINE_get_prev(ENGINE *e);
+/* Add another "ENGINE" type into the array. */
+int ENGINE_add(ENGINE *e);
+/* Remove an existing "ENGINE" type from the array. */
+int ENGINE_remove(ENGINE *e);
+/* Retrieve an engine from the list by its unique "id" value. */
+ENGINE *ENGINE_by_id(const char *id);
+/* Add all the built-in engines. */
+void ENGINE_load_openssl(void);
+void ENGINE_load_dynamic(void);
+# ifndef OPENSSL_NO_STATIC_ENGINE
+void ENGINE_load_4758cca(void);
+void ENGINE_load_aep(void);
+void ENGINE_load_atalla(void);
+void ENGINE_load_chil(void);
+void ENGINE_load_cswift(void);
+void ENGINE_load_nuron(void);
+void ENGINE_load_sureware(void);
+void ENGINE_load_ubsec(void);
+void ENGINE_load_padlock(void);
+void ENGINE_load_capi(void);
+#  ifndef OPENSSL_NO_GMP
+void ENGINE_load_gmp(void);
+#  endif
+#  ifndef OPENSSL_NO_GOST
+void ENGINE_load_gost(void);
+#  endif
+# endif
+void ENGINE_load_cryptodev(void);
+void ENGINE_load_rdrand(void);
+void ENGINE_load_builtin_engines(void);
+
+/*
+ * Get and set global flags (ENGINE_TABLE_FLAG_***) for the implementation
+ * "registry" handling.
+ */
+unsigned int ENGINE_get_table_flags(void);
+void ENGINE_set_table_flags(unsigned int flags);
+
+/*- Manage registration of ENGINEs per "table". For each type, there are 3
+ * functions;
+ *   ENGINE_register_***(e) - registers the implementation from 'e' (if it has one)
+ *   ENGINE_unregister_***(e) - unregister the implementation from 'e'
+ *   ENGINE_register_all_***() - call ENGINE_register_***() for each 'e' in the list
+ * Cleanup is automatically registered from each table when required, so
+ * ENGINE_cleanup() will reverse any "register" operations.
+ */
+
+int ENGINE_register_RSA(ENGINE *e);
+void ENGINE_unregister_RSA(ENGINE *e);
+void ENGINE_register_all_RSA(void);
+
+int ENGINE_register_DSA(ENGINE *e);
+void ENGINE_unregister_DSA(ENGINE *e);
+void ENGINE_register_all_DSA(void);
+
+int ENGINE_register_ECDH(ENGINE *e);
+void ENGINE_unregister_ECDH(ENGINE *e);
+void ENGINE_register_all_ECDH(void);
+
+int ENGINE_register_ECDSA(ENGINE *e);
+void ENGINE_unregister_ECDSA(ENGINE *e);
+void ENGINE_register_all_ECDSA(void);
+
+int ENGINE_register_DH(ENGINE *e);
+void ENGINE_unregister_DH(ENGINE *e);
+void ENGINE_register_all_DH(void);
+
+int ENGINE_register_RAND(ENGINE *e);
+void ENGINE_unregister_RAND(ENGINE *e);
+void ENGINE_register_all_RAND(void);
+
+int ENGINE_register_STORE(ENGINE *e);
+void ENGINE_unregister_STORE(ENGINE *e);
+void ENGINE_register_all_STORE(void);
+
+int ENGINE_register_ciphers(ENGINE *e);
+void ENGINE_unregister_ciphers(ENGINE *e);
+void ENGINE_register_all_ciphers(void);
+
+int ENGINE_register_digests(ENGINE *e);
+void ENGINE_unregister_digests(ENGINE *e);
+void ENGINE_register_all_digests(void);
+
+int ENGINE_register_pkey_meths(ENGINE *e);
+void ENGINE_unregister_pkey_meths(ENGINE *e);
+void ENGINE_register_all_pkey_meths(void);
+
+int ENGINE_register_pkey_asn1_meths(ENGINE *e);
+void ENGINE_unregister_pkey_asn1_meths(ENGINE *e);
+void ENGINE_register_all_pkey_asn1_meths(void);
+
+/*
+ * These functions register all support from the above categories. Note, use
+ * of these functions can result in static linkage of code your application
+ * may not need. If you only need a subset of functionality, consider using
+ * more selective initialisation.
+ */
+int ENGINE_register_complete(ENGINE *e);
+int ENGINE_register_all_complete(void);
+
+/*
+ * Send parametrised control commands to the engine. The possibilities to
+ * send down an integer, a pointer to data or a function pointer are
+ * provided. Any of the parameters may or may not be NULL, depending on the
+ * command number. In actuality, this function only requires a structural
+ * (rather than functional) reference to an engine, but many control commands
+ * may require the engine be functional. The caller should be aware of trying
+ * commands that require an operational ENGINE, and only use functional
+ * references in such situations.
+ */
+int ENGINE_ctrl(ENGINE *e, int cmd, long i, void *p, void (*f) (void));
+
+/*
+ * This function tests if an ENGINE-specific command is usable as a
+ * "setting". Eg. in an application's config file that gets processed through
+ * ENGINE_ctrl_cmd_string(). If this returns zero, it is not available to
+ * ENGINE_ctrl_cmd_string(), only ENGINE_ctrl().
+ */
+int ENGINE_cmd_is_executable(ENGINE *e, int cmd);
+
+/*
+ * This function works like ENGINE_ctrl() with the exception of taking a
+ * command name instead of a command number, and can handle optional
+ * commands. See the comment on ENGINE_ctrl_cmd_string() for an explanation
+ * on how to use the cmd_name and cmd_optional.
+ */
+int ENGINE_ctrl_cmd(ENGINE *e, const char *cmd_name,
+                    long i, void *p, void (*f) (void), int cmd_optional);
+
+/*
+ * This function passes a command-name and argument to an ENGINE. The
+ * cmd_name is converted to a command number and the control command is
+ * called using 'arg' as an argument (unless the ENGINE doesn't support such
+ * a command, in which case no control command is called). The command is
+ * checked for input flags, and if necessary the argument will be converted
+ * to a numeric value. If cmd_optional is non-zero, then if the ENGINE
+ * doesn't support the given cmd_name the return value will be success
+ * anyway. This function is intended for applications to use so that users
+ * (or config files) can supply engine-specific config data to the ENGINE at
+ * run-time to control behaviour of specific engines. As such, it shouldn't
+ * be used for calling ENGINE_ctrl() functions that return data, deal with
+ * binary data, or that are otherwise supposed to be used directly through
+ * ENGINE_ctrl() in application code. Any "return" data from an ENGINE_ctrl()
+ * operation in this function will be lost - the return value is interpreted
+ * as failure if the return value is zero, success otherwise, and this
+ * function returns a boolean value as a result. In other words, vendors of
+ * 'ENGINE'-enabled devices should write ENGINE implementations with
+ * parameterisations that work in this scheme, so that compliant ENGINE-based
+ * applications can work consistently with the same configuration for the
+ * same ENGINE-enabled devices, across applications.
+ */
+int ENGINE_ctrl_cmd_string(ENGINE *e, const char *cmd_name, const char *arg,
+                           int cmd_optional);
+
+/*
+ * These functions are useful for manufacturing new ENGINE structures. They
+ * don't address reference counting at all - one uses them to populate an
+ * ENGINE structure with personalised implementations of things prior to
+ * using it directly or adding it to the builtin ENGINE list in OpenSSL.
+ * These are also here so that the ENGINE structure doesn't have to be
+ * exposed and break binary compatibility!
+ */
+ENGINE *ENGINE_new(void);
+int ENGINE_free(ENGINE *e);
+int ENGINE_up_ref(ENGINE *e);
+int ENGINE_set_id(ENGINE *e, const char *id);
+int ENGINE_set_name(ENGINE *e, const char *name);
+int ENGINE_set_RSA(ENGINE *e, const RSA_METHOD *rsa_meth);
+int ENGINE_set_DSA(ENGINE *e, const DSA_METHOD *dsa_meth);
+int ENGINE_set_ECDH(ENGINE *e, const ECDH_METHOD *ecdh_meth);
+int ENGINE_set_ECDSA(ENGINE *e, const ECDSA_METHOD *ecdsa_meth);
+int ENGINE_set_DH(ENGINE *e, const DH_METHOD *dh_meth);
+int ENGINE_set_RAND(ENGINE *e, const RAND_METHOD *rand_meth);
+int ENGINE_set_STORE(ENGINE *e, const STORE_METHOD *store_meth);
+int ENGINE_set_destroy_function(ENGINE *e, ENGINE_GEN_INT_FUNC_PTR destroy_f);
+int ENGINE_set_init_function(ENGINE *e, ENGINE_GEN_INT_FUNC_PTR init_f);
+int ENGINE_set_finish_function(ENGINE *e, ENGINE_GEN_INT_FUNC_PTR finish_f);
+int ENGINE_set_ctrl_function(ENGINE *e, ENGINE_CTRL_FUNC_PTR ctrl_f);
+int ENGINE_set_load_privkey_function(ENGINE *e,
+                                     ENGINE_LOAD_KEY_PTR loadpriv_f);
+int ENGINE_set_load_pubkey_function(ENGINE *e, ENGINE_LOAD_KEY_PTR loadpub_f);
+int ENGINE_set_load_ssl_client_cert_function(ENGINE *e,
+                                             ENGINE_SSL_CLIENT_CERT_PTR
+                                             loadssl_f);
+int ENGINE_set_ciphers(ENGINE *e, ENGINE_CIPHERS_PTR f);
+int ENGINE_set_digests(ENGINE *e, ENGINE_DIGESTS_PTR f);
+int ENGINE_set_pkey_meths(ENGINE *e, ENGINE_PKEY_METHS_PTR f);
+int ENGINE_set_pkey_asn1_meths(ENGINE *e, ENGINE_PKEY_ASN1_METHS_PTR f);
+int ENGINE_set_flags(ENGINE *e, int flags);
+int ENGINE_set_cmd_defns(ENGINE *e, const ENGINE_CMD_DEFN *defns);
+/* These functions allow control over any per-structure ENGINE data. */
+int ENGINE_get_ex_new_index(long argl, void *argp, CRYPTO_EX_new *new_func,
+                            CRYPTO_EX_dup *dup_func,
+                            CRYPTO_EX_free *free_func);
+int ENGINE_set_ex_data(ENGINE *e, int idx, void *arg);
+void *ENGINE_get_ex_data(const ENGINE *e, int idx);
+
+/*
+ * This function cleans up anything that needs it. Eg. the ENGINE_add()
+ * function automatically ensures the list cleanup function is registered to
+ * be called from ENGINE_cleanup(). Similarly, all ENGINE_register_***
+ * functions ensure ENGINE_cleanup() will clean up after them.
+ */
+void ENGINE_cleanup(void);
+
+/*
+ * These return values from within the ENGINE structure. These can be useful
+ * with functional references as well as structural references - it depends
+ * which you obtained. Using the result for functional purposes if you only
+ * obtained a structural reference may be problematic!
+ */
+const char *ENGINE_get_id(const ENGINE *e);
+const char *ENGINE_get_name(const ENGINE *e);
+const RSA_METHOD *ENGINE_get_RSA(const ENGINE *e);
+const DSA_METHOD *ENGINE_get_DSA(const ENGINE *e);
+const ECDH_METHOD *ENGINE_get_ECDH(const ENGINE *e);
+const ECDSA_METHOD *ENGINE_get_ECDSA(const ENGINE *e);
+const DH_METHOD *ENGINE_get_DH(const ENGINE *e);
+const RAND_METHOD *ENGINE_get_RAND(const ENGINE *e);
+const STORE_METHOD *ENGINE_get_STORE(const ENGINE *e);
+ENGINE_GEN_INT_FUNC_PTR ENGINE_get_destroy_function(const ENGINE *e);
+ENGINE_GEN_INT_FUNC_PTR ENGINE_get_init_function(const ENGINE *e);
+ENGINE_GEN_INT_FUNC_PTR ENGINE_get_finish_function(const ENGINE *e);
+ENGINE_CTRL_FUNC_PTR ENGINE_get_ctrl_function(const ENGINE *e);
+ENGINE_LOAD_KEY_PTR ENGINE_get_load_privkey_function(const ENGINE *e);
+ENGINE_LOAD_KEY_PTR ENGINE_get_load_pubkey_function(const ENGINE *e);
+ENGINE_SSL_CLIENT_CERT_PTR ENGINE_get_ssl_client_cert_function(const ENGINE
+                                                               *e);
+ENGINE_CIPHERS_PTR ENGINE_get_ciphers(const ENGINE *e);
+ENGINE_DIGESTS_PTR ENGINE_get_digests(const ENGINE *e);
+ENGINE_PKEY_METHS_PTR ENGINE_get_pkey_meths(const ENGINE *e);
+ENGINE_PKEY_ASN1_METHS_PTR ENGINE_get_pkey_asn1_meths(const ENGINE *e);
+const EVP_CIPHER *ENGINE_get_cipher(ENGINE *e, int nid);
+const EVP_MD *ENGINE_get_digest(ENGINE *e, int nid);
+const EVP_PKEY_METHOD *ENGINE_get_pkey_meth(ENGINE *e, int nid);
+const EVP_PKEY_ASN1_METHOD *ENGINE_get_pkey_asn1_meth(ENGINE *e, int nid);
+const EVP_PKEY_ASN1_METHOD *ENGINE_get_pkey_asn1_meth_str(ENGINE *e,
+                                                          const char *str,
+                                                          int len);
+const EVP_PKEY_ASN1_METHOD *ENGINE_pkey_asn1_find_str(ENGINE **pe,
+                                                      const char *str,
+                                                      int len);
+const ENGINE_CMD_DEFN *ENGINE_get_cmd_defns(const ENGINE *e);
+int ENGINE_get_flags(const ENGINE *e);
+
+/*
+ * FUNCTIONAL functions. These functions deal with ENGINE structures that
+ * have (or will) be initialised for use. Broadly speaking, the structural
+ * functions are useful for iterating the list of available engine types,
+ * creating new engine types, and other "list" operations. These functions
+ * actually deal with ENGINEs that are to be used. As such these functions
+ * can fail (if applicable) when particular engines are unavailable - eg. if
+ * a hardware accelerator is not attached or not functioning correctly. Each
+ * ENGINE has 2 reference counts; structural and functional. Every time a
+ * functional reference is obtained or released, a corresponding structural
+ * reference is automatically obtained or released too.
+ */
+
+/*
+ * Initialise a engine type for use (or up its reference count if it's
+ * already in use). This will fail if the engine is not currently operational
+ * and cannot initialise.
+ */
+int ENGINE_init(ENGINE *e);
+/*
+ * Free a functional reference to a engine type. This does not require a
+ * corresponding call to ENGINE_free as it also releases a structural
+ * reference.
+ */
+int ENGINE_finish(ENGINE *e);
+
+/*
+ * The following functions handle keys that are stored in some secondary
+ * location, handled by the engine.  The storage may be on a card or
+ * whatever.
+ */
+EVP_PKEY *ENGINE_load_private_key(ENGINE *e, const char *key_id,
+                                  UI_METHOD *ui_method, void *callback_data);
+EVP_PKEY *ENGINE_load_public_key(ENGINE *e, const char *key_id,
+                                 UI_METHOD *ui_method, void *callback_data);
+int ENGINE_load_ssl_client_cert(ENGINE *e, SSL *s,
+                                STACK_OF(X509_NAME) *ca_dn, X509 **pcert,
+                                EVP_PKEY **ppkey, STACK_OF(X509) **pother,
+                                UI_METHOD *ui_method, void *callback_data);
+
+/*
+ * This returns a pointer for the current ENGINE structure that is (by
+ * default) performing any RSA operations. The value returned is an
+ * incremented reference, so it should be free'd (ENGINE_finish) before it is
+ * discarded.
+ */
+ENGINE *ENGINE_get_default_RSA(void);
+/* Same for the other "methods" */
+ENGINE *ENGINE_get_default_DSA(void);
+ENGINE *ENGINE_get_default_ECDH(void);
+ENGINE *ENGINE_get_default_ECDSA(void);
+ENGINE *ENGINE_get_default_DH(void);
+ENGINE *ENGINE_get_default_RAND(void);
+/*
+ * These functions can be used to get a functional reference to perform
+ * ciphering or digesting corresponding to "nid".
+ */
+ENGINE *ENGINE_get_cipher_engine(int nid);
+ENGINE *ENGINE_get_digest_engine(int nid);
+ENGINE *ENGINE_get_pkey_meth_engine(int nid);
+ENGINE *ENGINE_get_pkey_asn1_meth_engine(int nid);
+
+/*
+ * This sets a new default ENGINE structure for performing RSA operations. If
+ * the result is non-zero (success) then the ENGINE structure will have had
+ * its reference count up'd so the caller should still free their own
+ * reference 'e'.
+ */
+int ENGINE_set_default_RSA(ENGINE *e);
+int ENGINE_set_default_string(ENGINE *e, const char *def_list);
+/* Same for the other "methods" */
+int ENGINE_set_default_DSA(ENGINE *e);
+int ENGINE_set_default_ECDH(ENGINE *e);
+int ENGINE_set_default_ECDSA(ENGINE *e);
+int ENGINE_set_default_DH(ENGINE *e);
+int ENGINE_set_default_RAND(ENGINE *e);
+int ENGINE_set_default_ciphers(ENGINE *e);
+int ENGINE_set_default_digests(ENGINE *e);
+int ENGINE_set_default_pkey_meths(ENGINE *e);
+int ENGINE_set_default_pkey_asn1_meths(ENGINE *e);
+
+/*
+ * The combination "set" - the flags are bitwise "OR"d from the
+ * ENGINE_METHOD_*** defines above. As with the "ENGINE_register_complete()"
+ * function, this function can result in unnecessary static linkage. If your
+ * application requires only specific functionality, consider using more
+ * selective functions.
+ */
+int ENGINE_set_default(ENGINE *e, unsigned int flags);
+
+void ENGINE_add_conf_module(void);
+
+/* Deprecated functions ... */
+/* int ENGINE_clear_defaults(void); */
+
+/**************************/
+/* DYNAMIC ENGINE SUPPORT */
+/**************************/
+
+/* Binary/behaviour compatibility levels */
+# define OSSL_DYNAMIC_VERSION            (unsigned long)0x00020000
+/*
+ * Binary versions older than this are too old for us (whether we're a loader
+ * or a loadee)
+ */
+# define OSSL_DYNAMIC_OLDEST             (unsigned long)0x00020000
+
+/*
+ * When compiling an ENGINE entirely as an external shared library, loadable
+ * by the "dynamic" ENGINE, these types are needed. The 'dynamic_fns'
+ * structure type provides the calling application's (or library's) error
+ * functionality and memory management function pointers to the loaded
+ * library. These should be used/set in the loaded library code so that the
+ * loading application's 'state' will be used/changed in all operations. The
+ * 'static_state' pointer allows the loaded library to know if it shares the
+ * same static data as the calling application (or library), and thus whether
+ * these callbacks need to be set or not.
+ */
+typedef void *(*dyn_MEM_malloc_cb) (size_t);
+typedef void *(*dyn_MEM_realloc_cb) (void *, size_t);
+typedef void (*dyn_MEM_free_cb) (void *);
+typedef struct st_dynamic_MEM_fns {
+    dyn_MEM_malloc_cb malloc_cb;
+    dyn_MEM_realloc_cb realloc_cb;
+    dyn_MEM_free_cb free_cb;
+} dynamic_MEM_fns;
+/*
+ * FIXME: Perhaps the memory and locking code (crypto.h) should declare and
+ * use these types so we (and any other dependant code) can simplify a bit??
+ */
+typedef void (*dyn_lock_locking_cb) (int, int, const char *, int);
+typedef int (*dyn_lock_add_lock_cb) (int *, int, int, const char *, int);
+typedef struct CRYPTO_dynlock_value *(*dyn_dynlock_create_cb) (const char *,
+                                                               int);
+typedef void (*dyn_dynlock_lock_cb) (int, struct CRYPTO_dynlock_value *,
+                                     const char *, int);
+typedef void (*dyn_dynlock_destroy_cb) (struct CRYPTO_dynlock_value *,
+                                        const char *, int);
+typedef struct st_dynamic_LOCK_fns {
+    dyn_lock_locking_cb lock_locking_cb;
+    dyn_lock_add_lock_cb lock_add_lock_cb;
+    dyn_dynlock_create_cb dynlock_create_cb;
+    dyn_dynlock_lock_cb dynlock_lock_cb;
+    dyn_dynlock_destroy_cb dynlock_destroy_cb;
+} dynamic_LOCK_fns;
+/* The top-level structure */
+typedef struct st_dynamic_fns {
+    void *static_state;
+    const ERR_FNS *err_fns;
+    const CRYPTO_EX_DATA_IMPL *ex_data_fns;
+    dynamic_MEM_fns mem_fns;
+    dynamic_LOCK_fns lock_fns;
+} dynamic_fns;
+
+/*
+ * The version checking function should be of this prototype. NB: The
+ * ossl_version value passed in is the OSSL_DYNAMIC_VERSION of the loading
+ * code. If this function returns zero, it indicates a (potential) version
+ * incompatibility and the loaded library doesn't believe it can proceed.
+ * Otherwise, the returned value is the (latest) version supported by the
+ * loading library. The loader may still decide that the loaded code's
+ * version is unsatisfactory and could veto the load. The function is
+ * expected to be implemented with the symbol name "v_check", and a default
+ * implementation can be fully instantiated with
+ * IMPLEMENT_DYNAMIC_CHECK_FN().
+ */
+typedef unsigned long (*dynamic_v_check_fn) (unsigned long ossl_version);
+# define IMPLEMENT_DYNAMIC_CHECK_FN() \
+        OPENSSL_EXPORT unsigned long v_check(unsigned long v); \
+        OPENSSL_EXPORT unsigned long v_check(unsigned long v) { \
+                if(v >= OSSL_DYNAMIC_OLDEST) return OSSL_DYNAMIC_VERSION; \
+                return 0; }
+
+/*
+ * This function is passed the ENGINE structure to initialise with its own
+ * function and command settings. It should not adjust the structural or
+ * functional reference counts. If this function returns zero, (a) the load
+ * will be aborted, (b) the previous ENGINE state will be memcpy'd back onto
+ * the structure, and (c) the shared library will be unloaded. So
+ * implementations should do their own internal cleanup in failure
+ * circumstances otherwise they could leak. The 'id' parameter, if non-NULL,
+ * represents the ENGINE id that the loader is looking for. If this is NULL,
+ * the shared library can choose to return failure or to initialise a
+ * 'default' ENGINE. If non-NULL, the shared library must initialise only an
+ * ENGINE matching the passed 'id'. The function is expected to be
+ * implemented with the symbol name "bind_engine". A standard implementation
+ * can be instantiated with IMPLEMENT_DYNAMIC_BIND_FN(fn) where the parameter
+ * 'fn' is a callback function that populates the ENGINE structure and
+ * returns an int value (zero for failure). 'fn' should have prototype;
+ * [static] int fn(ENGINE *e, const char *id);
+ */
+typedef int (*dynamic_bind_engine) (ENGINE *e, const char *id,
+                                    const dynamic_fns *fns);
+# define IMPLEMENT_DYNAMIC_BIND_FN(fn) \
+        OPENSSL_EXPORT \
+        int bind_engine(ENGINE *e, const char *id, const dynamic_fns *fns); \
+        OPENSSL_EXPORT \
+        int bind_engine(ENGINE *e, const char *id, const dynamic_fns *fns) { \
+                if(ENGINE_get_static_state() == fns->static_state) goto skip_cbs; \
+                if(!CRYPTO_set_mem_functions(fns->mem_fns.malloc_cb, \
+                        fns->mem_fns.realloc_cb, fns->mem_fns.free_cb)) \
+                        return 0; \
+                CRYPTO_set_locking_callback(fns->lock_fns.lock_locking_cb); \
+                CRYPTO_set_add_lock_callback(fns->lock_fns.lock_add_lock_cb); \
+                CRYPTO_set_dynlock_create_callback(fns->lock_fns.dynlock_create_cb); \
+                CRYPTO_set_dynlock_lock_callback(fns->lock_fns.dynlock_lock_cb); \
+                CRYPTO_set_dynlock_destroy_callback(fns->lock_fns.dynlock_destroy_cb); \
+                if(!CRYPTO_set_ex_data_implementation(fns->ex_data_fns)) \
+                        return 0; \
+                if(!ERR_set_implementation(fns->err_fns)) return 0; \
+        skip_cbs: \
+                if(!fn(e,id)) return 0; \
+                return 1; }
+
+/*
+ * If the loading application (or library) and the loaded ENGINE library
+ * share the same static data (eg. they're both dynamically linked to the
+ * same libcrypto.so) we need a way to avoid trying to set system callbacks -
+ * this would fail, and for the same reason that it's unnecessary to try. If
+ * the loaded ENGINE has (or gets from through the loader) its own copy of
+ * the libcrypto static data, we will need to set the callbacks. The easiest
+ * way to detect this is to have a function that returns a pointer to some
+ * static data and let the loading application and loaded ENGINE compare
+ * their respective values.
+ */
+void *ENGINE_get_static_state(void);
+
+# if defined(__OpenBSD__) || defined(__FreeBSD__) || defined(HAVE_CRYPTODEV)
+void ENGINE_setup_bsd_cryptodev(void);
+# endif
+
+/* BEGIN ERROR CODES */
+/*
+ * The following lines are auto generated by the script mkerr.pl. Any changes
+ * made after this point may be overwritten when the script is next run.
+ */
+void ERR_load_ENGINE_strings(void);
+
+/* Error codes for the ENGINE functions. */
+
+/* Function codes. */
+# define ENGINE_F_DYNAMIC_CTRL                            180
+# define ENGINE_F_DYNAMIC_GET_DATA_CTX                    181
+# define ENGINE_F_DYNAMIC_LOAD                            182
+# define ENGINE_F_DYNAMIC_SET_DATA_CTX                    183
+# define ENGINE_F_ENGINE_ADD                              105
+# define ENGINE_F_ENGINE_BY_ID                            106
+# define ENGINE_F_ENGINE_CMD_IS_EXECUTABLE                170
+# define ENGINE_F_ENGINE_CTRL                             142
+# define ENGINE_F_ENGINE_CTRL_CMD                         178
+# define ENGINE_F_ENGINE_CTRL_CMD_STRING                  171
+# define ENGINE_F_ENGINE_FINISH                           107
+# define ENGINE_F_ENGINE_FREE_UTIL                        108
+# define ENGINE_F_ENGINE_GET_CIPHER                       185
+# define ENGINE_F_ENGINE_GET_DEFAULT_TYPE                 177
+# define ENGINE_F_ENGINE_GET_DIGEST                       186
+# define ENGINE_F_ENGINE_GET_NEXT                         115
+# define ENGINE_F_ENGINE_GET_PKEY_ASN1_METH               193
+# define ENGINE_F_ENGINE_GET_PKEY_METH                    192
+# define ENGINE_F_ENGINE_GET_PREV                         116
+# define ENGINE_F_ENGINE_INIT                             119
+# define ENGINE_F_ENGINE_LIST_ADD                         120
+# define ENGINE_F_ENGINE_LIST_REMOVE                      121
+# define ENGINE_F_ENGINE_LOAD_PRIVATE_KEY                 150
+# define ENGINE_F_ENGINE_LOAD_PUBLIC_KEY                  151
+# define ENGINE_F_ENGINE_LOAD_SSL_CLIENT_CERT             194
+# define ENGINE_F_ENGINE_NEW                              122
+# define ENGINE_F_ENGINE_REMOVE                           123
+# define ENGINE_F_ENGINE_SET_DEFAULT_STRING               189
+# define ENGINE_F_ENGINE_SET_DEFAULT_TYPE                 126
+# define ENGINE_F_ENGINE_SET_ID                           129
+# define ENGINE_F_ENGINE_SET_NAME                         130
+# define ENGINE_F_ENGINE_TABLE_REGISTER                   184
+# define ENGINE_F_ENGINE_UNLOAD_KEY                       152
+# define ENGINE_F_ENGINE_UNLOCKED_FINISH                  191
+# define ENGINE_F_ENGINE_UP_REF                           190
+# define ENGINE_F_INT_CTRL_HELPER                         172
+# define ENGINE_F_INT_ENGINE_CONFIGURE                    188
+# define ENGINE_F_INT_ENGINE_MODULE_INIT                  187
+# define ENGINE_F_LOG_MESSAGE                             141
+
+/* Reason codes. */
+# define ENGINE_R_ALREADY_LOADED                          100
+# define ENGINE_R_ARGUMENT_IS_NOT_A_NUMBER                133
+# define ENGINE_R_CMD_NOT_EXECUTABLE                      134
+# define ENGINE_R_COMMAND_TAKES_INPUT                     135
+# define ENGINE_R_COMMAND_TAKES_NO_INPUT                  136
+# define ENGINE_R_CONFLICTING_ENGINE_ID                   103
+# define ENGINE_R_CTRL_COMMAND_NOT_IMPLEMENTED            119
+# define ENGINE_R_DH_NOT_IMPLEMENTED                      139
+# define ENGINE_R_DSA_NOT_IMPLEMENTED                     140
+# define ENGINE_R_DSO_FAILURE                             104
+# define ENGINE_R_DSO_NOT_FOUND                           132
+# define ENGINE_R_ENGINES_SECTION_ERROR                   148
+# define ENGINE_R_ENGINE_CONFIGURATION_ERROR              102
+# define ENGINE_R_ENGINE_IS_NOT_IN_LIST                   105
+# define ENGINE_R_ENGINE_SECTION_ERROR                    149
+# define ENGINE_R_FAILED_LOADING_PRIVATE_KEY              128
+# define ENGINE_R_FAILED_LOADING_PUBLIC_KEY               129
+# define ENGINE_R_FINISH_FAILED                           106
+# define ENGINE_R_GET_HANDLE_FAILED                       107
+# define ENGINE_R_ID_OR_NAME_MISSING                      108
+# define ENGINE_R_INIT_FAILED                             109
+# define ENGINE_R_INTERNAL_LIST_ERROR                     110
+# define ENGINE_R_INVALID_ARGUMENT                        143
+# define ENGINE_R_INVALID_CMD_NAME                        137
+# define ENGINE_R_INVALID_CMD_NUMBER                      138
+# define ENGINE_R_INVALID_INIT_VALUE                      151
+# define ENGINE_R_INVALID_STRING                          150
+# define ENGINE_R_NOT_INITIALISED                         117
+# define ENGINE_R_NOT_LOADED                              112
+# define ENGINE_R_NO_CONTROL_FUNCTION                     120
+# define ENGINE_R_NO_INDEX                                144
+# define ENGINE_R_NO_LOAD_FUNCTION                        125
+# define ENGINE_R_NO_REFERENCE                            130
+# define ENGINE_R_NO_SUCH_ENGINE                          116
+# define ENGINE_R_NO_UNLOAD_FUNCTION                      126
+# define ENGINE_R_PROVIDE_PARAMETERS                      113
+# define ENGINE_R_RSA_NOT_IMPLEMENTED                     141
+# define ENGINE_R_UNIMPLEMENTED_CIPHER                    146
+# define ENGINE_R_UNIMPLEMENTED_DIGEST                    147
+# define ENGINE_R_UNIMPLEMENTED_PUBLIC_KEY_METHOD         101
+# define ENGINE_R_VERSION_INCOMPATIBILITY                 145
+
+#ifdef  __cplusplus
+}
+#endif
+#endif

+ 391 - 0
libssh2/openssl/include/openssl/err.h

@@ -0,0 +1,391 @@
+/* crypto/err/err.h */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * 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 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. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    "This product includes cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``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 AUTHOR OR CONTRIBUTORS 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.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+/* ====================================================================
+ * Copyright (c) 1998-2019 The OpenSSL 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. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    openssl-core@openssl.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED 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 OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS 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.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com).  This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+
+#ifndef HEADER_ERR_H
+# define HEADER_ERR_H
+
+# include <openssl/e_os2.h>
+
+# ifndef OPENSSL_NO_FP_API
+#  include <stdio.h>
+#  include <stdlib.h>
+# endif
+
+# include <openssl/ossl_typ.h>
+# ifndef OPENSSL_NO_BIO
+#  include <openssl/bio.h>
+# endif
+# ifndef OPENSSL_NO_LHASH
+#  include <openssl/lhash.h>
+# endif
+
+#ifdef  __cplusplus
+extern "C" {
+#endif
+
+# ifndef OPENSSL_NO_ERR
+#  define ERR_PUT_error(a,b,c,d,e)        ERR_put_error(a,b,c,d,e)
+# else
+#  define ERR_PUT_error(a,b,c,d,e)        ERR_put_error(a,b,c,NULL,0)
+# endif
+
+# include <errno.h>
+
+# define ERR_TXT_MALLOCED        0x01
+# define ERR_TXT_STRING          0x02
+
+# define ERR_FLAG_MARK           0x01
+# define ERR_FLAG_CLEAR          0x02
+
+# define ERR_NUM_ERRORS  16
+typedef struct err_state_st {
+    CRYPTO_THREADID tid;
+    int err_flags[ERR_NUM_ERRORS];
+    unsigned long err_buffer[ERR_NUM_ERRORS];
+    char *err_data[ERR_NUM_ERRORS];
+    int err_data_flags[ERR_NUM_ERRORS];
+    const char *err_file[ERR_NUM_ERRORS];
+    int err_line[ERR_NUM_ERRORS];
+    int top, bottom;
+} ERR_STATE;
+
+/* library */
+# define ERR_LIB_NONE            1
+# define ERR_LIB_SYS             2
+# define ERR_LIB_BN              3
+# define ERR_LIB_RSA             4
+# define ERR_LIB_DH              5
+# define ERR_LIB_EVP             6
+# define ERR_LIB_BUF             7
+# define ERR_LIB_OBJ             8
+# define ERR_LIB_PEM             9
+# define ERR_LIB_DSA             10
+# define ERR_LIB_X509            11
+/* #define ERR_LIB_METH         12 */
+# define ERR_LIB_ASN1            13
+# define ERR_LIB_CONF            14
+# define ERR_LIB_CRYPTO          15
+# define ERR_LIB_EC              16
+# define ERR_LIB_SSL             20
+/* #define ERR_LIB_SSL23        21 */
+/* #define ERR_LIB_SSL2         22 */
+/* #define ERR_LIB_SSL3         23 */
+/* #define ERR_LIB_RSAREF       30 */
+/* #define ERR_LIB_PROXY        31 */
+# define ERR_LIB_BIO             32
+# define ERR_LIB_PKCS7           33
+# define ERR_LIB_X509V3          34
+# define ERR_LIB_PKCS12          35
+# define ERR_LIB_RAND            36
+# define ERR_LIB_DSO             37
+# define ERR_LIB_ENGINE          38
+# define ERR_LIB_OCSP            39
+# define ERR_LIB_UI              40
+# define ERR_LIB_COMP            41
+# define ERR_LIB_ECDSA           42
+# define ERR_LIB_ECDH            43
+# define ERR_LIB_STORE           44
+# define ERR_LIB_FIPS            45
+# define ERR_LIB_CMS             46
+# define ERR_LIB_TS              47
+# define ERR_LIB_HMAC            48
+# define ERR_LIB_JPAKE           49
+
+# define ERR_LIB_USER            128
+
+# define SYSerr(f,r)  ERR_PUT_error(ERR_LIB_SYS,(f),(r),__FILE__,__LINE__)
+# define BNerr(f,r)   ERR_PUT_error(ERR_LIB_BN,(f),(r),__FILE__,__LINE__)
+# define RSAerr(f,r)  ERR_PUT_error(ERR_LIB_RSA,(f),(r),__FILE__,__LINE__)
+# define DHerr(f,r)   ERR_PUT_error(ERR_LIB_DH,(f),(r),__FILE__,__LINE__)
+# define EVPerr(f,r)  ERR_PUT_error(ERR_LIB_EVP,(f),(r),__FILE__,__LINE__)
+# define BUFerr(f,r)  ERR_PUT_error(ERR_LIB_BUF,(f),(r),__FILE__,__LINE__)
+# define OBJerr(f,r)  ERR_PUT_error(ERR_LIB_OBJ,(f),(r),__FILE__,__LINE__)
+# define PEMerr(f,r)  ERR_PUT_error(ERR_LIB_PEM,(f),(r),__FILE__,__LINE__)
+# define DSAerr(f,r)  ERR_PUT_error(ERR_LIB_DSA,(f),(r),__FILE__,__LINE__)
+# define X509err(f,r) ERR_PUT_error(ERR_LIB_X509,(f),(r),__FILE__,__LINE__)
+# define ASN1err(f,r) ERR_PUT_error(ERR_LIB_ASN1,(f),(r),__FILE__,__LINE__)
+# define CONFerr(f,r) ERR_PUT_error(ERR_LIB_CONF,(f),(r),__FILE__,__LINE__)
+# define CRYPTOerr(f,r) ERR_PUT_error(ERR_LIB_CRYPTO,(f),(r),__FILE__,__LINE__)
+# define ECerr(f,r)   ERR_PUT_error(ERR_LIB_EC,(f),(r),__FILE__,__LINE__)
+# define SSLerr(f,r)  ERR_PUT_error(ERR_LIB_SSL,(f),(r),__FILE__,__LINE__)
+# define BIOerr(f,r)  ERR_PUT_error(ERR_LIB_BIO,(f),(r),__FILE__,__LINE__)
+# define PKCS7err(f,r) ERR_PUT_error(ERR_LIB_PKCS7,(f),(r),__FILE__,__LINE__)
+# define X509V3err(f,r) ERR_PUT_error(ERR_LIB_X509V3,(f),(r),__FILE__,__LINE__)
+# define PKCS12err(f,r) ERR_PUT_error(ERR_LIB_PKCS12,(f),(r),__FILE__,__LINE__)
+# define RANDerr(f,r) ERR_PUT_error(ERR_LIB_RAND,(f),(r),__FILE__,__LINE__)
+# define DSOerr(f,r) ERR_PUT_error(ERR_LIB_DSO,(f),(r),__FILE__,__LINE__)
+# define ENGINEerr(f,r) ERR_PUT_error(ERR_LIB_ENGINE,(f),(r),__FILE__,__LINE__)
+# define OCSPerr(f,r) ERR_PUT_error(ERR_LIB_OCSP,(f),(r),__FILE__,__LINE__)
+# define UIerr(f,r) ERR_PUT_error(ERR_LIB_UI,(f),(r),__FILE__,__LINE__)
+# define COMPerr(f,r) ERR_PUT_error(ERR_LIB_COMP,(f),(r),__FILE__,__LINE__)
+# define ECDSAerr(f,r)  ERR_PUT_error(ERR_LIB_ECDSA,(f),(r),__FILE__,__LINE__)
+# define ECDHerr(f,r)  ERR_PUT_error(ERR_LIB_ECDH,(f),(r),__FILE__,__LINE__)
+# define STOREerr(f,r) ERR_PUT_error(ERR_LIB_STORE,(f),(r),__FILE__,__LINE__)
+# define FIPSerr(f,r) ERR_PUT_error(ERR_LIB_FIPS,(f),(r),__FILE__,__LINE__)
+# define CMSerr(f,r) ERR_PUT_error(ERR_LIB_CMS,(f),(r),__FILE__,__LINE__)
+# define TSerr(f,r) ERR_PUT_error(ERR_LIB_TS,(f),(r),__FILE__,__LINE__)
+# define HMACerr(f,r) ERR_PUT_error(ERR_LIB_HMAC,(f),(r),__FILE__,__LINE__)
+# define JPAKEerr(f,r) ERR_PUT_error(ERR_LIB_JPAKE,(f),(r),__FILE__,__LINE__)
+
+/*
+ * Borland C seems too stupid to be able to shift and do longs in the
+ * pre-processor :-(
+ */
+# define ERR_PACK(l,f,r)         (((((unsigned long)l)&0xffL)*0x1000000)| \
+                                ((((unsigned long)f)&0xfffL)*0x1000)| \
+                                ((((unsigned long)r)&0xfffL)))
+# define ERR_GET_LIB(l)          (int)((((unsigned long)l)>>24L)&0xffL)
+# define ERR_GET_FUNC(l)         (int)((((unsigned long)l)>>12L)&0xfffL)
+# define ERR_GET_REASON(l)       (int)((l)&0xfffL)
+# define ERR_FATAL_ERROR(l)      (int)((l)&ERR_R_FATAL)
+
+/* OS functions */
+# define SYS_F_FOPEN             1
+# define SYS_F_CONNECT           2
+# define SYS_F_GETSERVBYNAME     3
+# define SYS_F_SOCKET            4
+# define SYS_F_IOCTLSOCKET       5
+# define SYS_F_BIND              6
+# define SYS_F_LISTEN            7
+# define SYS_F_ACCEPT            8
+# define SYS_F_WSASTARTUP        9/* Winsock stuff */
+# define SYS_F_OPENDIR           10
+# define SYS_F_FREAD             11
+# define SYS_F_FFLUSH            18
+
+/* reasons */
+# define ERR_R_SYS_LIB   ERR_LIB_SYS/* 2 */
+# define ERR_R_BN_LIB    ERR_LIB_BN/* 3 */
+# define ERR_R_RSA_LIB   ERR_LIB_RSA/* 4 */
+# define ERR_R_DH_LIB    ERR_LIB_DH/* 5 */
+# define ERR_R_EVP_LIB   ERR_LIB_EVP/* 6 */
+# define ERR_R_BUF_LIB   ERR_LIB_BUF/* 7 */
+# define ERR_R_OBJ_LIB   ERR_LIB_OBJ/* 8 */
+# define ERR_R_PEM_LIB   ERR_LIB_PEM/* 9 */
+# define ERR_R_DSA_LIB   ERR_LIB_DSA/* 10 */
+# define ERR_R_X509_LIB  ERR_LIB_X509/* 11 */
+# define ERR_R_ASN1_LIB  ERR_LIB_ASN1/* 13 */
+# define ERR_R_CONF_LIB  ERR_LIB_CONF/* 14 */
+# define ERR_R_CRYPTO_LIB ERR_LIB_CRYPTO/* 15 */
+# define ERR_R_EC_LIB    ERR_LIB_EC/* 16 */
+# define ERR_R_SSL_LIB   ERR_LIB_SSL/* 20 */
+# define ERR_R_BIO_LIB   ERR_LIB_BIO/* 32 */
+# define ERR_R_PKCS7_LIB ERR_LIB_PKCS7/* 33 */
+# define ERR_R_X509V3_LIB ERR_LIB_X509V3/* 34 */
+# define ERR_R_PKCS12_LIB ERR_LIB_PKCS12/* 35 */
+# define ERR_R_RAND_LIB  ERR_LIB_RAND/* 36 */
+# define ERR_R_DSO_LIB   ERR_LIB_DSO/* 37 */
+# define ERR_R_ENGINE_LIB ERR_LIB_ENGINE/* 38 */
+# define ERR_R_OCSP_LIB  ERR_LIB_OCSP/* 39 */
+# define ERR_R_UI_LIB    ERR_LIB_UI/* 40 */
+# define ERR_R_COMP_LIB  ERR_LIB_COMP/* 41 */
+# define ERR_R_ECDSA_LIB ERR_LIB_ECDSA/* 42 */
+# define ERR_R_ECDH_LIB  ERR_LIB_ECDH/* 43 */
+# define ERR_R_STORE_LIB ERR_LIB_STORE/* 44 */
+# define ERR_R_TS_LIB    ERR_LIB_TS/* 45 */
+
+# define ERR_R_NESTED_ASN1_ERROR                 58
+# define ERR_R_BAD_ASN1_OBJECT_HEADER            59
+# define ERR_R_BAD_GET_ASN1_OBJECT_CALL          60
+# define ERR_R_EXPECTING_AN_ASN1_SEQUENCE        61
+# define ERR_R_ASN1_LENGTH_MISMATCH              62
+# define ERR_R_MISSING_ASN1_EOS                  63
+
+/* fatal error */
+# define ERR_R_FATAL                             64
+# define ERR_R_MALLOC_FAILURE                    (1|ERR_R_FATAL)
+# define ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED       (2|ERR_R_FATAL)
+# define ERR_R_PASSED_NULL_PARAMETER             (3|ERR_R_FATAL)
+# define ERR_R_INTERNAL_ERROR                    (4|ERR_R_FATAL)
+# define ERR_R_DISABLED                          (5|ERR_R_FATAL)
+
+/*
+ * 99 is the maximum possible ERR_R_... code, higher values are reserved for
+ * the individual libraries
+ */
+
+typedef struct ERR_string_data_st {
+    unsigned long error;
+    const char *string;
+} ERR_STRING_DATA;
+
+void ERR_put_error(int lib, int func, int reason, const char *file, int line);
+void ERR_set_error_data(char *data, int flags);
+
+unsigned long ERR_get_error(void);
+unsigned long ERR_get_error_line(const char **file, int *line);
+unsigned long ERR_get_error_line_data(const char **file, int *line,
+                                      const char **data, int *flags);
+unsigned long ERR_peek_error(void);
+unsigned long ERR_peek_error_line(const char **file, int *line);
+unsigned long ERR_peek_error_line_data(const char **file, int *line,
+                                       const char **data, int *flags);
+unsigned long ERR_peek_last_error(void);
+unsigned long ERR_peek_last_error_line(const char **file, int *line);
+unsigned long ERR_peek_last_error_line_data(const char **file, int *line,
+                                            const char **data, int *flags);
+void ERR_clear_error(void);
+char *ERR_error_string(unsigned long e, char *buf);
+void ERR_error_string_n(unsigned long e, char *buf, size_t len);
+const char *ERR_lib_error_string(unsigned long e);
+const char *ERR_func_error_string(unsigned long e);
+const char *ERR_reason_error_string(unsigned long e);
+void ERR_print_errors_cb(int (*cb) (const char *str, size_t len, void *u),
+                         void *u);
+# ifndef OPENSSL_NO_FP_API
+void ERR_print_errors_fp(FILE *fp);
+# endif
+# ifndef OPENSSL_NO_BIO
+void ERR_print_errors(BIO *bp);
+# endif
+void ERR_add_error_data(int num, ...);
+void ERR_add_error_vdata(int num, va_list args);
+void ERR_load_strings(int lib, ERR_STRING_DATA str[]);
+void ERR_unload_strings(int lib, ERR_STRING_DATA str[]);
+void ERR_load_ERR_strings(void);
+void ERR_load_crypto_strings(void);
+void ERR_free_strings(void);
+
+void ERR_remove_thread_state(const CRYPTO_THREADID *tid);
+# ifndef OPENSSL_NO_DEPRECATED
+void ERR_remove_state(unsigned long pid); /* if zero we look it up */
+# endif
+ERR_STATE *ERR_get_state(void);
+
+# ifndef OPENSSL_NO_LHASH
+LHASH_OF(ERR_STRING_DATA) *ERR_get_string_table(void);
+LHASH_OF(ERR_STATE) *ERR_get_err_state_table(void);
+void ERR_release_err_state_table(LHASH_OF(ERR_STATE) **hash);
+# endif
+
+int ERR_get_next_error_library(void);
+
+int ERR_set_mark(void);
+int ERR_pop_to_mark(void);
+
+/* Already defined in ossl_typ.h */
+/* typedef struct st_ERR_FNS ERR_FNS; */
+/*
+ * An application can use this function and provide the return value to
+ * loaded modules that should use the application's ERR state/functionality
+ */
+const ERR_FNS *ERR_get_implementation(void);
+/*
+ * A loaded module should call this function prior to any ERR operations
+ * using the application's "ERR_FNS".
+ */
+int ERR_set_implementation(const ERR_FNS *fns);
+
+#ifdef  __cplusplus
+}
+#endif
+
+#endif

+ 1630 - 0
libssh2/openssl/include/openssl/evp.h

@@ -0,0 +1,1630 @@
+/* crypto/evp/evp.h */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * 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 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. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    "This product includes cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``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 AUTHOR OR CONTRIBUTORS 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.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+#ifndef HEADER_ENVELOPE_H
+# define HEADER_ENVELOPE_H
+
+# ifdef OPENSSL_ALGORITHM_DEFINES
+#  include <openssl/opensslconf.h>
+# else
+#  define OPENSSL_ALGORITHM_DEFINES
+#  include <openssl/opensslconf.h>
+#  undef OPENSSL_ALGORITHM_DEFINES
+# endif
+
+# include <openssl/ossl_typ.h>
+
+# include <openssl/symhacks.h>
+
+# ifndef OPENSSL_NO_BIO
+#  include <openssl/bio.h>
+# endif
+
+/*-
+#define EVP_RC2_KEY_SIZE                16
+#define EVP_RC4_KEY_SIZE                16
+#define EVP_BLOWFISH_KEY_SIZE           16
+#define EVP_CAST5_KEY_SIZE              16
+#define EVP_RC5_32_12_16_KEY_SIZE       16
+*/
+# define EVP_MAX_MD_SIZE                 64/* longest known is SHA512 */
+# define EVP_MAX_KEY_LENGTH              64
+# define EVP_MAX_IV_LENGTH               16
+# define EVP_MAX_BLOCK_LENGTH            32
+
+# define PKCS5_SALT_LEN                  8
+/* Default PKCS#5 iteration count */
+# define PKCS5_DEFAULT_ITER              2048
+
+# include <openssl/objects.h>
+
+# define EVP_PK_RSA      0x0001
+# define EVP_PK_DSA      0x0002
+# define EVP_PK_DH       0x0004
+# define EVP_PK_EC       0x0008
+# define EVP_PKT_SIGN    0x0010
+# define EVP_PKT_ENC     0x0020
+# define EVP_PKT_EXCH    0x0040
+# define EVP_PKS_RSA     0x0100
+# define EVP_PKS_DSA     0x0200
+# define EVP_PKS_EC      0x0400
+
+# define EVP_PKEY_NONE   NID_undef
+# define EVP_PKEY_RSA    NID_rsaEncryption
+# define EVP_PKEY_RSA2   NID_rsa
+# define EVP_PKEY_DSA    NID_dsa
+# define EVP_PKEY_DSA1   NID_dsa_2
+# define EVP_PKEY_DSA2   NID_dsaWithSHA
+# define EVP_PKEY_DSA3   NID_dsaWithSHA1
+# define EVP_PKEY_DSA4   NID_dsaWithSHA1_2
+# define EVP_PKEY_DH     NID_dhKeyAgreement
+# define EVP_PKEY_DHX    NID_dhpublicnumber
+# define EVP_PKEY_EC     NID_X9_62_id_ecPublicKey
+# define EVP_PKEY_HMAC   NID_hmac
+# define EVP_PKEY_CMAC   NID_cmac
+
+#ifdef  __cplusplus
+extern "C" {
+#endif
+
+/*
+ * Type needs to be a bit field Sub-type needs to be for variations on the
+ * method, as in, can it do arbitrary encryption....
+ */
+struct evp_pkey_st {
+    int type;
+    int save_type;
+    int references;
+    const EVP_PKEY_ASN1_METHOD *ameth;
+    ENGINE *engine;
+    union {
+        char *ptr;
+# ifndef OPENSSL_NO_RSA
+        struct rsa_st *rsa;     /* RSA */
+# endif
+# ifndef OPENSSL_NO_DSA
+        struct dsa_st *dsa;     /* DSA */
+# endif
+# ifndef OPENSSL_NO_DH
+        struct dh_st *dh;       /* DH */
+# endif
+# ifndef OPENSSL_NO_EC
+        struct ec_key_st *ec;   /* ECC */
+# endif
+    } pkey;
+    int save_parameters;
+    STACK_OF(X509_ATTRIBUTE) *attributes; /* [ 0 ] */
+} /* EVP_PKEY */ ;
+
+# define EVP_PKEY_MO_SIGN        0x0001
+# define EVP_PKEY_MO_VERIFY      0x0002
+# define EVP_PKEY_MO_ENCRYPT     0x0004
+# define EVP_PKEY_MO_DECRYPT     0x0008
+
+# ifndef EVP_MD
+struct env_md_st {
+    int type;
+    int pkey_type;
+    int md_size;
+    unsigned long flags;
+    int (*init) (EVP_MD_CTX *ctx);
+    int (*update) (EVP_MD_CTX *ctx, const void *data, size_t count);
+    int (*final) (EVP_MD_CTX *ctx, unsigned char *md);
+    int (*copy) (EVP_MD_CTX *to, const EVP_MD_CTX *from);
+    int (*cleanup) (EVP_MD_CTX *ctx);
+    /* FIXME: prototype these some day */
+    int (*sign) (int type, const unsigned char *m, unsigned int m_length,
+                 unsigned char *sigret, unsigned int *siglen, void *key);
+    int (*verify) (int type, const unsigned char *m, unsigned int m_length,
+                   const unsigned char *sigbuf, unsigned int siglen,
+                   void *key);
+    int required_pkey_type[5];  /* EVP_PKEY_xxx */
+    int block_size;
+    int ctx_size;               /* how big does the ctx->md_data need to be */
+    /* control function */
+    int (*md_ctrl) (EVP_MD_CTX *ctx, int cmd, int p1, void *p2);
+} /* EVP_MD */ ;
+
+typedef int evp_sign_method(int type, const unsigned char *m,
+                            unsigned int m_length, unsigned char *sigret,
+                            unsigned int *siglen, void *key);
+typedef int evp_verify_method(int type, const unsigned char *m,
+                              unsigned int m_length,
+                              const unsigned char *sigbuf,
+                              unsigned int siglen, void *key);
+
+/* digest can only handle a single block */
+#  define EVP_MD_FLAG_ONESHOT     0x0001
+
+/*
+ * digest is a "clone" digest used
+ * which is a copy of an existing
+ * one for a specific public key type.
+ * EVP_dss1() etc
+ */
+#  define EVP_MD_FLAG_PKEY_DIGEST 0x0002
+
+/* Digest uses EVP_PKEY_METHOD for signing instead of MD specific signing */
+
+#  define EVP_MD_FLAG_PKEY_METHOD_SIGNATURE       0x0004
+
+/* DigestAlgorithmIdentifier flags... */
+
+#  define EVP_MD_FLAG_DIGALGID_MASK               0x0018
+
+/* NULL or absent parameter accepted. Use NULL */
+
+#  define EVP_MD_FLAG_DIGALGID_NULL               0x0000
+
+/* NULL or absent parameter accepted. Use NULL for PKCS#1 otherwise absent */
+
+#  define EVP_MD_FLAG_DIGALGID_ABSENT             0x0008
+
+/* Custom handling via ctrl */
+
+#  define EVP_MD_FLAG_DIGALGID_CUSTOM             0x0018
+
+/* Note if suitable for use in FIPS mode */
+#  define EVP_MD_FLAG_FIPS        0x0400
+
+/* Digest ctrls */
+
+#  define EVP_MD_CTRL_DIGALGID                    0x1
+#  define EVP_MD_CTRL_MICALG                      0x2
+
+/* Minimum Algorithm specific ctrl value */
+
+#  define EVP_MD_CTRL_ALG_CTRL                    0x1000
+
+#  define EVP_PKEY_NULL_method    NULL,NULL,{0,0,0,0}
+
+#  ifndef OPENSSL_NO_DSA
+#   define EVP_PKEY_DSA_method     (evp_sign_method *)DSA_sign, \
+                                (evp_verify_method *)DSA_verify, \
+                                {EVP_PKEY_DSA,EVP_PKEY_DSA2,EVP_PKEY_DSA3, \
+                                        EVP_PKEY_DSA4,0}
+#  else
+#   define EVP_PKEY_DSA_method     EVP_PKEY_NULL_method
+#  endif
+
+#  ifndef OPENSSL_NO_ECDSA
+#   define EVP_PKEY_ECDSA_method   (evp_sign_method *)ECDSA_sign, \
+                                (evp_verify_method *)ECDSA_verify, \
+                                 {EVP_PKEY_EC,0,0,0}
+#  else
+#   define EVP_PKEY_ECDSA_method   EVP_PKEY_NULL_method
+#  endif
+
+#  ifndef OPENSSL_NO_RSA
+#   define EVP_PKEY_RSA_method     (evp_sign_method *)RSA_sign, \
+                                (evp_verify_method *)RSA_verify, \
+                                {EVP_PKEY_RSA,EVP_PKEY_RSA2,0,0}
+#   define EVP_PKEY_RSA_ASN1_OCTET_STRING_method \
+                                (evp_sign_method *)RSA_sign_ASN1_OCTET_STRING, \
+                                (evp_verify_method *)RSA_verify_ASN1_OCTET_STRING, \
+                                {EVP_PKEY_RSA,EVP_PKEY_RSA2,0,0}
+#  else
+#   define EVP_PKEY_RSA_method     EVP_PKEY_NULL_method
+#   define EVP_PKEY_RSA_ASN1_OCTET_STRING_method EVP_PKEY_NULL_method
+#  endif
+
+# endif                         /* !EVP_MD */
+
+struct env_md_ctx_st {
+    const EVP_MD *digest;
+    ENGINE *engine;             /* functional reference if 'digest' is
+                                 * ENGINE-provided */
+    unsigned long flags;
+    void *md_data;
+    /* Public key context for sign/verify */
+    EVP_PKEY_CTX *pctx;
+    /* Update function: usually copied from EVP_MD */
+    int (*update) (EVP_MD_CTX *ctx, const void *data, size_t count);
+} /* EVP_MD_CTX */ ;
+
+/* values for EVP_MD_CTX flags */
+
+# define EVP_MD_CTX_FLAG_ONESHOT         0x0001/* digest update will be
+                                                * called once only */
+# define EVP_MD_CTX_FLAG_CLEANED         0x0002/* context has already been
+                                                * cleaned */
+# define EVP_MD_CTX_FLAG_REUSE           0x0004/* Don't free up ctx->md_data
+                                                * in EVP_MD_CTX_cleanup */
+/*
+ * FIPS and pad options are ignored in 1.0.0, definitions are here so we
+ * don't accidentally reuse the values for other purposes.
+ */
+
+# define EVP_MD_CTX_FLAG_NON_FIPS_ALLOW  0x0008/* Allow use of non FIPS
+                                                * digest in FIPS mode */
+
+/*
+ * The following PAD options are also currently ignored in 1.0.0, digest
+ * parameters are handled through EVP_DigestSign*() and EVP_DigestVerify*()
+ * instead.
+ */
+# define EVP_MD_CTX_FLAG_PAD_MASK        0xF0/* RSA mode to use */
+# define EVP_MD_CTX_FLAG_PAD_PKCS1       0x00/* PKCS#1 v1.5 mode */
+# define EVP_MD_CTX_FLAG_PAD_X931        0x10/* X9.31 mode */
+# define EVP_MD_CTX_FLAG_PAD_PSS         0x20/* PSS mode */
+
+# define EVP_MD_CTX_FLAG_NO_INIT         0x0100/* Don't initialize md_data */
+
+struct evp_cipher_st {
+    int nid;
+    int block_size;
+    /* Default value for variable length ciphers */
+    int key_len;
+    int iv_len;
+    /* Various flags */
+    unsigned long flags;
+    /* init key */
+    int (*init) (EVP_CIPHER_CTX *ctx, const unsigned char *key,
+                 const unsigned char *iv, int enc);
+    /* encrypt/decrypt data */
+    int (*do_cipher) (EVP_CIPHER_CTX *ctx, unsigned char *out,
+                      const unsigned char *in, size_t inl);
+    /* cleanup ctx */
+    int (*cleanup) (EVP_CIPHER_CTX *);
+    /* how big ctx->cipher_data needs to be */
+    int ctx_size;
+    /* Populate a ASN1_TYPE with parameters */
+    int (*set_asn1_parameters) (EVP_CIPHER_CTX *, ASN1_TYPE *);
+    /* Get parameters from a ASN1_TYPE */
+    int (*get_asn1_parameters) (EVP_CIPHER_CTX *, ASN1_TYPE *);
+    /* Miscellaneous operations */
+    int (*ctrl) (EVP_CIPHER_CTX *, int type, int arg, void *ptr);
+    /* Application data */
+    void *app_data;
+} /* EVP_CIPHER */ ;
+
+/* Values for cipher flags */
+
+/* Modes for ciphers */
+
+# define         EVP_CIPH_STREAM_CIPHER          0x0
+# define         EVP_CIPH_ECB_MODE               0x1
+# define         EVP_CIPH_CBC_MODE               0x2
+# define         EVP_CIPH_CFB_MODE               0x3
+# define         EVP_CIPH_OFB_MODE               0x4
+# define         EVP_CIPH_CTR_MODE               0x5
+# define         EVP_CIPH_GCM_MODE               0x6
+# define         EVP_CIPH_CCM_MODE               0x7
+# define         EVP_CIPH_XTS_MODE               0x10001
+# define         EVP_CIPH_WRAP_MODE              0x10002
+# define         EVP_CIPH_MODE                   0xF0007
+/* Set if variable length cipher */
+# define         EVP_CIPH_VARIABLE_LENGTH        0x8
+/* Set if the iv handling should be done by the cipher itself */
+# define         EVP_CIPH_CUSTOM_IV              0x10
+/* Set if the cipher's init() function should be called if key is NULL */
+# define         EVP_CIPH_ALWAYS_CALL_INIT       0x20
+/* Call ctrl() to init cipher parameters */
+# define         EVP_CIPH_CTRL_INIT              0x40
+/* Don't use standard key length function */
+# define         EVP_CIPH_CUSTOM_KEY_LENGTH      0x80
+/* Don't use standard block padding */
+# define         EVP_CIPH_NO_PADDING             0x100
+/* cipher handles random key generation */
+# define         EVP_CIPH_RAND_KEY               0x200
+/* cipher has its own additional copying logic */
+# define         EVP_CIPH_CUSTOM_COPY            0x400
+/* Allow use default ASN1 get/set iv */
+# define         EVP_CIPH_FLAG_DEFAULT_ASN1      0x1000
+/* Buffer length in bits not bytes: CFB1 mode only */
+# define         EVP_CIPH_FLAG_LENGTH_BITS       0x2000
+/* Note if suitable for use in FIPS mode */
+# define         EVP_CIPH_FLAG_FIPS              0x4000
+/* Allow non FIPS cipher in FIPS mode */
+# define         EVP_CIPH_FLAG_NON_FIPS_ALLOW    0x8000
+/*
+ * Cipher handles any and all padding logic as well as finalisation.
+ */
+# define         EVP_CIPH_FLAG_CUSTOM_CIPHER     0x100000
+# define         EVP_CIPH_FLAG_AEAD_CIPHER       0x200000
+# define         EVP_CIPH_FLAG_TLS1_1_MULTIBLOCK 0x400000
+
+/*
+ * Cipher context flag to indicate we can handle wrap mode: if allowed in
+ * older applications it could overflow buffers.
+ */
+
+# define         EVP_CIPHER_CTX_FLAG_WRAP_ALLOW  0x1
+
+/* ctrl() values */
+
+# define         EVP_CTRL_INIT                   0x0
+# define         EVP_CTRL_SET_KEY_LENGTH         0x1
+# define         EVP_CTRL_GET_RC2_KEY_BITS       0x2
+# define         EVP_CTRL_SET_RC2_KEY_BITS       0x3
+# define         EVP_CTRL_GET_RC5_ROUNDS         0x4
+# define         EVP_CTRL_SET_RC5_ROUNDS         0x5
+# define         EVP_CTRL_RAND_KEY               0x6
+# define         EVP_CTRL_PBE_PRF_NID            0x7
+# define         EVP_CTRL_COPY                   0x8
+# define         EVP_CTRL_GCM_SET_IVLEN          0x9
+# define         EVP_CTRL_GCM_GET_TAG            0x10
+# define         EVP_CTRL_GCM_SET_TAG            0x11
+# define         EVP_CTRL_GCM_SET_IV_FIXED       0x12
+# define         EVP_CTRL_GCM_IV_GEN             0x13
+# define         EVP_CTRL_CCM_SET_IVLEN          EVP_CTRL_GCM_SET_IVLEN
+# define         EVP_CTRL_CCM_GET_TAG            EVP_CTRL_GCM_GET_TAG
+# define         EVP_CTRL_CCM_SET_TAG            EVP_CTRL_GCM_SET_TAG
+# define         EVP_CTRL_CCM_SET_L              0x14
+# define         EVP_CTRL_CCM_SET_MSGLEN         0x15
+/*
+ * AEAD cipher deduces payload length and returns number of bytes required to
+ * store MAC and eventual padding. Subsequent call to EVP_Cipher even
+ * appends/verifies MAC.
+ */
+# define         EVP_CTRL_AEAD_TLS1_AAD          0x16
+/* Used by composite AEAD ciphers, no-op in GCM, CCM... */
+# define         EVP_CTRL_AEAD_SET_MAC_KEY       0x17
+/* Set the GCM invocation field, decrypt only */
+# define         EVP_CTRL_GCM_SET_IV_INV         0x18
+
+# define         EVP_CTRL_TLS1_1_MULTIBLOCK_AAD  0x19
+# define         EVP_CTRL_TLS1_1_MULTIBLOCK_ENCRYPT      0x1a
+# define         EVP_CTRL_TLS1_1_MULTIBLOCK_DECRYPT      0x1b
+# define         EVP_CTRL_TLS1_1_MULTIBLOCK_MAX_BUFSIZE  0x1c
+
+/* RFC 5246 defines additional data to be 13 bytes in length */
+# define         EVP_AEAD_TLS1_AAD_LEN           13
+
+typedef struct {
+    unsigned char *out;
+    const unsigned char *inp;
+    size_t len;
+    unsigned int interleave;
+} EVP_CTRL_TLS1_1_MULTIBLOCK_PARAM;
+
+/* GCM TLS constants */
+/* Length of fixed part of IV derived from PRF */
+# define EVP_GCM_TLS_FIXED_IV_LEN                        4
+/* Length of explicit part of IV part of TLS records */
+# define EVP_GCM_TLS_EXPLICIT_IV_LEN                     8
+/* Length of tag for TLS */
+# define EVP_GCM_TLS_TAG_LEN                             16
+
+typedef struct evp_cipher_info_st {
+    const EVP_CIPHER *cipher;
+    unsigned char iv[EVP_MAX_IV_LENGTH];
+} EVP_CIPHER_INFO;
+
+struct evp_cipher_ctx_st {
+    const EVP_CIPHER *cipher;
+    ENGINE *engine;             /* functional reference if 'cipher' is
+                                 * ENGINE-provided */
+    int encrypt;                /* encrypt or decrypt */
+    int buf_len;                /* number we have left */
+    unsigned char oiv[EVP_MAX_IV_LENGTH]; /* original iv */
+    unsigned char iv[EVP_MAX_IV_LENGTH]; /* working iv */
+    unsigned char buf[EVP_MAX_BLOCK_LENGTH]; /* saved partial block */
+    int num;                    /* used by cfb/ofb/ctr mode */
+    void *app_data;             /* application stuff */
+    int key_len;                /* May change for variable length cipher */
+    unsigned long flags;        /* Various flags */
+    void *cipher_data;          /* per EVP data */
+    int final_used;
+    int block_mask;
+    unsigned char final[EVP_MAX_BLOCK_LENGTH]; /* possible final block */
+} /* EVP_CIPHER_CTX */ ;
+
+typedef struct evp_Encode_Ctx_st {
+    /* number saved in a partial encode/decode */
+    int num;
+    /*
+     * The length is either the output line length (in input bytes) or the
+     * shortest input line length that is ok.  Once decoding begins, the
+     * length is adjusted up each time a longer line is decoded
+     */
+    int length;
+    /* data to encode */
+    unsigned char enc_data[80];
+    /* number read on current line */
+    int line_num;
+    int expect_nl;
+} EVP_ENCODE_CTX;
+
+/* Password based encryption function */
+typedef int (EVP_PBE_KEYGEN) (EVP_CIPHER_CTX *ctx, const char *pass,
+                              int passlen, ASN1_TYPE *param,
+                              const EVP_CIPHER *cipher, const EVP_MD *md,
+                              int en_de);
+
+# ifndef OPENSSL_NO_RSA
+#  define EVP_PKEY_assign_RSA(pkey,rsa) EVP_PKEY_assign((pkey),EVP_PKEY_RSA,\
+                                        (char *)(rsa))
+# endif
+
+# ifndef OPENSSL_NO_DSA
+#  define EVP_PKEY_assign_DSA(pkey,dsa) EVP_PKEY_assign((pkey),EVP_PKEY_DSA,\
+                                        (char *)(dsa))
+# endif
+
+# ifndef OPENSSL_NO_DH
+#  define EVP_PKEY_assign_DH(pkey,dh) EVP_PKEY_assign((pkey),EVP_PKEY_DH,\
+                                        (char *)(dh))
+# endif
+
+# ifndef OPENSSL_NO_EC
+#  define EVP_PKEY_assign_EC_KEY(pkey,eckey) EVP_PKEY_assign((pkey),EVP_PKEY_EC,\
+                                        (char *)(eckey))
+# endif
+
+/* Add some extra combinations */
+# define EVP_get_digestbynid(a) EVP_get_digestbyname(OBJ_nid2sn(a))
+# define EVP_get_digestbyobj(a) EVP_get_digestbynid(OBJ_obj2nid(a))
+# define EVP_get_cipherbynid(a) EVP_get_cipherbyname(OBJ_nid2sn(a))
+# define EVP_get_cipherbyobj(a) EVP_get_cipherbynid(OBJ_obj2nid(a))
+
+int EVP_MD_type(const EVP_MD *md);
+# define EVP_MD_nid(e)                   EVP_MD_type(e)
+# define EVP_MD_name(e)                  OBJ_nid2sn(EVP_MD_nid(e))
+int EVP_MD_pkey_type(const EVP_MD *md);
+int EVP_MD_size(const EVP_MD *md);
+int EVP_MD_block_size(const EVP_MD *md);
+unsigned long EVP_MD_flags(const EVP_MD *md);
+
+const EVP_MD *EVP_MD_CTX_md(const EVP_MD_CTX *ctx);
+# define EVP_MD_CTX_size(e)              EVP_MD_size(EVP_MD_CTX_md(e))
+# define EVP_MD_CTX_block_size(e)        EVP_MD_block_size(EVP_MD_CTX_md(e))
+# define EVP_MD_CTX_type(e)              EVP_MD_type(EVP_MD_CTX_md(e))
+
+int EVP_CIPHER_nid(const EVP_CIPHER *cipher);
+# define EVP_CIPHER_name(e)              OBJ_nid2sn(EVP_CIPHER_nid(e))
+int EVP_CIPHER_block_size(const EVP_CIPHER *cipher);
+int EVP_CIPHER_key_length(const EVP_CIPHER *cipher);
+int EVP_CIPHER_iv_length(const EVP_CIPHER *cipher);
+unsigned long EVP_CIPHER_flags(const EVP_CIPHER *cipher);
+# define EVP_CIPHER_mode(e)              (EVP_CIPHER_flags(e) & EVP_CIPH_MODE)
+
+const EVP_CIPHER *EVP_CIPHER_CTX_cipher(const EVP_CIPHER_CTX *ctx);
+int EVP_CIPHER_CTX_nid(const EVP_CIPHER_CTX *ctx);
+int EVP_CIPHER_CTX_block_size(const EVP_CIPHER_CTX *ctx);
+int EVP_CIPHER_CTX_key_length(const EVP_CIPHER_CTX *ctx);
+int EVP_CIPHER_CTX_iv_length(const EVP_CIPHER_CTX *ctx);
+int EVP_CIPHER_CTX_copy(EVP_CIPHER_CTX *out, const EVP_CIPHER_CTX *in);
+void *EVP_CIPHER_CTX_get_app_data(const EVP_CIPHER_CTX *ctx);
+void EVP_CIPHER_CTX_set_app_data(EVP_CIPHER_CTX *ctx, void *data);
+# define EVP_CIPHER_CTX_type(c)         EVP_CIPHER_type(EVP_CIPHER_CTX_cipher(c))
+unsigned long EVP_CIPHER_CTX_flags(const EVP_CIPHER_CTX *ctx);
+# define EVP_CIPHER_CTX_mode(e)          (EVP_CIPHER_CTX_flags(e) & EVP_CIPH_MODE)
+
+# define EVP_ENCODE_LENGTH(l)    (((l+2)/3*4)+(l/48+1)*2+80)
+# define EVP_DECODE_LENGTH(l)    ((l+3)/4*3+80)
+
+# define EVP_SignInit_ex(a,b,c)          EVP_DigestInit_ex(a,b,c)
+# define EVP_SignInit(a,b)               EVP_DigestInit(a,b)
+# define EVP_SignUpdate(a,b,c)           EVP_DigestUpdate(a,b,c)
+# define EVP_VerifyInit_ex(a,b,c)        EVP_DigestInit_ex(a,b,c)
+# define EVP_VerifyInit(a,b)             EVP_DigestInit(a,b)
+# define EVP_VerifyUpdate(a,b,c)         EVP_DigestUpdate(a,b,c)
+# define EVP_OpenUpdate(a,b,c,d,e)       EVP_DecryptUpdate(a,b,c,d,e)
+# define EVP_SealUpdate(a,b,c,d,e)       EVP_EncryptUpdate(a,b,c,d,e)
+# define EVP_DigestSignUpdate(a,b,c)     EVP_DigestUpdate(a,b,c)
+# define EVP_DigestVerifyUpdate(a,b,c)   EVP_DigestUpdate(a,b,c)
+
+# ifdef CONST_STRICT
+void BIO_set_md(BIO *, const EVP_MD *md);
+# else
+#  define BIO_set_md(b,md)               BIO_ctrl(b,BIO_C_SET_MD,0,(char *)md)
+# endif
+# define BIO_get_md(b,mdp)               BIO_ctrl(b,BIO_C_GET_MD,0,(char *)mdp)
+# define BIO_get_md_ctx(b,mdcp)     BIO_ctrl(b,BIO_C_GET_MD_CTX,0,(char *)mdcp)
+# define BIO_set_md_ctx(b,mdcp)     BIO_ctrl(b,BIO_C_SET_MD_CTX,0,(char *)mdcp)
+# define BIO_get_cipher_status(b)        BIO_ctrl(b,BIO_C_GET_CIPHER_STATUS,0,NULL)
+# define BIO_get_cipher_ctx(b,c_pp)      BIO_ctrl(b,BIO_C_GET_CIPHER_CTX,0,(char *)c_pp)
+
+int EVP_Cipher(EVP_CIPHER_CTX *c,
+               unsigned char *out, const unsigned char *in, unsigned int inl);
+
+# define EVP_add_cipher_alias(n,alias) \
+        OBJ_NAME_add((alias),OBJ_NAME_TYPE_CIPHER_METH|OBJ_NAME_ALIAS,(n))
+# define EVP_add_digest_alias(n,alias) \
+        OBJ_NAME_add((alias),OBJ_NAME_TYPE_MD_METH|OBJ_NAME_ALIAS,(n))
+# define EVP_delete_cipher_alias(alias) \
+        OBJ_NAME_remove(alias,OBJ_NAME_TYPE_CIPHER_METH|OBJ_NAME_ALIAS);
+# define EVP_delete_digest_alias(alias) \
+        OBJ_NAME_remove(alias,OBJ_NAME_TYPE_MD_METH|OBJ_NAME_ALIAS);
+
+void EVP_MD_CTX_init(EVP_MD_CTX *ctx);
+int EVP_MD_CTX_cleanup(EVP_MD_CTX *ctx);
+EVP_MD_CTX *EVP_MD_CTX_create(void);
+void EVP_MD_CTX_destroy(EVP_MD_CTX *ctx);
+int EVP_MD_CTX_copy_ex(EVP_MD_CTX *out, const EVP_MD_CTX *in);
+void EVP_MD_CTX_set_flags(EVP_MD_CTX *ctx, int flags);
+void EVP_MD_CTX_clear_flags(EVP_MD_CTX *ctx, int flags);
+int EVP_MD_CTX_test_flags(const EVP_MD_CTX *ctx, int flags);
+int EVP_DigestInit_ex(EVP_MD_CTX *ctx, const EVP_MD *type, ENGINE *impl);
+int EVP_DigestUpdate(EVP_MD_CTX *ctx, const void *d, size_t cnt);
+int EVP_DigestFinal_ex(EVP_MD_CTX *ctx, unsigned char *md, unsigned int *s);
+int EVP_Digest(const void *data, size_t count,
+               unsigned char *md, unsigned int *size, const EVP_MD *type,
+               ENGINE *impl);
+
+int EVP_MD_CTX_copy(EVP_MD_CTX *out, const EVP_MD_CTX *in);
+int EVP_DigestInit(EVP_MD_CTX *ctx, const EVP_MD *type);
+int EVP_DigestFinal(EVP_MD_CTX *ctx, unsigned char *md, unsigned int *s);
+
+int EVP_read_pw_string(char *buf, int length, const char *prompt, int verify);
+int EVP_read_pw_string_min(char *buf, int minlen, int maxlen,
+                           const char *prompt, int verify);
+void EVP_set_pw_prompt(const char *prompt);
+char *EVP_get_pw_prompt(void);
+
+int EVP_BytesToKey(const EVP_CIPHER *type, const EVP_MD *md,
+                   const unsigned char *salt, const unsigned char *data,
+                   int datal, int count, unsigned char *key,
+                   unsigned char *iv);
+
+void EVP_CIPHER_CTX_set_flags(EVP_CIPHER_CTX *ctx, int flags);
+void EVP_CIPHER_CTX_clear_flags(EVP_CIPHER_CTX *ctx, int flags);
+int EVP_CIPHER_CTX_test_flags(const EVP_CIPHER_CTX *ctx, int flags);
+
+int EVP_EncryptInit(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *cipher,
+                    const unsigned char *key, const unsigned char *iv);
+int EVP_EncryptInit_ex(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *cipher,
+                       ENGINE *impl, const unsigned char *key,
+                       const unsigned char *iv);
+int EVP_EncryptUpdate(EVP_CIPHER_CTX *ctx, unsigned char *out, int *outl,
+                      const unsigned char *in, int inl);
+int EVP_EncryptFinal_ex(EVP_CIPHER_CTX *ctx, unsigned char *out, int *outl);
+int EVP_EncryptFinal(EVP_CIPHER_CTX *ctx, unsigned char *out, int *outl);
+
+int EVP_DecryptInit(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *cipher,
+                    const unsigned char *key, const unsigned char *iv);
+int EVP_DecryptInit_ex(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *cipher,
+                       ENGINE *impl, const unsigned char *key,
+                       const unsigned char *iv);
+int EVP_DecryptUpdate(EVP_CIPHER_CTX *ctx, unsigned char *out, int *outl,
+                      const unsigned char *in, int inl);
+int EVP_DecryptFinal(EVP_CIPHER_CTX *ctx, unsigned char *outm, int *outl);
+int EVP_DecryptFinal_ex(EVP_CIPHER_CTX *ctx, unsigned char *outm, int *outl);
+
+int EVP_CipherInit(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *cipher,
+                   const unsigned char *key, const unsigned char *iv,
+                   int enc);
+int EVP_CipherInit_ex(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *cipher,
+                      ENGINE *impl, const unsigned char *key,
+                      const unsigned char *iv, int enc);
+int EVP_CipherUpdate(EVP_CIPHER_CTX *ctx, unsigned char *out, int *outl,
+                     const unsigned char *in, int inl);
+int EVP_CipherFinal(EVP_CIPHER_CTX *ctx, unsigned char *outm, int *outl);
+int EVP_CipherFinal_ex(EVP_CIPHER_CTX *ctx, unsigned char *outm, int *outl);
+
+int EVP_SignFinal(EVP_MD_CTX *ctx, unsigned char *md, unsigned int *s,
+                  EVP_PKEY *pkey);
+
+int EVP_VerifyFinal(EVP_MD_CTX *ctx, const unsigned char *sigbuf,
+                    unsigned int siglen, EVP_PKEY *pkey);
+
+int EVP_DigestSignInit(EVP_MD_CTX *ctx, EVP_PKEY_CTX **pctx,
+                       const EVP_MD *type, ENGINE *e, EVP_PKEY *pkey);
+int EVP_DigestSignFinal(EVP_MD_CTX *ctx,
+                        unsigned char *sigret, size_t *siglen);
+
+int EVP_DigestVerifyInit(EVP_MD_CTX *ctx, EVP_PKEY_CTX **pctx,
+                         const EVP_MD *type, ENGINE *e, EVP_PKEY *pkey);
+int EVP_DigestVerifyFinal(EVP_MD_CTX *ctx,
+                          const unsigned char *sig, size_t siglen);
+
+int EVP_OpenInit(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *type,
+                 const unsigned char *ek, int ekl, const unsigned char *iv,
+                 EVP_PKEY *priv);
+int EVP_OpenFinal(EVP_CIPHER_CTX *ctx, unsigned char *out, int *outl);
+
+int EVP_SealInit(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *type,
+                 unsigned char **ek, int *ekl, unsigned char *iv,
+                 EVP_PKEY **pubk, int npubk);
+int EVP_SealFinal(EVP_CIPHER_CTX *ctx, unsigned char *out, int *outl);
+
+void EVP_EncodeInit(EVP_ENCODE_CTX *ctx);
+void EVP_EncodeUpdate(EVP_ENCODE_CTX *ctx, unsigned char *out, int *outl,
+                      const unsigned char *in, int inl);
+void EVP_EncodeFinal(EVP_ENCODE_CTX *ctx, unsigned char *out, int *outl);
+int EVP_EncodeBlock(unsigned char *t, const unsigned char *f, int n);
+
+void EVP_DecodeInit(EVP_ENCODE_CTX *ctx);
+int EVP_DecodeUpdate(EVP_ENCODE_CTX *ctx, unsigned char *out, int *outl,
+                     const unsigned char *in, int inl);
+int EVP_DecodeFinal(EVP_ENCODE_CTX *ctx, unsigned
+                    char *out, int *outl);
+int EVP_DecodeBlock(unsigned char *t, const unsigned char *f, int n);
+
+void EVP_CIPHER_CTX_init(EVP_CIPHER_CTX *a);
+int EVP_CIPHER_CTX_cleanup(EVP_CIPHER_CTX *a);
+EVP_CIPHER_CTX *EVP_CIPHER_CTX_new(void);
+void EVP_CIPHER_CTX_free(EVP_CIPHER_CTX *a);
+int EVP_CIPHER_CTX_set_key_length(EVP_CIPHER_CTX *x, int keylen);
+int EVP_CIPHER_CTX_set_padding(EVP_CIPHER_CTX *c, int pad);
+int EVP_CIPHER_CTX_ctrl(EVP_CIPHER_CTX *ctx, int type, int arg, void *ptr);
+int EVP_CIPHER_CTX_rand_key(EVP_CIPHER_CTX *ctx, unsigned char *key);
+
+# ifndef OPENSSL_NO_BIO
+BIO_METHOD *BIO_f_md(void);
+BIO_METHOD *BIO_f_base64(void);
+BIO_METHOD *BIO_f_cipher(void);
+BIO_METHOD *BIO_f_reliable(void);
+void BIO_set_cipher(BIO *b, const EVP_CIPHER *c, const unsigned char *k,
+                    const unsigned char *i, int enc);
+# endif
+
+const EVP_MD *EVP_md_null(void);
+# ifndef OPENSSL_NO_MD2
+const EVP_MD *EVP_md2(void);
+# endif
+# ifndef OPENSSL_NO_MD4
+const EVP_MD *EVP_md4(void);
+# endif
+# ifndef OPENSSL_NO_MD5
+const EVP_MD *EVP_md5(void);
+# endif
+# ifndef OPENSSL_NO_SHA
+const EVP_MD *EVP_sha(void);
+const EVP_MD *EVP_sha1(void);
+const EVP_MD *EVP_dss(void);
+const EVP_MD *EVP_dss1(void);
+const EVP_MD *EVP_ecdsa(void);
+# endif
+# ifndef OPENSSL_NO_SHA256
+const EVP_MD *EVP_sha224(void);
+const EVP_MD *EVP_sha256(void);
+# endif
+# ifndef OPENSSL_NO_SHA512
+const EVP_MD *EVP_sha384(void);
+const EVP_MD *EVP_sha512(void);
+# endif
+# ifndef OPENSSL_NO_MDC2
+const EVP_MD *EVP_mdc2(void);
+# endif
+# ifndef OPENSSL_NO_RIPEMD
+const EVP_MD *EVP_ripemd160(void);
+# endif
+# ifndef OPENSSL_NO_WHIRLPOOL
+const EVP_MD *EVP_whirlpool(void);
+# endif
+const EVP_CIPHER *EVP_enc_null(void); /* does nothing :-) */
+# ifndef OPENSSL_NO_DES
+const EVP_CIPHER *EVP_des_ecb(void);
+const EVP_CIPHER *EVP_des_ede(void);
+const EVP_CIPHER *EVP_des_ede3(void);
+const EVP_CIPHER *EVP_des_ede_ecb(void);
+const EVP_CIPHER *EVP_des_ede3_ecb(void);
+const EVP_CIPHER *EVP_des_cfb64(void);
+#  define EVP_des_cfb EVP_des_cfb64
+const EVP_CIPHER *EVP_des_cfb1(void);
+const EVP_CIPHER *EVP_des_cfb8(void);
+const EVP_CIPHER *EVP_des_ede_cfb64(void);
+#  define EVP_des_ede_cfb EVP_des_ede_cfb64
+#  if 0
+const EVP_CIPHER *EVP_des_ede_cfb1(void);
+const EVP_CIPHER *EVP_des_ede_cfb8(void);
+#  endif
+const EVP_CIPHER *EVP_des_ede3_cfb64(void);
+#  define EVP_des_ede3_cfb EVP_des_ede3_cfb64
+const EVP_CIPHER *EVP_des_ede3_cfb1(void);
+const EVP_CIPHER *EVP_des_ede3_cfb8(void);
+const EVP_CIPHER *EVP_des_ofb(void);
+const EVP_CIPHER *EVP_des_ede_ofb(void);
+const EVP_CIPHER *EVP_des_ede3_ofb(void);
+const EVP_CIPHER *EVP_des_cbc(void);
+const EVP_CIPHER *EVP_des_ede_cbc(void);
+const EVP_CIPHER *EVP_des_ede3_cbc(void);
+const EVP_CIPHER *EVP_desx_cbc(void);
+const EVP_CIPHER *EVP_des_ede3_wrap(void);
+/*
+ * This should now be supported through the dev_crypto ENGINE. But also, why
+ * are rc4 and md5 declarations made here inside a "NO_DES" precompiler
+ * branch?
+ */
+#  if 0
+#   ifdef OPENSSL_OPENBSD_DEV_CRYPTO
+const EVP_CIPHER *EVP_dev_crypto_des_ede3_cbc(void);
+const EVP_CIPHER *EVP_dev_crypto_rc4(void);
+const EVP_MD *EVP_dev_crypto_md5(void);
+#   endif
+#  endif
+# endif
+# ifndef OPENSSL_NO_RC4
+const EVP_CIPHER *EVP_rc4(void);
+const EVP_CIPHER *EVP_rc4_40(void);
+#  ifndef OPENSSL_NO_MD5
+const EVP_CIPHER *EVP_rc4_hmac_md5(void);
+#  endif
+# endif
+# ifndef OPENSSL_NO_IDEA
+const EVP_CIPHER *EVP_idea_ecb(void);
+const EVP_CIPHER *EVP_idea_cfb64(void);
+#  define EVP_idea_cfb EVP_idea_cfb64
+const EVP_CIPHER *EVP_idea_ofb(void);
+const EVP_CIPHER *EVP_idea_cbc(void);
+# endif
+# ifndef OPENSSL_NO_RC2
+const EVP_CIPHER *EVP_rc2_ecb(void);
+const EVP_CIPHER *EVP_rc2_cbc(void);
+const EVP_CIPHER *EVP_rc2_40_cbc(void);
+const EVP_CIPHER *EVP_rc2_64_cbc(void);
+const EVP_CIPHER *EVP_rc2_cfb64(void);
+#  define EVP_rc2_cfb EVP_rc2_cfb64
+const EVP_CIPHER *EVP_rc2_ofb(void);
+# endif
+# ifndef OPENSSL_NO_BF
+const EVP_CIPHER *EVP_bf_ecb(void);
+const EVP_CIPHER *EVP_bf_cbc(void);
+const EVP_CIPHER *EVP_bf_cfb64(void);
+#  define EVP_bf_cfb EVP_bf_cfb64
+const EVP_CIPHER *EVP_bf_ofb(void);
+# endif
+# ifndef OPENSSL_NO_CAST
+const EVP_CIPHER *EVP_cast5_ecb(void);
+const EVP_CIPHER *EVP_cast5_cbc(void);
+const EVP_CIPHER *EVP_cast5_cfb64(void);
+#  define EVP_cast5_cfb EVP_cast5_cfb64
+const EVP_CIPHER *EVP_cast5_ofb(void);
+# endif
+# ifndef OPENSSL_NO_RC5
+const EVP_CIPHER *EVP_rc5_32_12_16_cbc(void);
+const EVP_CIPHER *EVP_rc5_32_12_16_ecb(void);
+const EVP_CIPHER *EVP_rc5_32_12_16_cfb64(void);
+#  define EVP_rc5_32_12_16_cfb EVP_rc5_32_12_16_cfb64
+const EVP_CIPHER *EVP_rc5_32_12_16_ofb(void);
+# endif
+# ifndef OPENSSL_NO_AES
+const EVP_CIPHER *EVP_aes_128_ecb(void);
+const EVP_CIPHER *EVP_aes_128_cbc(void);
+const EVP_CIPHER *EVP_aes_128_cfb1(void);
+const EVP_CIPHER *EVP_aes_128_cfb8(void);
+const EVP_CIPHER *EVP_aes_128_cfb128(void);
+#  define EVP_aes_128_cfb EVP_aes_128_cfb128
+const EVP_CIPHER *EVP_aes_128_ofb(void);
+const EVP_CIPHER *EVP_aes_128_ctr(void);
+const EVP_CIPHER *EVP_aes_128_ccm(void);
+const EVP_CIPHER *EVP_aes_128_gcm(void);
+const EVP_CIPHER *EVP_aes_128_xts(void);
+const EVP_CIPHER *EVP_aes_128_wrap(void);
+const EVP_CIPHER *EVP_aes_192_ecb(void);
+const EVP_CIPHER *EVP_aes_192_cbc(void);
+const EVP_CIPHER *EVP_aes_192_cfb1(void);
+const EVP_CIPHER *EVP_aes_192_cfb8(void);
+const EVP_CIPHER *EVP_aes_192_cfb128(void);
+#  define EVP_aes_192_cfb EVP_aes_192_cfb128
+const EVP_CIPHER *EVP_aes_192_ofb(void);
+const EVP_CIPHER *EVP_aes_192_ctr(void);
+const EVP_CIPHER *EVP_aes_192_ccm(void);
+const EVP_CIPHER *EVP_aes_192_gcm(void);
+const EVP_CIPHER *EVP_aes_192_wrap(void);
+const EVP_CIPHER *EVP_aes_256_ecb(void);
+const EVP_CIPHER *EVP_aes_256_cbc(void);
+const EVP_CIPHER *EVP_aes_256_cfb1(void);
+const EVP_CIPHER *EVP_aes_256_cfb8(void);
+const EVP_CIPHER *EVP_aes_256_cfb128(void);
+#  define EVP_aes_256_cfb EVP_aes_256_cfb128
+const EVP_CIPHER *EVP_aes_256_ofb(void);
+const EVP_CIPHER *EVP_aes_256_ctr(void);
+const EVP_CIPHER *EVP_aes_256_ccm(void);
+const EVP_CIPHER *EVP_aes_256_gcm(void);
+const EVP_CIPHER *EVP_aes_256_xts(void);
+const EVP_CIPHER *EVP_aes_256_wrap(void);
+#  if !defined(OPENSSL_NO_SHA) && !defined(OPENSSL_NO_SHA1)
+const EVP_CIPHER *EVP_aes_128_cbc_hmac_sha1(void);
+const EVP_CIPHER *EVP_aes_256_cbc_hmac_sha1(void);
+#  endif
+#  ifndef OPENSSL_NO_SHA256
+const EVP_CIPHER *EVP_aes_128_cbc_hmac_sha256(void);
+const EVP_CIPHER *EVP_aes_256_cbc_hmac_sha256(void);
+#  endif
+# endif
+# ifndef OPENSSL_NO_CAMELLIA
+const EVP_CIPHER *EVP_camellia_128_ecb(void);
+const EVP_CIPHER *EVP_camellia_128_cbc(void);
+const EVP_CIPHER *EVP_camellia_128_cfb1(void);
+const EVP_CIPHER *EVP_camellia_128_cfb8(void);
+const EVP_CIPHER *EVP_camellia_128_cfb128(void);
+#  define EVP_camellia_128_cfb EVP_camellia_128_cfb128
+const EVP_CIPHER *EVP_camellia_128_ofb(void);
+const EVP_CIPHER *EVP_camellia_192_ecb(void);
+const EVP_CIPHER *EVP_camellia_192_cbc(void);
+const EVP_CIPHER *EVP_camellia_192_cfb1(void);
+const EVP_CIPHER *EVP_camellia_192_cfb8(void);
+const EVP_CIPHER *EVP_camellia_192_cfb128(void);
+#  define EVP_camellia_192_cfb EVP_camellia_192_cfb128
+const EVP_CIPHER *EVP_camellia_192_ofb(void);
+const EVP_CIPHER *EVP_camellia_256_ecb(void);
+const EVP_CIPHER *EVP_camellia_256_cbc(void);
+const EVP_CIPHER *EVP_camellia_256_cfb1(void);
+const EVP_CIPHER *EVP_camellia_256_cfb8(void);
+const EVP_CIPHER *EVP_camellia_256_cfb128(void);
+#  define EVP_camellia_256_cfb EVP_camellia_256_cfb128
+const EVP_CIPHER *EVP_camellia_256_ofb(void);
+# endif
+
+# ifndef OPENSSL_NO_SEED
+const EVP_CIPHER *EVP_seed_ecb(void);
+const EVP_CIPHER *EVP_seed_cbc(void);
+const EVP_CIPHER *EVP_seed_cfb128(void);
+#  define EVP_seed_cfb EVP_seed_cfb128
+const EVP_CIPHER *EVP_seed_ofb(void);
+# endif
+
+void OPENSSL_add_all_algorithms_noconf(void);
+void OPENSSL_add_all_algorithms_conf(void);
+
+# ifdef OPENSSL_LOAD_CONF
+#  define OpenSSL_add_all_algorithms() \
+                OPENSSL_add_all_algorithms_conf()
+# else
+#  define OpenSSL_add_all_algorithms() \
+                OPENSSL_add_all_algorithms_noconf()
+# endif
+
+void OpenSSL_add_all_ciphers(void);
+void OpenSSL_add_all_digests(void);
+# define SSLeay_add_all_algorithms() OpenSSL_add_all_algorithms()
+# define SSLeay_add_all_ciphers() OpenSSL_add_all_ciphers()
+# define SSLeay_add_all_digests() OpenSSL_add_all_digests()
+
+int EVP_add_cipher(const EVP_CIPHER *cipher);
+int EVP_add_digest(const EVP_MD *digest);
+
+const EVP_CIPHER *EVP_get_cipherbyname(const char *name);
+const EVP_MD *EVP_get_digestbyname(const char *name);
+void EVP_cleanup(void);
+
+void EVP_CIPHER_do_all(void (*fn) (const EVP_CIPHER *ciph,
+                                   const char *from, const char *to, void *x),
+                       void *arg);
+void EVP_CIPHER_do_all_sorted(void (*fn)
+                               (const EVP_CIPHER *ciph, const char *from,
+                                const char *to, void *x), void *arg);
+
+void EVP_MD_do_all(void (*fn) (const EVP_MD *ciph,
+                               const char *from, const char *to, void *x),
+                   void *arg);
+void EVP_MD_do_all_sorted(void (*fn)
+                           (const EVP_MD *ciph, const char *from,
+                            const char *to, void *x), void *arg);
+
+int EVP_PKEY_decrypt_old(unsigned char *dec_key,
+                         const unsigned char *enc_key, int enc_key_len,
+                         EVP_PKEY *private_key);
+int EVP_PKEY_encrypt_old(unsigned char *enc_key,
+                         const unsigned char *key, int key_len,
+                         EVP_PKEY *pub_key);
+int EVP_PKEY_type(int type);
+int EVP_PKEY_id(const EVP_PKEY *pkey);
+int EVP_PKEY_base_id(const EVP_PKEY *pkey);
+int EVP_PKEY_bits(EVP_PKEY *pkey);
+int EVP_PKEY_size(EVP_PKEY *pkey);
+int EVP_PKEY_set_type(EVP_PKEY *pkey, int type);
+int EVP_PKEY_set_type_str(EVP_PKEY *pkey, const char *str, int len);
+int EVP_PKEY_assign(EVP_PKEY *pkey, int type, void *key);
+void *EVP_PKEY_get0(EVP_PKEY *pkey);
+
+# ifndef OPENSSL_NO_RSA
+struct rsa_st;
+int EVP_PKEY_set1_RSA(EVP_PKEY *pkey, struct rsa_st *key);
+struct rsa_st *EVP_PKEY_get1_RSA(EVP_PKEY *pkey);
+# endif
+# ifndef OPENSSL_NO_DSA
+struct dsa_st;
+int EVP_PKEY_set1_DSA(EVP_PKEY *pkey, struct dsa_st *key);
+struct dsa_st *EVP_PKEY_get1_DSA(EVP_PKEY *pkey);
+# endif
+# ifndef OPENSSL_NO_DH
+struct dh_st;
+int EVP_PKEY_set1_DH(EVP_PKEY *pkey, struct dh_st *key);
+struct dh_st *EVP_PKEY_get1_DH(EVP_PKEY *pkey);
+# endif
+# ifndef OPENSSL_NO_EC
+struct ec_key_st;
+int EVP_PKEY_set1_EC_KEY(EVP_PKEY *pkey, struct ec_key_st *key);
+struct ec_key_st *EVP_PKEY_get1_EC_KEY(EVP_PKEY *pkey);
+# endif
+
+EVP_PKEY *EVP_PKEY_new(void);
+void EVP_PKEY_free(EVP_PKEY *pkey);
+
+EVP_PKEY *d2i_PublicKey(int type, EVP_PKEY **a, const unsigned char **pp,
+                        long length);
+int i2d_PublicKey(EVP_PKEY *a, unsigned char **pp);
+
+EVP_PKEY *d2i_PrivateKey(int type, EVP_PKEY **a, const unsigned char **pp,
+                         long length);
+EVP_PKEY *d2i_AutoPrivateKey(EVP_PKEY **a, const unsigned char **pp,
+                             long length);
+int i2d_PrivateKey(EVP_PKEY *a, unsigned char **pp);
+
+int EVP_PKEY_copy_parameters(EVP_PKEY *to, const EVP_PKEY *from);
+int EVP_PKEY_missing_parameters(const EVP_PKEY *pkey);
+int EVP_PKEY_save_parameters(EVP_PKEY *pkey, int mode);
+int EVP_PKEY_cmp_parameters(const EVP_PKEY *a, const EVP_PKEY *b);
+
+int EVP_PKEY_cmp(const EVP_PKEY *a, const EVP_PKEY *b);
+
+int EVP_PKEY_print_public(BIO *out, const EVP_PKEY *pkey,
+                          int indent, ASN1_PCTX *pctx);
+int EVP_PKEY_print_private(BIO *out, const EVP_PKEY *pkey,
+                           int indent, ASN1_PCTX *pctx);
+int EVP_PKEY_print_params(BIO *out, const EVP_PKEY *pkey,
+                          int indent, ASN1_PCTX *pctx);
+
+int EVP_PKEY_get_default_digest_nid(EVP_PKEY *pkey, int *pnid);
+
+int EVP_CIPHER_type(const EVP_CIPHER *ctx);
+
+/* calls methods */
+int EVP_CIPHER_param_to_asn1(EVP_CIPHER_CTX *c, ASN1_TYPE *type);
+int EVP_CIPHER_asn1_to_param(EVP_CIPHER_CTX *c, ASN1_TYPE *type);
+
+/* These are used by EVP_CIPHER methods */
+int EVP_CIPHER_set_asn1_iv(EVP_CIPHER_CTX *c, ASN1_TYPE *type);
+int EVP_CIPHER_get_asn1_iv(EVP_CIPHER_CTX *c, ASN1_TYPE *type);
+
+/* PKCS5 password based encryption */
+int PKCS5_PBE_keyivgen(EVP_CIPHER_CTX *ctx, const char *pass, int passlen,
+                       ASN1_TYPE *param, const EVP_CIPHER *cipher,
+                       const EVP_MD *md, int en_de);
+int PKCS5_PBKDF2_HMAC_SHA1(const char *pass, int passlen,
+                           const unsigned char *salt, int saltlen, int iter,
+                           int keylen, unsigned char *out);
+int PKCS5_PBKDF2_HMAC(const char *pass, int passlen,
+                      const unsigned char *salt, int saltlen, int iter,
+                      const EVP_MD *digest, int keylen, unsigned char *out);
+int PKCS5_v2_PBE_keyivgen(EVP_CIPHER_CTX *ctx, const char *pass, int passlen,
+                          ASN1_TYPE *param, const EVP_CIPHER *cipher,
+                          const EVP_MD *md, int en_de);
+
+void PKCS5_PBE_add(void);
+
+int EVP_PBE_CipherInit(ASN1_OBJECT *pbe_obj, const char *pass, int passlen,
+                       ASN1_TYPE *param, EVP_CIPHER_CTX *ctx, int en_de);
+
+/* PBE type */
+
+/* Can appear as the outermost AlgorithmIdentifier */
+# define EVP_PBE_TYPE_OUTER      0x0
+/* Is an PRF type OID */
+# define EVP_PBE_TYPE_PRF        0x1
+
+int EVP_PBE_alg_add_type(int pbe_type, int pbe_nid, int cipher_nid,
+                         int md_nid, EVP_PBE_KEYGEN *keygen);
+int EVP_PBE_alg_add(int nid, const EVP_CIPHER *cipher, const EVP_MD *md,
+                    EVP_PBE_KEYGEN *keygen);
+int EVP_PBE_find(int type, int pbe_nid, int *pcnid, int *pmnid,
+                 EVP_PBE_KEYGEN **pkeygen);
+void EVP_PBE_cleanup(void);
+
+# define ASN1_PKEY_ALIAS         0x1
+# define ASN1_PKEY_DYNAMIC       0x2
+# define ASN1_PKEY_SIGPARAM_NULL 0x4
+
+# define ASN1_PKEY_CTRL_PKCS7_SIGN       0x1
+# define ASN1_PKEY_CTRL_PKCS7_ENCRYPT    0x2
+# define ASN1_PKEY_CTRL_DEFAULT_MD_NID   0x3
+# define ASN1_PKEY_CTRL_CMS_SIGN         0x5
+# define ASN1_PKEY_CTRL_CMS_ENVELOPE     0x7
+# define ASN1_PKEY_CTRL_CMS_RI_TYPE      0x8
+
+int EVP_PKEY_asn1_get_count(void);
+const EVP_PKEY_ASN1_METHOD *EVP_PKEY_asn1_get0(int idx);
+const EVP_PKEY_ASN1_METHOD *EVP_PKEY_asn1_find(ENGINE **pe, int type);
+const EVP_PKEY_ASN1_METHOD *EVP_PKEY_asn1_find_str(ENGINE **pe,
+                                                   const char *str, int len);
+int EVP_PKEY_asn1_add0(const EVP_PKEY_ASN1_METHOD *ameth);
+int EVP_PKEY_asn1_add_alias(int to, int from);
+int EVP_PKEY_asn1_get0_info(int *ppkey_id, int *pkey_base_id,
+                            int *ppkey_flags, const char **pinfo,
+                            const char **ppem_str,
+                            const EVP_PKEY_ASN1_METHOD *ameth);
+
+const EVP_PKEY_ASN1_METHOD *EVP_PKEY_get0_asn1(EVP_PKEY *pkey);
+EVP_PKEY_ASN1_METHOD *EVP_PKEY_asn1_new(int id, int flags,
+                                        const char *pem_str,
+                                        const char *info);
+void EVP_PKEY_asn1_copy(EVP_PKEY_ASN1_METHOD *dst,
+                        const EVP_PKEY_ASN1_METHOD *src);
+void EVP_PKEY_asn1_free(EVP_PKEY_ASN1_METHOD *ameth);
+void EVP_PKEY_asn1_set_public(EVP_PKEY_ASN1_METHOD *ameth,
+                              int (*pub_decode) (EVP_PKEY *pk,
+                                                 X509_PUBKEY *pub),
+                              int (*pub_encode) (X509_PUBKEY *pub,
+                                                 const EVP_PKEY *pk),
+                              int (*pub_cmp) (const EVP_PKEY *a,
+                                              const EVP_PKEY *b),
+                              int (*pub_print) (BIO *out,
+                                                const EVP_PKEY *pkey,
+                                                int indent, ASN1_PCTX *pctx),
+                              int (*pkey_size) (const EVP_PKEY *pk),
+                              int (*pkey_bits) (const EVP_PKEY *pk));
+void EVP_PKEY_asn1_set_private(EVP_PKEY_ASN1_METHOD *ameth,
+                               int (*priv_decode) (EVP_PKEY *pk,
+                                                   PKCS8_PRIV_KEY_INFO
+                                                   *p8inf),
+                               int (*priv_encode) (PKCS8_PRIV_KEY_INFO *p8,
+                                                   const EVP_PKEY *pk),
+                               int (*priv_print) (BIO *out,
+                                                  const EVP_PKEY *pkey,
+                                                  int indent,
+                                                  ASN1_PCTX *pctx));
+void EVP_PKEY_asn1_set_param(EVP_PKEY_ASN1_METHOD *ameth,
+                             int (*param_decode) (EVP_PKEY *pkey,
+                                                  const unsigned char **pder,
+                                                  int derlen),
+                             int (*param_encode) (const EVP_PKEY *pkey,
+                                                  unsigned char **pder),
+                             int (*param_missing) (const EVP_PKEY *pk),
+                             int (*param_copy) (EVP_PKEY *to,
+                                                const EVP_PKEY *from),
+                             int (*param_cmp) (const EVP_PKEY *a,
+                                               const EVP_PKEY *b),
+                             int (*param_print) (BIO *out,
+                                                 const EVP_PKEY *pkey,
+                                                 int indent,
+                                                 ASN1_PCTX *pctx));
+
+void EVP_PKEY_asn1_set_free(EVP_PKEY_ASN1_METHOD *ameth,
+                            void (*pkey_free) (EVP_PKEY *pkey));
+void EVP_PKEY_asn1_set_ctrl(EVP_PKEY_ASN1_METHOD *ameth,
+                            int (*pkey_ctrl) (EVP_PKEY *pkey, int op,
+                                              long arg1, void *arg2));
+void EVP_PKEY_asn1_set_item(EVP_PKEY_ASN1_METHOD *ameth,
+                            int (*item_verify) (EVP_MD_CTX *ctx,
+                                                const ASN1_ITEM *it,
+                                                void *asn,
+                                                X509_ALGOR *a,
+                                                ASN1_BIT_STRING *sig,
+                                                EVP_PKEY *pkey),
+                            int (*item_sign) (EVP_MD_CTX *ctx,
+                                              const ASN1_ITEM *it,
+                                              void *asn,
+                                              X509_ALGOR *alg1,
+                                              X509_ALGOR *alg2,
+                                              ASN1_BIT_STRING *sig));
+
+# define EVP_PKEY_OP_UNDEFINED           0
+# define EVP_PKEY_OP_PARAMGEN            (1<<1)
+# define EVP_PKEY_OP_KEYGEN              (1<<2)
+# define EVP_PKEY_OP_SIGN                (1<<3)
+# define EVP_PKEY_OP_VERIFY              (1<<4)
+# define EVP_PKEY_OP_VERIFYRECOVER       (1<<5)
+# define EVP_PKEY_OP_SIGNCTX             (1<<6)
+# define EVP_PKEY_OP_VERIFYCTX           (1<<7)
+# define EVP_PKEY_OP_ENCRYPT             (1<<8)
+# define EVP_PKEY_OP_DECRYPT             (1<<9)
+# define EVP_PKEY_OP_DERIVE              (1<<10)
+
+# define EVP_PKEY_OP_TYPE_SIG    \
+        (EVP_PKEY_OP_SIGN | EVP_PKEY_OP_VERIFY | EVP_PKEY_OP_VERIFYRECOVER \
+                | EVP_PKEY_OP_SIGNCTX | EVP_PKEY_OP_VERIFYCTX)
+
+# define EVP_PKEY_OP_TYPE_CRYPT \
+        (EVP_PKEY_OP_ENCRYPT | EVP_PKEY_OP_DECRYPT)
+
+# define EVP_PKEY_OP_TYPE_NOGEN \
+        (EVP_PKEY_OP_SIG | EVP_PKEY_OP_CRYPT | EVP_PKEY_OP_DERIVE)
+
+# define EVP_PKEY_OP_TYPE_GEN \
+                (EVP_PKEY_OP_PARAMGEN | EVP_PKEY_OP_KEYGEN)
+
+# define  EVP_PKEY_CTX_set_signature_md(ctx, md) \
+                EVP_PKEY_CTX_ctrl(ctx, -1, EVP_PKEY_OP_TYPE_SIG,  \
+                                        EVP_PKEY_CTRL_MD, 0, (void *)md)
+
+# define  EVP_PKEY_CTX_get_signature_md(ctx, pmd)        \
+                EVP_PKEY_CTX_ctrl(ctx, -1, EVP_PKEY_OP_TYPE_SIG,  \
+                                        EVP_PKEY_CTRL_GET_MD, 0, (void *)pmd)
+
+# define EVP_PKEY_CTRL_MD                1
+# define EVP_PKEY_CTRL_PEER_KEY          2
+
+# define EVP_PKEY_CTRL_PKCS7_ENCRYPT     3
+# define EVP_PKEY_CTRL_PKCS7_DECRYPT     4
+
+# define EVP_PKEY_CTRL_PKCS7_SIGN        5
+
+# define EVP_PKEY_CTRL_SET_MAC_KEY       6
+
+# define EVP_PKEY_CTRL_DIGESTINIT        7
+
+/* Used by GOST key encryption in TLS */
+# define EVP_PKEY_CTRL_SET_IV            8
+
+# define EVP_PKEY_CTRL_CMS_ENCRYPT       9
+# define EVP_PKEY_CTRL_CMS_DECRYPT       10
+# define EVP_PKEY_CTRL_CMS_SIGN          11
+
+# define EVP_PKEY_CTRL_CIPHER            12
+
+# define EVP_PKEY_CTRL_GET_MD            13
+
+# define EVP_PKEY_ALG_CTRL               0x1000
+
+# define EVP_PKEY_FLAG_AUTOARGLEN        2
+/*
+ * Method handles all operations: don't assume any digest related defaults.
+ */
+# define EVP_PKEY_FLAG_SIGCTX_CUSTOM     4
+
+const EVP_PKEY_METHOD *EVP_PKEY_meth_find(int type);
+EVP_PKEY_METHOD *EVP_PKEY_meth_new(int id, int flags);
+void EVP_PKEY_meth_get0_info(int *ppkey_id, int *pflags,
+                             const EVP_PKEY_METHOD *meth);
+void EVP_PKEY_meth_copy(EVP_PKEY_METHOD *dst, const EVP_PKEY_METHOD *src);
+void EVP_PKEY_meth_free(EVP_PKEY_METHOD *pmeth);
+int EVP_PKEY_meth_add0(const EVP_PKEY_METHOD *pmeth);
+
+EVP_PKEY_CTX *EVP_PKEY_CTX_new(EVP_PKEY *pkey, ENGINE *e);
+EVP_PKEY_CTX *EVP_PKEY_CTX_new_id(int id, ENGINE *e);
+EVP_PKEY_CTX *EVP_PKEY_CTX_dup(EVP_PKEY_CTX *ctx);
+void EVP_PKEY_CTX_free(EVP_PKEY_CTX *ctx);
+
+int EVP_PKEY_CTX_ctrl(EVP_PKEY_CTX *ctx, int keytype, int optype,
+                      int cmd, int p1, void *p2);
+int EVP_PKEY_CTX_ctrl_str(EVP_PKEY_CTX *ctx, const char *type,
+                          const char *value);
+
+int EVP_PKEY_CTX_get_operation(EVP_PKEY_CTX *ctx);
+void EVP_PKEY_CTX_set0_keygen_info(EVP_PKEY_CTX *ctx, int *dat, int datlen);
+
+EVP_PKEY *EVP_PKEY_new_mac_key(int type, ENGINE *e,
+                               const unsigned char *key, int keylen);
+
+void EVP_PKEY_CTX_set_data(EVP_PKEY_CTX *ctx, void *data);
+void *EVP_PKEY_CTX_get_data(EVP_PKEY_CTX *ctx);
+EVP_PKEY *EVP_PKEY_CTX_get0_pkey(EVP_PKEY_CTX *ctx);
+
+EVP_PKEY *EVP_PKEY_CTX_get0_peerkey(EVP_PKEY_CTX *ctx);
+
+void EVP_PKEY_CTX_set_app_data(EVP_PKEY_CTX *ctx, void *data);
+void *EVP_PKEY_CTX_get_app_data(EVP_PKEY_CTX *ctx);
+
+int EVP_PKEY_sign_init(EVP_PKEY_CTX *ctx);
+int EVP_PKEY_sign(EVP_PKEY_CTX *ctx,
+                  unsigned char *sig, size_t *siglen,
+                  const unsigned char *tbs, size_t tbslen);
+int EVP_PKEY_verify_init(EVP_PKEY_CTX *ctx);
+int EVP_PKEY_verify(EVP_PKEY_CTX *ctx,
+                    const unsigned char *sig, size_t siglen,
+                    const unsigned char *tbs, size_t tbslen);
+int EVP_PKEY_verify_recover_init(EVP_PKEY_CTX *ctx);
+int EVP_PKEY_verify_recover(EVP_PKEY_CTX *ctx,
+                            unsigned char *rout, size_t *routlen,
+                            const unsigned char *sig, size_t siglen);
+int EVP_PKEY_encrypt_init(EVP_PKEY_CTX *ctx);
+int EVP_PKEY_encrypt(EVP_PKEY_CTX *ctx,
+                     unsigned char *out, size_t *outlen,
+                     const unsigned char *in, size_t inlen);
+int EVP_PKEY_decrypt_init(EVP_PKEY_CTX *ctx);
+int EVP_PKEY_decrypt(EVP_PKEY_CTX *ctx,
+                     unsigned char *out, size_t *outlen,
+                     const unsigned char *in, size_t inlen);
+
+int EVP_PKEY_derive_init(EVP_PKEY_CTX *ctx);
+int EVP_PKEY_derive_set_peer(EVP_PKEY_CTX *ctx, EVP_PKEY *peer);
+int EVP_PKEY_derive(EVP_PKEY_CTX *ctx, unsigned char *key, size_t *keylen);
+
+typedef int EVP_PKEY_gen_cb (EVP_PKEY_CTX *ctx);
+
+int EVP_PKEY_paramgen_init(EVP_PKEY_CTX *ctx);
+int EVP_PKEY_paramgen(EVP_PKEY_CTX *ctx, EVP_PKEY **ppkey);
+int EVP_PKEY_keygen_init(EVP_PKEY_CTX *ctx);
+int EVP_PKEY_keygen(EVP_PKEY_CTX *ctx, EVP_PKEY **ppkey);
+
+void EVP_PKEY_CTX_set_cb(EVP_PKEY_CTX *ctx, EVP_PKEY_gen_cb *cb);
+EVP_PKEY_gen_cb *EVP_PKEY_CTX_get_cb(EVP_PKEY_CTX *ctx);
+
+int EVP_PKEY_CTX_get_keygen_info(EVP_PKEY_CTX *ctx, int idx);
+
+void EVP_PKEY_meth_set_init(EVP_PKEY_METHOD *pmeth,
+                            int (*init) (EVP_PKEY_CTX *ctx));
+
+void EVP_PKEY_meth_set_copy(EVP_PKEY_METHOD *pmeth,
+                            int (*copy) (EVP_PKEY_CTX *dst,
+                                         EVP_PKEY_CTX *src));
+
+void EVP_PKEY_meth_set_cleanup(EVP_PKEY_METHOD *pmeth,
+                               void (*cleanup) (EVP_PKEY_CTX *ctx));
+
+void EVP_PKEY_meth_set_paramgen(EVP_PKEY_METHOD *pmeth,
+                                int (*paramgen_init) (EVP_PKEY_CTX *ctx),
+                                int (*paramgen) (EVP_PKEY_CTX *ctx,
+                                                 EVP_PKEY *pkey));
+
+void EVP_PKEY_meth_set_keygen(EVP_PKEY_METHOD *pmeth,
+                              int (*keygen_init) (EVP_PKEY_CTX *ctx),
+                              int (*keygen) (EVP_PKEY_CTX *ctx,
+                                             EVP_PKEY *pkey));
+
+void EVP_PKEY_meth_set_sign(EVP_PKEY_METHOD *pmeth,
+                            int (*sign_init) (EVP_PKEY_CTX *ctx),
+                            int (*sign) (EVP_PKEY_CTX *ctx,
+                                         unsigned char *sig, size_t *siglen,
+                                         const unsigned char *tbs,
+                                         size_t tbslen));
+
+void EVP_PKEY_meth_set_verify(EVP_PKEY_METHOD *pmeth,
+                              int (*verify_init) (EVP_PKEY_CTX *ctx),
+                              int (*verify) (EVP_PKEY_CTX *ctx,
+                                             const unsigned char *sig,
+                                             size_t siglen,
+                                             const unsigned char *tbs,
+                                             size_t tbslen));
+
+void EVP_PKEY_meth_set_verify_recover(EVP_PKEY_METHOD *pmeth,
+                                      int (*verify_recover_init) (EVP_PKEY_CTX
+                                                                  *ctx),
+                                      int (*verify_recover) (EVP_PKEY_CTX
+                                                             *ctx,
+                                                             unsigned char
+                                                             *sig,
+                                                             size_t *siglen,
+                                                             const unsigned
+                                                             char *tbs,
+                                                             size_t tbslen));
+
+void EVP_PKEY_meth_set_signctx(EVP_PKEY_METHOD *pmeth,
+                               int (*signctx_init) (EVP_PKEY_CTX *ctx,
+                                                    EVP_MD_CTX *mctx),
+                               int (*signctx) (EVP_PKEY_CTX *ctx,
+                                               unsigned char *sig,
+                                               size_t *siglen,
+                                               EVP_MD_CTX *mctx));
+
+void EVP_PKEY_meth_set_verifyctx(EVP_PKEY_METHOD *pmeth,
+                                 int (*verifyctx_init) (EVP_PKEY_CTX *ctx,
+                                                        EVP_MD_CTX *mctx),
+                                 int (*verifyctx) (EVP_PKEY_CTX *ctx,
+                                                   const unsigned char *sig,
+                                                   int siglen,
+                                                   EVP_MD_CTX *mctx));
+
+void EVP_PKEY_meth_set_encrypt(EVP_PKEY_METHOD *pmeth,
+                               int (*encrypt_init) (EVP_PKEY_CTX *ctx),
+                               int (*encryptfn) (EVP_PKEY_CTX *ctx,
+                                                 unsigned char *out,
+                                                 size_t *outlen,
+                                                 const unsigned char *in,
+                                                 size_t inlen));
+
+void EVP_PKEY_meth_set_decrypt(EVP_PKEY_METHOD *pmeth,
+                               int (*decrypt_init) (EVP_PKEY_CTX *ctx),
+                               int (*decrypt) (EVP_PKEY_CTX *ctx,
+                                               unsigned char *out,
+                                               size_t *outlen,
+                                               const unsigned char *in,
+                                               size_t inlen));
+
+void EVP_PKEY_meth_set_derive(EVP_PKEY_METHOD *pmeth,
+                              int (*derive_init) (EVP_PKEY_CTX *ctx),
+                              int (*derive) (EVP_PKEY_CTX *ctx,
+                                             unsigned char *key,
+                                             size_t *keylen));
+
+void EVP_PKEY_meth_set_ctrl(EVP_PKEY_METHOD *pmeth,
+                            int (*ctrl) (EVP_PKEY_CTX *ctx, int type, int p1,
+                                         void *p2),
+                            int (*ctrl_str) (EVP_PKEY_CTX *ctx,
+                                             const char *type,
+                                             const char *value));
+
+void EVP_PKEY_meth_get_init(EVP_PKEY_METHOD *pmeth,
+                            int (**pinit) (EVP_PKEY_CTX *ctx));
+
+void EVP_PKEY_meth_get_copy(EVP_PKEY_METHOD *pmeth,
+                            int (**pcopy) (EVP_PKEY_CTX *dst,
+                                           EVP_PKEY_CTX *src));
+
+void EVP_PKEY_meth_get_cleanup(EVP_PKEY_METHOD *pmeth,
+                               void (**pcleanup) (EVP_PKEY_CTX *ctx));
+
+void EVP_PKEY_meth_get_paramgen(EVP_PKEY_METHOD *pmeth,
+                                int (**pparamgen_init) (EVP_PKEY_CTX *ctx),
+                                int (**pparamgen) (EVP_PKEY_CTX *ctx,
+                                                   EVP_PKEY *pkey));
+
+void EVP_PKEY_meth_get_keygen(EVP_PKEY_METHOD *pmeth,
+                              int (**pkeygen_init) (EVP_PKEY_CTX *ctx),
+                              int (**pkeygen) (EVP_PKEY_CTX *ctx,
+                                               EVP_PKEY *pkey));
+
+void EVP_PKEY_meth_get_sign(EVP_PKEY_METHOD *pmeth,
+                            int (**psign_init) (EVP_PKEY_CTX *ctx),
+                            int (**psign) (EVP_PKEY_CTX *ctx,
+                                           unsigned char *sig, size_t *siglen,
+                                           const unsigned char *tbs,
+                                           size_t tbslen));
+
+void EVP_PKEY_meth_get_verify(EVP_PKEY_METHOD *pmeth,
+                              int (**pverify_init) (EVP_PKEY_CTX *ctx),
+                              int (**pverify) (EVP_PKEY_CTX *ctx,
+                                               const unsigned char *sig,
+                                               size_t siglen,
+                                               const unsigned char *tbs,
+                                               size_t tbslen));
+
+void EVP_PKEY_meth_get_verify_recover(EVP_PKEY_METHOD *pmeth,
+                                      int (**pverify_recover_init) (EVP_PKEY_CTX
+                                                                    *ctx),
+                                      int (**pverify_recover) (EVP_PKEY_CTX
+                                                               *ctx,
+                                                               unsigned char
+                                                               *sig,
+                                                               size_t *siglen,
+                                                               const unsigned
+                                                               char *tbs,
+                                                               size_t tbslen));
+
+void EVP_PKEY_meth_get_signctx(EVP_PKEY_METHOD *pmeth,
+                               int (**psignctx_init) (EVP_PKEY_CTX *ctx,
+                                                      EVP_MD_CTX *mctx),
+                               int (**psignctx) (EVP_PKEY_CTX *ctx,
+                                                 unsigned char *sig,
+                                                 size_t *siglen,
+                                                 EVP_MD_CTX *mctx));
+
+void EVP_PKEY_meth_get_verifyctx(EVP_PKEY_METHOD *pmeth,
+                                 int (**pverifyctx_init) (EVP_PKEY_CTX *ctx,
+                                                          EVP_MD_CTX *mctx),
+                                 int (**pverifyctx) (EVP_PKEY_CTX *ctx,
+                                                     const unsigned char *sig,
+                                                     int siglen,
+                                                     EVP_MD_CTX *mctx));
+
+void EVP_PKEY_meth_get_encrypt(EVP_PKEY_METHOD *pmeth,
+                               int (**pencrypt_init) (EVP_PKEY_CTX *ctx),
+                               int (**pencryptfn) (EVP_PKEY_CTX *ctx,
+                                                   unsigned char *out,
+                                                   size_t *outlen,
+                                                   const unsigned char *in,
+                                                   size_t inlen));
+
+void EVP_PKEY_meth_get_decrypt(EVP_PKEY_METHOD *pmeth,
+                               int (**pdecrypt_init) (EVP_PKEY_CTX *ctx),
+                               int (**pdecrypt) (EVP_PKEY_CTX *ctx,
+                                                 unsigned char *out,
+                                                 size_t *outlen,
+                                                 const unsigned char *in,
+                                                 size_t inlen));
+
+void EVP_PKEY_meth_get_derive(EVP_PKEY_METHOD *pmeth,
+                              int (**pderive_init) (EVP_PKEY_CTX *ctx),
+                              int (**pderive) (EVP_PKEY_CTX *ctx,
+                                               unsigned char *key,
+                                               size_t *keylen));
+
+void EVP_PKEY_meth_get_ctrl(EVP_PKEY_METHOD *pmeth,
+                            int (**pctrl) (EVP_PKEY_CTX *ctx, int type, int p1,
+                                           void *p2),
+                            int (**pctrl_str) (EVP_PKEY_CTX *ctx,
+                                               const char *type,
+                                               const char *value));
+
+void EVP_add_alg_module(void);
+
+/* BEGIN ERROR CODES */
+/*
+ * The following lines are auto generated by the script mkerr.pl. Any changes
+ * made after this point may be overwritten when the script is next run.
+ */
+
+void ERR_load_EVP_strings(void);
+
+/* Error codes for the EVP functions. */
+
+/* Function codes. */
+# define EVP_F_AESNI_INIT_KEY                             165
+# define EVP_F_AESNI_XTS_CIPHER                           176
+# define EVP_F_AES_INIT_KEY                               133
+# define EVP_F_AES_T4_INIT_KEY                            178
+# define EVP_F_AES_XTS                                    172
+# define EVP_F_AES_XTS_CIPHER                             175
+# define EVP_F_ALG_MODULE_INIT                            177
+# define EVP_F_CAMELLIA_INIT_KEY                          159
+# define EVP_F_CMAC_INIT                                  173
+# define EVP_F_CMLL_T4_INIT_KEY                           179
+# define EVP_F_D2I_PKEY                                   100
+# define EVP_F_DO_SIGVER_INIT                             161
+# define EVP_F_DSAPKEY2PKCS8                              134
+# define EVP_F_DSA_PKEY2PKCS8                             135
+# define EVP_F_ECDSA_PKEY2PKCS8                           129
+# define EVP_F_ECKEY_PKEY2PKCS8                           132
+# define EVP_F_EVP_CIPHERINIT_EX                          123
+# define EVP_F_EVP_CIPHER_CTX_COPY                        163
+# define EVP_F_EVP_CIPHER_CTX_CTRL                        124
+# define EVP_F_EVP_CIPHER_CTX_SET_KEY_LENGTH              122
+# define EVP_F_EVP_DECRYPTFINAL_EX                        101
+# define EVP_F_EVP_DECRYPTUPDATE                          181
+# define EVP_F_EVP_DIGESTINIT_EX                          128
+# define EVP_F_EVP_ENCRYPTFINAL_EX                        127
+# define EVP_F_EVP_ENCRYPTUPDATE                          180
+# define EVP_F_EVP_MD_CTX_COPY_EX                         110
+# define EVP_F_EVP_MD_SIZE                                162
+# define EVP_F_EVP_OPENINIT                               102
+# define EVP_F_EVP_PBE_ALG_ADD                            115
+# define EVP_F_EVP_PBE_ALG_ADD_TYPE                       160
+# define EVP_F_EVP_PBE_CIPHERINIT                         116
+# define EVP_F_EVP_PKCS82PKEY                             111
+# define EVP_F_EVP_PKCS82PKEY_BROKEN                      136
+# define EVP_F_EVP_PKEY2PKCS8_BROKEN                      113
+# define EVP_F_EVP_PKEY_COPY_PARAMETERS                   103
+# define EVP_F_EVP_PKEY_CTX_CTRL                          137
+# define EVP_F_EVP_PKEY_CTX_CTRL_STR                      150
+# define EVP_F_EVP_PKEY_CTX_DUP                           156
+# define EVP_F_EVP_PKEY_DECRYPT                           104
+# define EVP_F_EVP_PKEY_DECRYPT_INIT                      138
+# define EVP_F_EVP_PKEY_DECRYPT_OLD                       151
+# define EVP_F_EVP_PKEY_DERIVE                            153
+# define EVP_F_EVP_PKEY_DERIVE_INIT                       154
+# define EVP_F_EVP_PKEY_DERIVE_SET_PEER                   155
+# define EVP_F_EVP_PKEY_ENCRYPT                           105
+# define EVP_F_EVP_PKEY_ENCRYPT_INIT                      139
+# define EVP_F_EVP_PKEY_ENCRYPT_OLD                       152
+# define EVP_F_EVP_PKEY_GET1_DH                           119
+# define EVP_F_EVP_PKEY_GET1_DSA                          120
+# define EVP_F_EVP_PKEY_GET1_ECDSA                        130
+# define EVP_F_EVP_PKEY_GET1_EC_KEY                       131
+# define EVP_F_EVP_PKEY_GET1_RSA                          121
+# define EVP_F_EVP_PKEY_KEYGEN                            146
+# define EVP_F_EVP_PKEY_KEYGEN_INIT                       147
+# define EVP_F_EVP_PKEY_NEW                               106
+# define EVP_F_EVP_PKEY_PARAMGEN                          148
+# define EVP_F_EVP_PKEY_PARAMGEN_INIT                     149
+# define EVP_F_EVP_PKEY_SIGN                              140
+# define EVP_F_EVP_PKEY_SIGN_INIT                         141
+# define EVP_F_EVP_PKEY_VERIFY                            142
+# define EVP_F_EVP_PKEY_VERIFY_INIT                       143
+# define EVP_F_EVP_PKEY_VERIFY_RECOVER                    144
+# define EVP_F_EVP_PKEY_VERIFY_RECOVER_INIT               145
+# define EVP_F_EVP_RIJNDAEL                               126
+# define EVP_F_EVP_SIGNFINAL                              107
+# define EVP_F_EVP_VERIFYFINAL                            108
+# define EVP_F_FIPS_CIPHERINIT                            166
+# define EVP_F_FIPS_CIPHER_CTX_COPY                       170
+# define EVP_F_FIPS_CIPHER_CTX_CTRL                       167
+# define EVP_F_FIPS_CIPHER_CTX_SET_KEY_LENGTH             171
+# define EVP_F_FIPS_DIGESTINIT                            168
+# define EVP_F_FIPS_MD_CTX_COPY                           169
+# define EVP_F_HMAC_INIT_EX                               174
+# define EVP_F_INT_CTX_NEW                                157
+# define EVP_F_PKCS5_PBE_KEYIVGEN                         117
+# define EVP_F_PKCS5_V2_PBE_KEYIVGEN                      118
+# define EVP_F_PKCS5_V2_PBKDF2_KEYIVGEN                   164
+# define EVP_F_PKCS8_SET_BROKEN                           112
+# define EVP_F_PKEY_SET_TYPE                              158
+# define EVP_F_RC2_MAGIC_TO_METH                          109
+# define EVP_F_RC5_CTRL                                   125
+
+/* Reason codes. */
+# define EVP_R_AES_IV_SETUP_FAILED                        162
+# define EVP_R_AES_KEY_SETUP_FAILED                       143
+# define EVP_R_ASN1_LIB                                   140
+# define EVP_R_BAD_BLOCK_LENGTH                           136
+# define EVP_R_BAD_DECRYPT                                100
+# define EVP_R_BAD_KEY_LENGTH                             137
+# define EVP_R_BN_DECODE_ERROR                            112
+# define EVP_R_BN_PUBKEY_ERROR                            113
+# define EVP_R_BUFFER_TOO_SMALL                           155
+# define EVP_R_CAMELLIA_KEY_SETUP_FAILED                  157
+# define EVP_R_CIPHER_PARAMETER_ERROR                     122
+# define EVP_R_COMMAND_NOT_SUPPORTED                      147
+# define EVP_R_CTRL_NOT_IMPLEMENTED                       132
+# define EVP_R_CTRL_OPERATION_NOT_IMPLEMENTED             133
+# define EVP_R_DATA_NOT_MULTIPLE_OF_BLOCK_LENGTH          138
+# define EVP_R_DECODE_ERROR                               114
+# define EVP_R_DIFFERENT_KEY_TYPES                        101
+# define EVP_R_DIFFERENT_PARAMETERS                       153
+# define EVP_R_DISABLED_FOR_FIPS                          163
+# define EVP_R_ENCODE_ERROR                               115
+# define EVP_R_ERROR_LOADING_SECTION                      165
+# define EVP_R_ERROR_SETTING_FIPS_MODE                    166
+# define EVP_R_EVP_PBE_CIPHERINIT_ERROR                   119
+# define EVP_R_EXPECTING_AN_RSA_KEY                       127
+# define EVP_R_EXPECTING_A_DH_KEY                         128
+# define EVP_R_EXPECTING_A_DSA_KEY                        129
+# define EVP_R_EXPECTING_A_ECDSA_KEY                      141
+# define EVP_R_EXPECTING_A_EC_KEY                         142
+# define EVP_R_FIPS_MODE_NOT_SUPPORTED                    167
+# define EVP_R_INITIALIZATION_ERROR                       134
+# define EVP_R_INPUT_NOT_INITIALIZED                      111
+# define EVP_R_INVALID_DIGEST                             152
+# define EVP_R_INVALID_FIPS_MODE                          168
+# define EVP_R_INVALID_KEY                                171
+# define EVP_R_INVALID_KEY_LENGTH                         130
+# define EVP_R_INVALID_OPERATION                          148
+# define EVP_R_IV_TOO_LARGE                               102
+# define EVP_R_KEYGEN_FAILURE                             120
+# define EVP_R_MESSAGE_DIGEST_IS_NULL                     159
+# define EVP_R_METHOD_NOT_SUPPORTED                       144
+# define EVP_R_MISSING_PARAMETERS                         103
+# define EVP_R_NO_CIPHER_SET                              131
+# define EVP_R_NO_DEFAULT_DIGEST                          158
+# define EVP_R_NO_DIGEST_SET                              139
+# define EVP_R_NO_DSA_PARAMETERS                          116
+# define EVP_R_NO_KEY_SET                                 154
+# define EVP_R_NO_OPERATION_SET                           149
+# define EVP_R_NO_SIGN_FUNCTION_CONFIGURED                104
+# define EVP_R_NO_VERIFY_FUNCTION_CONFIGURED              105
+# define EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE   150
+# define EVP_R_OPERATON_NOT_INITIALIZED                   151
+# define EVP_R_PKCS8_UNKNOWN_BROKEN_TYPE                  117
+# define EVP_R_PRIVATE_KEY_DECODE_ERROR                   145
+# define EVP_R_PRIVATE_KEY_ENCODE_ERROR                   146
+# define EVP_R_PUBLIC_KEY_NOT_RSA                         106
+# define EVP_R_TOO_LARGE                                  164
+# define EVP_R_UNKNOWN_CIPHER                             160
+# define EVP_R_UNKNOWN_DIGEST                             161
+# define EVP_R_UNKNOWN_OPTION                             169
+# define EVP_R_UNKNOWN_PBE_ALGORITHM                      121
+# define EVP_R_UNSUPORTED_NUMBER_OF_ROUNDS                135
+# define EVP_R_UNSUPPORTED_ALGORITHM                      156
+# define EVP_R_UNSUPPORTED_CIPHER                         107
+# define EVP_R_UNSUPPORTED_KEYLENGTH                      123
+# define EVP_R_UNSUPPORTED_KEY_DERIVATION_FUNCTION        124
+# define EVP_R_UNSUPPORTED_KEY_SIZE                       108
+# define EVP_R_UNSUPPORTED_PRF                            125
+# define EVP_R_UNSUPPORTED_PRIVATE_KEY_ALGORITHM          118
+# define EVP_R_UNSUPPORTED_SALT_TYPE                      126
+# define EVP_R_WRAP_MODE_NOT_ALLOWED                      170
+# define EVP_R_WRONG_FINAL_BLOCK_LENGTH                   109
+# define EVP_R_WRONG_PUBLIC_KEY_TYPE                      110
+
+# ifdef  __cplusplus
+}
+# endif
+#endif

+ 109 - 0
libssh2/openssl/include/openssl/hmac.h

@@ -0,0 +1,109 @@
+/* crypto/hmac/hmac.h */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * 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 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. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    "This product includes cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``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 AUTHOR OR CONTRIBUTORS 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.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+#ifndef HEADER_HMAC_H
+# define HEADER_HMAC_H
+
+# include <openssl/opensslconf.h>
+
+# ifdef OPENSSL_NO_HMAC
+#  error HMAC is disabled.
+# endif
+
+# include <openssl/evp.h>
+
+# define HMAC_MAX_MD_CBLOCK      128/* largest known is SHA512 */
+
+#ifdef  __cplusplus
+extern "C" {
+#endif
+
+typedef struct hmac_ctx_st {
+    const EVP_MD *md;
+    EVP_MD_CTX md_ctx;
+    EVP_MD_CTX i_ctx;
+    EVP_MD_CTX o_ctx;
+    unsigned int key_length;
+    unsigned char key[HMAC_MAX_MD_CBLOCK];
+} HMAC_CTX;
+
+# define HMAC_size(e)    (EVP_MD_size((e)->md))
+
+void HMAC_CTX_init(HMAC_CTX *ctx);
+void HMAC_CTX_cleanup(HMAC_CTX *ctx);
+
+/* deprecated */
+# define HMAC_cleanup(ctx) HMAC_CTX_cleanup(ctx)
+
+/* deprecated */
+int HMAC_Init(HMAC_CTX *ctx, const void *key, int len, const EVP_MD *md);
+int HMAC_Init_ex(HMAC_CTX *ctx, const void *key, int len,
+                 const EVP_MD *md, ENGINE *impl);
+int HMAC_Update(HMAC_CTX *ctx, const unsigned char *data, size_t len);
+int HMAC_Final(HMAC_CTX *ctx, unsigned char *md, unsigned int *len);
+unsigned char *HMAC(const EVP_MD *evp_md, const void *key, int key_len,
+                    const unsigned char *d, size_t n, unsigned char *md,
+                    unsigned int *md_len);
+int HMAC_CTX_copy(HMAC_CTX *dctx, HMAC_CTX *sctx);
+
+void HMAC_CTX_set_flags(HMAC_CTX *ctx, unsigned long flags);
+
+#ifdef  __cplusplus
+}
+#endif
+
+#endif

+ 105 - 0
libssh2/openssl/include/openssl/idea.h

@@ -0,0 +1,105 @@
+/* crypto/idea/idea.h */
+/* Copyright (C) 1995-1997 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * 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 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. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    "This product includes cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``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 AUTHOR OR CONTRIBUTORS 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.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+#ifndef HEADER_IDEA_H
+# define HEADER_IDEA_H
+
+# include <openssl/opensslconf.h>/* IDEA_INT, OPENSSL_NO_IDEA */
+
+# ifdef OPENSSL_NO_IDEA
+#  error IDEA is disabled.
+# endif
+
+# define IDEA_ENCRYPT    1
+# define IDEA_DECRYPT    0
+
+# define IDEA_BLOCK      8
+# define IDEA_KEY_LENGTH 16
+
+#ifdef  __cplusplus
+extern "C" {
+#endif
+
+typedef struct idea_key_st {
+    IDEA_INT data[9][6];
+} IDEA_KEY_SCHEDULE;
+
+const char *idea_options(void);
+void idea_ecb_encrypt(const unsigned char *in, unsigned char *out,
+                      IDEA_KEY_SCHEDULE *ks);
+# ifdef OPENSSL_FIPS
+void private_idea_set_encrypt_key(const unsigned char *key,
+                                  IDEA_KEY_SCHEDULE *ks);
+# endif
+void idea_set_encrypt_key(const unsigned char *key, IDEA_KEY_SCHEDULE *ks);
+void idea_set_decrypt_key(IDEA_KEY_SCHEDULE *ek, IDEA_KEY_SCHEDULE *dk);
+void idea_cbc_encrypt(const unsigned char *in, unsigned char *out,
+                      long length, IDEA_KEY_SCHEDULE *ks, unsigned char *iv,
+                      int enc);
+void idea_cfb64_encrypt(const unsigned char *in, unsigned char *out,
+                        long length, IDEA_KEY_SCHEDULE *ks, unsigned char *iv,
+                        int *num, int enc);
+void idea_ofb64_encrypt(const unsigned char *in, unsigned char *out,
+                        long length, IDEA_KEY_SCHEDULE *ks, unsigned char *iv,
+                        int *num);
+void idea_encrypt(unsigned long *in, IDEA_KEY_SCHEDULE *ks);
+#ifdef  __cplusplus
+}
+#endif
+
+#endif

+ 240 - 0
libssh2/openssl/include/openssl/krb5_asn.h

@@ -0,0 +1,240 @@
+/* krb5_asn.h */
+/*
+ * Written by Vern Staats <staatsvr@asc.hpc.mil> for the OpenSSL project, **
+ * using ocsp/{*.h,*asn*.c} as a starting point
+ */
+
+/* ====================================================================
+ * Copyright (c) 1998-2000 The OpenSSL 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. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    openssl-core@openssl.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED 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 OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS 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.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com).  This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+
+#ifndef HEADER_KRB5_ASN_H
+# define HEADER_KRB5_ASN_H
+
+/*
+ * #include <krb5.h>
+ */
+# include <openssl/safestack.h>
+
+#ifdef  __cplusplus
+extern "C" {
+#endif
+
+/*
+ * ASN.1 from Kerberos RFC 1510
+ */
+
+/*-     EncryptedData ::=   SEQUENCE {
+ *              etype[0]                      INTEGER, -- EncryptionType
+ *              kvno[1]                       INTEGER OPTIONAL,
+ *              cipher[2]                     OCTET STRING -- ciphertext
+ *      }
+ */
+typedef struct krb5_encdata_st {
+    ASN1_INTEGER *etype;
+    ASN1_INTEGER *kvno;
+    ASN1_OCTET_STRING *cipher;
+} KRB5_ENCDATA;
+
+DECLARE_STACK_OF(KRB5_ENCDATA)
+
+/*-     PrincipalName ::=   SEQUENCE {
+ *              name-type[0]                  INTEGER,
+ *              name-string[1]                SEQUENCE OF GeneralString
+ *      }
+ */
+typedef struct krb5_princname_st {
+    ASN1_INTEGER *nametype;
+    STACK_OF(ASN1_GENERALSTRING) *namestring;
+} KRB5_PRINCNAME;
+
+DECLARE_STACK_OF(KRB5_PRINCNAME)
+
+/*-     Ticket ::=      [APPLICATION 1] SEQUENCE {
+ *              tkt-vno[0]                    INTEGER,
+ *              realm[1]                      Realm,
+ *              sname[2]                      PrincipalName,
+ *              enc-part[3]                   EncryptedData
+ *      }
+ */
+typedef struct krb5_tktbody_st {
+    ASN1_INTEGER *tktvno;
+    ASN1_GENERALSTRING *realm;
+    KRB5_PRINCNAME *sname;
+    KRB5_ENCDATA *encdata;
+} KRB5_TKTBODY;
+
+typedef STACK_OF(KRB5_TKTBODY) KRB5_TICKET;
+DECLARE_STACK_OF(KRB5_TKTBODY)
+
+/*-     AP-REQ ::=      [APPLICATION 14] SEQUENCE {
+ *              pvno[0]                       INTEGER,
+ *              msg-type[1]                   INTEGER,
+ *              ap-options[2]                 APOptions,
+ *              ticket[3]                     Ticket,
+ *              authenticator[4]              EncryptedData
+ *      }
+ *
+ *      APOptions ::=   BIT STRING {
+ *              reserved(0), use-session-key(1), mutual-required(2) }
+ */
+typedef struct krb5_ap_req_st {
+    ASN1_INTEGER *pvno;
+    ASN1_INTEGER *msgtype;
+    ASN1_BIT_STRING *apoptions;
+    KRB5_TICKET *ticket;
+    KRB5_ENCDATA *authenticator;
+} KRB5_APREQBODY;
+
+typedef STACK_OF(KRB5_APREQBODY) KRB5_APREQ;
+DECLARE_STACK_OF(KRB5_APREQBODY)
+
+/*      Authenticator Stuff     */
+
+/*-     Checksum ::=   SEQUENCE {
+ *              cksumtype[0]                  INTEGER,
+ *              checksum[1]                   OCTET STRING
+ *      }
+ */
+typedef struct krb5_checksum_st {
+    ASN1_INTEGER *ctype;
+    ASN1_OCTET_STRING *checksum;
+} KRB5_CHECKSUM;
+
+DECLARE_STACK_OF(KRB5_CHECKSUM)
+
+/*-     EncryptionKey ::=   SEQUENCE {
+ *              keytype[0]                    INTEGER,
+ *              keyvalue[1]                   OCTET STRING
+ *      }
+ */
+typedef struct krb5_encryptionkey_st {
+    ASN1_INTEGER *ktype;
+    ASN1_OCTET_STRING *keyvalue;
+} KRB5_ENCKEY;
+
+DECLARE_STACK_OF(KRB5_ENCKEY)
+
+/*-     AuthorizationData ::=   SEQUENCE OF SEQUENCE {
+ *              ad-type[0]                    INTEGER,
+ *              ad-data[1]                    OCTET STRING
+ *      }
+ */
+typedef struct krb5_authorization_st {
+    ASN1_INTEGER *adtype;
+    ASN1_OCTET_STRING *addata;
+} KRB5_AUTHDATA;
+
+DECLARE_STACK_OF(KRB5_AUTHDATA)
+
+/*-     -- Unencrypted authenticator
+ *      Authenticator ::=    [APPLICATION 2] SEQUENCE    {
+ *              authenticator-vno[0]          INTEGER,
+ *              crealm[1]                     Realm,
+ *              cname[2]                      PrincipalName,
+ *              cksum[3]                      Checksum OPTIONAL,
+ *              cusec[4]                      INTEGER,
+ *              ctime[5]                      KerberosTime,
+ *              subkey[6]                     EncryptionKey OPTIONAL,
+ *              seq-number[7]                 INTEGER OPTIONAL,
+ *              authorization-data[8]         AuthorizationData OPTIONAL
+ *      }
+ */
+typedef struct krb5_authenticator_st {
+    ASN1_INTEGER *avno;
+    ASN1_GENERALSTRING *crealm;
+    KRB5_PRINCNAME *cname;
+    KRB5_CHECKSUM *cksum;
+    ASN1_INTEGER *cusec;
+    ASN1_GENERALIZEDTIME *ctime;
+    KRB5_ENCKEY *subkey;
+    ASN1_INTEGER *seqnum;
+    KRB5_AUTHDATA *authorization;
+} KRB5_AUTHENTBODY;
+
+typedef STACK_OF(KRB5_AUTHENTBODY) KRB5_AUTHENT;
+DECLARE_STACK_OF(KRB5_AUTHENTBODY)
+
+/*-  DECLARE_ASN1_FUNCTIONS(type) = DECLARE_ASN1_FUNCTIONS_name(type, type) =
+ *      type *name##_new(void);
+ *      void name##_free(type *a);
+ *      DECLARE_ASN1_ENCODE_FUNCTIONS(type, name, name) =
+ *       DECLARE_ASN1_ENCODE_FUNCTIONS(type, itname, name) =
+ *        type *d2i_##name(type **a, const unsigned char **in, long len);
+ *        int i2d_##name(type *a, unsigned char **out);
+ *        DECLARE_ASN1_ITEM(itname) = OPENSSL_EXTERN const ASN1_ITEM itname##_it
+ */
+
+DECLARE_ASN1_FUNCTIONS(KRB5_ENCDATA)
+DECLARE_ASN1_FUNCTIONS(KRB5_PRINCNAME)
+DECLARE_ASN1_FUNCTIONS(KRB5_TKTBODY)
+DECLARE_ASN1_FUNCTIONS(KRB5_APREQBODY)
+DECLARE_ASN1_FUNCTIONS(KRB5_TICKET)
+DECLARE_ASN1_FUNCTIONS(KRB5_APREQ)
+
+DECLARE_ASN1_FUNCTIONS(KRB5_CHECKSUM)
+DECLARE_ASN1_FUNCTIONS(KRB5_ENCKEY)
+DECLARE_ASN1_FUNCTIONS(KRB5_AUTHDATA)
+DECLARE_ASN1_FUNCTIONS(KRB5_AUTHENTBODY)
+DECLARE_ASN1_FUNCTIONS(KRB5_AUTHENT)
+
+/* BEGIN ERROR CODES */
+/*
+ * The following lines are auto generated by the script mkerr.pl. Any changes
+ * made after this point may be overwritten when the script is next run.
+ */
+
+#ifdef  __cplusplus
+}
+#endif
+#endif

+ 197 - 0
libssh2/openssl/include/openssl/kssl.h

@@ -0,0 +1,197 @@
+/* ssl/kssl.h */
+/*
+ * Written by Vern Staats <staatsvr@asc.hpc.mil> for the OpenSSL project
+ * 2000. project 2000.
+ */
+/* ====================================================================
+ * Copyright (c) 2000 The OpenSSL 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. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    licensing@OpenSSL.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED 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 OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS 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.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com).  This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+
+/*
+ **      19990701        VRS     Started.
+ */
+
+#ifndef KSSL_H
+# define KSSL_H
+
+# include <openssl/opensslconf.h>
+
+# ifndef OPENSSL_NO_KRB5
+
+#  include <stdio.h>
+#  include <ctype.h>
+#  include <krb5.h>
+#  ifdef OPENSSL_SYS_WIN32
+/*
+ * These can sometimes get redefined indirectly by krb5 header files after
+ * they get undefed in ossl_typ.h
+ */
+#   undef X509_NAME
+#   undef X509_EXTENSIONS
+#   undef OCSP_REQUEST
+#   undef OCSP_RESPONSE
+#  endif
+
+#ifdef  __cplusplus
+extern "C" {
+#endif
+
+/*
+ *      Depending on which KRB5 implementation used, some types from
+ *      the other may be missing.  Resolve that here and now
+ */
+#  ifdef KRB5_HEIMDAL
+typedef unsigned char krb5_octet;
+#   define FAR
+#  else
+
+#   ifndef FAR
+#    define FAR
+#   endif
+
+#  endif
+
+/*-
+ *      Uncomment this to debug kssl problems or
+ *      to trace usage of the Kerberos session key
+ *
+ *      #define         KSSL_DEBUG
+ */
+
+#  ifndef KRB5SVC
+#   define KRB5SVC "host"
+#  endif
+
+#  ifndef KRB5KEYTAB
+#   define KRB5KEYTAB      "/etc/krb5.keytab"
+#  endif
+
+#  ifndef KRB5SENDAUTH
+#   define KRB5SENDAUTH    1
+#  endif
+
+#  ifndef KRB5CHECKAUTH
+#   define KRB5CHECKAUTH   1
+#  endif
+
+#  ifndef KSSL_CLOCKSKEW
+#   define KSSL_CLOCKSKEW  300;
+#  endif
+
+#  define KSSL_ERR_MAX    255
+typedef struct kssl_err_st {
+    int reason;
+    char text[KSSL_ERR_MAX + 1];
+} KSSL_ERR;
+
+/*-     Context for passing
+ *              (1) Kerberos session key to SSL, and
+ *              (2)     Config data between application and SSL lib
+ */
+typedef struct kssl_ctx_st {
+    /*      used by:    disposition:            */
+    char *service_name;         /* C,S default ok (kssl) */
+    char *service_host;         /* C input, REQUIRED */
+    char *client_princ;         /* S output from krb5 ticket */
+    char *keytab_file;          /* S NULL (/etc/krb5.keytab) */
+    char *cred_cache;           /* C NULL (default) */
+    krb5_enctype enctype;
+    int length;
+    krb5_octet FAR *key;
+} KSSL_CTX;
+
+#  define KSSL_CLIENT     1
+#  define KSSL_SERVER     2
+#  define KSSL_SERVICE    3
+#  define KSSL_KEYTAB     4
+
+#  define KSSL_CTX_OK     0
+#  define KSSL_CTX_ERR    1
+#  define KSSL_NOMEM      2
+
+/* Public (for use by applications that use OpenSSL with Kerberos 5 support */
+krb5_error_code kssl_ctx_setstring(KSSL_CTX *kssl_ctx, int which, char *text);
+KSSL_CTX *kssl_ctx_new(void);
+KSSL_CTX *kssl_ctx_free(KSSL_CTX *kssl_ctx);
+void kssl_ctx_show(KSSL_CTX *kssl_ctx);
+krb5_error_code kssl_ctx_setprinc(KSSL_CTX *kssl_ctx, int which,
+                                  krb5_data *realm, krb5_data *entity,
+                                  int nentities);
+krb5_error_code kssl_cget_tkt(KSSL_CTX *kssl_ctx, krb5_data **enc_tktp,
+                              krb5_data *authenp, KSSL_ERR *kssl_err);
+krb5_error_code kssl_sget_tkt(KSSL_CTX *kssl_ctx, krb5_data *indata,
+                              krb5_ticket_times *ttimes, KSSL_ERR *kssl_err);
+krb5_error_code kssl_ctx_setkey(KSSL_CTX *kssl_ctx, krb5_keyblock *session);
+void kssl_err_set(KSSL_ERR *kssl_err, int reason, char *text);
+void kssl_krb5_free_data_contents(krb5_context context, krb5_data *data);
+krb5_error_code kssl_build_principal_2(krb5_context context,
+                                       krb5_principal *princ, int rlen,
+                                       const char *realm, int slen,
+                                       const char *svc, int hlen,
+                                       const char *host);
+krb5_error_code kssl_validate_times(krb5_timestamp atime,
+                                    krb5_ticket_times *ttimes);
+krb5_error_code kssl_check_authent(KSSL_CTX *kssl_ctx, krb5_data *authentp,
+                                   krb5_timestamp *atimep,
+                                   KSSL_ERR *kssl_err);
+unsigned char *kssl_skip_confound(krb5_enctype enctype, unsigned char *authn);
+
+void SSL_set0_kssl_ctx(SSL *s, KSSL_CTX *kctx);
+KSSL_CTX *SSL_get0_kssl_ctx(SSL *s);
+char *kssl_ctx_get0_client_princ(KSSL_CTX *kctx);
+
+#ifdef  __cplusplus
+}
+#endif
+# endif                         /* OPENSSL_NO_KRB5 */
+#endif                          /* KSSL_H */

+ 240 - 0
libssh2/openssl/include/openssl/lhash.h

@@ -0,0 +1,240 @@
+/* crypto/lhash/lhash.h */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * 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 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. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    "This product includes cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``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 AUTHOR OR CONTRIBUTORS 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.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+/*
+ * Header for dynamic hash table routines Author - Eric Young
+ */
+
+#ifndef HEADER_LHASH_H
+# define HEADER_LHASH_H
+
+# include <openssl/e_os2.h>
+# ifndef OPENSSL_NO_FP_API
+#  include <stdio.h>
+# endif
+
+# ifndef OPENSSL_NO_BIO
+#  include <openssl/bio.h>
+# endif
+
+#ifdef  __cplusplus
+extern "C" {
+#endif
+
+typedef struct lhash_node_st {
+    void *data;
+    struct lhash_node_st *next;
+# ifndef OPENSSL_NO_HASH_COMP
+    unsigned long hash;
+# endif
+} LHASH_NODE;
+
+typedef int (*LHASH_COMP_FN_TYPE) (const void *, const void *);
+typedef unsigned long (*LHASH_HASH_FN_TYPE) (const void *);
+typedef void (*LHASH_DOALL_FN_TYPE) (void *);
+typedef void (*LHASH_DOALL_ARG_FN_TYPE) (void *, void *);
+
+/*
+ * Macros for declaring and implementing type-safe wrappers for LHASH
+ * callbacks. This way, callbacks can be provided to LHASH structures without
+ * function pointer casting and the macro-defined callbacks provide
+ * per-variable casting before deferring to the underlying type-specific
+ * callbacks. NB: It is possible to place a "static" in front of both the
+ * DECLARE and IMPLEMENT macros if the functions are strictly internal.
+ */
+
+/* First: "hash" functions */
+# define DECLARE_LHASH_HASH_FN(name, o_type) \
+        unsigned long name##_LHASH_HASH(const void *);
+# define IMPLEMENT_LHASH_HASH_FN(name, o_type) \
+        unsigned long name##_LHASH_HASH(const void *arg) { \
+                const o_type *a = arg; \
+                return name##_hash(a); }
+# define LHASH_HASH_FN(name) name##_LHASH_HASH
+
+/* Second: "compare" functions */
+# define DECLARE_LHASH_COMP_FN(name, o_type) \
+        int name##_LHASH_COMP(const void *, const void *);
+# define IMPLEMENT_LHASH_COMP_FN(name, o_type) \
+        int name##_LHASH_COMP(const void *arg1, const void *arg2) { \
+                const o_type *a = arg1;             \
+                const o_type *b = arg2; \
+                return name##_cmp(a,b); }
+# define LHASH_COMP_FN(name) name##_LHASH_COMP
+
+/* Third: "doall" functions */
+# define DECLARE_LHASH_DOALL_FN(name, o_type) \
+        void name##_LHASH_DOALL(void *);
+# define IMPLEMENT_LHASH_DOALL_FN(name, o_type) \
+        void name##_LHASH_DOALL(void *arg) { \
+                o_type *a = arg; \
+                name##_doall(a); }
+# define LHASH_DOALL_FN(name) name##_LHASH_DOALL
+
+/* Fourth: "doall_arg" functions */
+# define DECLARE_LHASH_DOALL_ARG_FN(name, o_type, a_type) \
+        void name##_LHASH_DOALL_ARG(void *, void *);
+# define IMPLEMENT_LHASH_DOALL_ARG_FN(name, o_type, a_type) \
+        void name##_LHASH_DOALL_ARG(void *arg1, void *arg2) { \
+                o_type *a = arg1; \
+                a_type *b = arg2; \
+                name##_doall_arg(a, b); }
+# define LHASH_DOALL_ARG_FN(name) name##_LHASH_DOALL_ARG
+
+typedef struct lhash_st {
+    LHASH_NODE **b;
+    LHASH_COMP_FN_TYPE comp;
+    LHASH_HASH_FN_TYPE hash;
+    unsigned int num_nodes;
+    unsigned int num_alloc_nodes;
+    unsigned int p;
+    unsigned int pmax;
+    unsigned long up_load;      /* load times 256 */
+    unsigned long down_load;    /* load times 256 */
+    unsigned long num_items;
+    unsigned long num_expands;
+    unsigned long num_expand_reallocs;
+    unsigned long num_contracts;
+    unsigned long num_contract_reallocs;
+    unsigned long num_hash_calls;
+    unsigned long num_comp_calls;
+    unsigned long num_insert;
+    unsigned long num_replace;
+    unsigned long num_delete;
+    unsigned long num_no_delete;
+    unsigned long num_retrieve;
+    unsigned long num_retrieve_miss;
+    unsigned long num_hash_comps;
+    int error;
+} _LHASH;                       /* Do not use _LHASH directly, use LHASH_OF
+                                 * and friends */
+
+# define LH_LOAD_MULT    256
+
+/*
+ * Indicates a malloc() error in the last call, this is only bad in
+ * lh_insert().
+ */
+# define lh_error(lh)    ((lh)->error)
+
+_LHASH *lh_new(LHASH_HASH_FN_TYPE h, LHASH_COMP_FN_TYPE c);
+void lh_free(_LHASH *lh);
+void *lh_insert(_LHASH *lh, void *data);
+void *lh_delete(_LHASH *lh, const void *data);
+void *lh_retrieve(_LHASH *lh, const void *data);
+void lh_doall(_LHASH *lh, LHASH_DOALL_FN_TYPE func);
+void lh_doall_arg(_LHASH *lh, LHASH_DOALL_ARG_FN_TYPE func, void *arg);
+unsigned long lh_strhash(const char *c);
+unsigned long lh_num_items(const _LHASH *lh);
+
+# ifndef OPENSSL_NO_FP_API
+void lh_stats(const _LHASH *lh, FILE *out);
+void lh_node_stats(const _LHASH *lh, FILE *out);
+void lh_node_usage_stats(const _LHASH *lh, FILE *out);
+# endif
+
+# ifndef OPENSSL_NO_BIO
+void lh_stats_bio(const _LHASH *lh, BIO *out);
+void lh_node_stats_bio(const _LHASH *lh, BIO *out);
+void lh_node_usage_stats_bio(const _LHASH *lh, BIO *out);
+# endif
+
+/* Type checking... */
+
+# define LHASH_OF(type) struct lhash_st_##type
+
+# define DECLARE_LHASH_OF(type) LHASH_OF(type) { int dummy; }
+
+# define CHECKED_LHASH_OF(type,lh) \
+  ((_LHASH *)CHECKED_PTR_OF(LHASH_OF(type),lh))
+
+/* Define wrapper functions. */
+# define LHM_lh_new(type, name) \
+  ((LHASH_OF(type) *)lh_new(LHASH_HASH_FN(name), LHASH_COMP_FN(name)))
+# define LHM_lh_error(type, lh) \
+  lh_error(CHECKED_LHASH_OF(type,lh))
+# define LHM_lh_insert(type, lh, inst) \
+  ((type *)lh_insert(CHECKED_LHASH_OF(type, lh), \
+                     CHECKED_PTR_OF(type, inst)))
+# define LHM_lh_retrieve(type, lh, inst) \
+  ((type *)lh_retrieve(CHECKED_LHASH_OF(type, lh), \
+                       CHECKED_PTR_OF(type, inst)))
+# define LHM_lh_delete(type, lh, inst) \
+  ((type *)lh_delete(CHECKED_LHASH_OF(type, lh),                        \
+                     CHECKED_PTR_OF(type, inst)))
+# define LHM_lh_doall(type, lh,fn) lh_doall(CHECKED_LHASH_OF(type, lh), fn)
+# define LHM_lh_doall_arg(type, lh, fn, arg_type, arg) \
+  lh_doall_arg(CHECKED_LHASH_OF(type, lh), fn, CHECKED_PTR_OF(arg_type, arg))
+# define LHM_lh_num_items(type, lh) lh_num_items(CHECKED_LHASH_OF(type, lh))
+# define LHM_lh_down_load(type, lh) (CHECKED_LHASH_OF(type, lh)->down_load)
+# define LHM_lh_node_stats_bio(type, lh, out) \
+  lh_node_stats_bio(CHECKED_LHASH_OF(type, lh), out)
+# define LHM_lh_node_usage_stats_bio(type, lh, out) \
+  lh_node_usage_stats_bio(CHECKED_LHASH_OF(type, lh), out)
+# define LHM_lh_stats_bio(type, lh, out) \
+  lh_stats_bio(CHECKED_LHASH_OF(type, lh), out)
+# define LHM_lh_free(type, lh) lh_free(CHECKED_LHASH_OF(type, lh))
+
+DECLARE_LHASH_OF(OPENSSL_STRING);
+DECLARE_LHASH_OF(OPENSSL_CSTRING);
+
+#ifdef  __cplusplus
+}
+#endif
+
+#endif

+ 119 - 0
libssh2/openssl/include/openssl/md4.h

@@ -0,0 +1,119 @@
+/* crypto/md4/md4.h */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * 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 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. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    "This product includes cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``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 AUTHOR OR CONTRIBUTORS 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.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+#ifndef HEADER_MD4_H
+# define HEADER_MD4_H
+
+# include <openssl/e_os2.h>
+# include <stddef.h>
+
+#ifdef  __cplusplus
+extern "C" {
+#endif
+
+# ifdef OPENSSL_NO_MD4
+#  error MD4 is disabled.
+# endif
+
+/*-
+ * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+ * ! MD4_LONG has to be at least 32 bits wide. If it's wider, then !
+ * ! MD4_LONG_LOG2 has to be defined along.                        !
+ * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+ */
+
+# if defined(__LP32__)
+#  define MD4_LONG unsigned long
+# elif defined(OPENSSL_SYS_CRAY) || defined(__ILP64__)
+#  define MD4_LONG unsigned long
+#  define MD4_LONG_LOG2 3
+/*
+ * _CRAY note. I could declare short, but I have no idea what impact
+ * does it have on performance on none-T3E machines. I could declare
+ * int, but at least on C90 sizeof(int) can be chosen at compile time.
+ * So I've chosen long...
+ *                                      <appro@fy.chalmers.se>
+ */
+# else
+#  define MD4_LONG unsigned int
+# endif
+
+# define MD4_CBLOCK      64
+# define MD4_LBLOCK      (MD4_CBLOCK/4)
+# define MD4_DIGEST_LENGTH 16
+
+typedef struct MD4state_st {
+    MD4_LONG A, B, C, D;
+    MD4_LONG Nl, Nh;
+    MD4_LONG data[MD4_LBLOCK];
+    unsigned int num;
+} MD4_CTX;
+
+# ifdef OPENSSL_FIPS
+int private_MD4_Init(MD4_CTX *c);
+# endif
+int MD4_Init(MD4_CTX *c);
+int MD4_Update(MD4_CTX *c, const void *data, size_t len);
+int MD4_Final(unsigned char *md, MD4_CTX *c);
+unsigned char *MD4(const unsigned char *d, size_t n, unsigned char *md);
+void MD4_Transform(MD4_CTX *c, const unsigned char *b);
+#ifdef  __cplusplus
+}
+#endif
+
+#endif

+ 119 - 0
libssh2/openssl/include/openssl/md5.h

@@ -0,0 +1,119 @@
+/* crypto/md5/md5.h */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * 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 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. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    "This product includes cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``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 AUTHOR OR CONTRIBUTORS 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.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+#ifndef HEADER_MD5_H
+# define HEADER_MD5_H
+
+# include <openssl/e_os2.h>
+# include <stddef.h>
+
+#ifdef  __cplusplus
+extern "C" {
+#endif
+
+# ifdef OPENSSL_NO_MD5
+#  error MD5 is disabled.
+# endif
+
+/*
+ * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+ * ! MD5_LONG has to be at least 32 bits wide. If it's wider, then !
+ * ! MD5_LONG_LOG2 has to be defined along.                        !
+ * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+ */
+
+# if defined(__LP32__)
+#  define MD5_LONG unsigned long
+# elif defined(OPENSSL_SYS_CRAY) || defined(__ILP64__)
+#  define MD5_LONG unsigned long
+#  define MD5_LONG_LOG2 3
+/*
+ * _CRAY note. I could declare short, but I have no idea what impact
+ * does it have on performance on none-T3E machines. I could declare
+ * int, but at least on C90 sizeof(int) can be chosen at compile time.
+ * So I've chosen long...
+ *                                      <appro@fy.chalmers.se>
+ */
+# else
+#  define MD5_LONG unsigned int
+# endif
+
+# define MD5_CBLOCK      64
+# define MD5_LBLOCK      (MD5_CBLOCK/4)
+# define MD5_DIGEST_LENGTH 16
+
+typedef struct MD5state_st {
+    MD5_LONG A, B, C, D;
+    MD5_LONG Nl, Nh;
+    MD5_LONG data[MD5_LBLOCK];
+    unsigned int num;
+} MD5_CTX;
+
+# ifdef OPENSSL_FIPS
+int private_MD5_Init(MD5_CTX *c);
+# endif
+int MD5_Init(MD5_CTX *c);
+int MD5_Update(MD5_CTX *c, const void *data, size_t len);
+int MD5_Final(unsigned char *md, MD5_CTX *c);
+unsigned char *MD5(const unsigned char *d, size_t n, unsigned char *md);
+void MD5_Transform(MD5_CTX *c, const unsigned char *b);
+#ifdef  __cplusplus
+}
+#endif
+
+#endif

+ 94 - 0
libssh2/openssl/include/openssl/mdc2.h

@@ -0,0 +1,94 @@
+/* crypto/mdc2/mdc2.h */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * 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 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. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    "This product includes cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``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 AUTHOR OR CONTRIBUTORS 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.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+#ifndef HEADER_MDC2_H
+# define HEADER_MDC2_H
+
+# include <openssl/des.h>
+
+#ifdef  __cplusplus
+extern "C" {
+#endif
+
+# ifdef OPENSSL_NO_MDC2
+#  error MDC2 is disabled.
+# endif
+
+# define MDC2_BLOCK              8
+# define MDC2_DIGEST_LENGTH      16
+
+typedef struct mdc2_ctx_st {
+    unsigned int num;
+    unsigned char data[MDC2_BLOCK];
+    DES_cblock h, hh;
+    int pad_type;               /* either 1 or 2, default 1 */
+} MDC2_CTX;
+
+# ifdef OPENSSL_FIPS
+int private_MDC2_Init(MDC2_CTX *c);
+# endif
+int MDC2_Init(MDC2_CTX *c);
+int MDC2_Update(MDC2_CTX *c, const unsigned char *data, size_t len);
+int MDC2_Final(unsigned char *md, MDC2_CTX *c);
+unsigned char *MDC2(const unsigned char *d, size_t n, unsigned char *md);
+
+#ifdef  __cplusplus
+}
+#endif
+
+#endif

+ 163 - 0
libssh2/openssl/include/openssl/modes.h

@@ -0,0 +1,163 @@
+/* ====================================================================
+ * Copyright (c) 2008 The OpenSSL Project. All rights reserved.
+ *
+ * Rights for redistribution and usage in source and binary
+ * forms are granted according to the OpenSSL license.
+ */
+
+#include <stddef.h>
+
+#ifdef  __cplusplus
+extern "C" {
+#endif
+typedef void (*block128_f) (const unsigned char in[16],
+                            unsigned char out[16], const void *key);
+
+typedef void (*cbc128_f) (const unsigned char *in, unsigned char *out,
+                          size_t len, const void *key,
+                          unsigned char ivec[16], int enc);
+
+typedef void (*ctr128_f) (const unsigned char *in, unsigned char *out,
+                          size_t blocks, const void *key,
+                          const unsigned char ivec[16]);
+
+typedef void (*ccm128_f) (const unsigned char *in, unsigned char *out,
+                          size_t blocks, const void *key,
+                          const unsigned char ivec[16],
+                          unsigned char cmac[16]);
+
+void CRYPTO_cbc128_encrypt(const unsigned char *in, unsigned char *out,
+                           size_t len, const void *key,
+                           unsigned char ivec[16], block128_f block);
+void CRYPTO_cbc128_decrypt(const unsigned char *in, unsigned char *out,
+                           size_t len, const void *key,
+                           unsigned char ivec[16], block128_f block);
+
+void CRYPTO_ctr128_encrypt(const unsigned char *in, unsigned char *out,
+                           size_t len, const void *key,
+                           unsigned char ivec[16],
+                           unsigned char ecount_buf[16], unsigned int *num,
+                           block128_f block);
+
+void CRYPTO_ctr128_encrypt_ctr32(const unsigned char *in, unsigned char *out,
+                                 size_t len, const void *key,
+                                 unsigned char ivec[16],
+                                 unsigned char ecount_buf[16],
+                                 unsigned int *num, ctr128_f ctr);
+
+void CRYPTO_ofb128_encrypt(const unsigned char *in, unsigned char *out,
+                           size_t len, const void *key,
+                           unsigned char ivec[16], int *num,
+                           block128_f block);
+
+void CRYPTO_cfb128_encrypt(const unsigned char *in, unsigned char *out,
+                           size_t len, const void *key,
+                           unsigned char ivec[16], int *num,
+                           int enc, block128_f block);
+void CRYPTO_cfb128_8_encrypt(const unsigned char *in, unsigned char *out,
+                             size_t length, const void *key,
+                             unsigned char ivec[16], int *num,
+                             int enc, block128_f block);
+void CRYPTO_cfb128_1_encrypt(const unsigned char *in, unsigned char *out,
+                             size_t bits, const void *key,
+                             unsigned char ivec[16], int *num,
+                             int enc, block128_f block);
+
+size_t CRYPTO_cts128_encrypt_block(const unsigned char *in,
+                                   unsigned char *out, size_t len,
+                                   const void *key, unsigned char ivec[16],
+                                   block128_f block);
+size_t CRYPTO_cts128_encrypt(const unsigned char *in, unsigned char *out,
+                             size_t len, const void *key,
+                             unsigned char ivec[16], cbc128_f cbc);
+size_t CRYPTO_cts128_decrypt_block(const unsigned char *in,
+                                   unsigned char *out, size_t len,
+                                   const void *key, unsigned char ivec[16],
+                                   block128_f block);
+size_t CRYPTO_cts128_decrypt(const unsigned char *in, unsigned char *out,
+                             size_t len, const void *key,
+                             unsigned char ivec[16], cbc128_f cbc);
+
+size_t CRYPTO_nistcts128_encrypt_block(const unsigned char *in,
+                                       unsigned char *out, size_t len,
+                                       const void *key,
+                                       unsigned char ivec[16],
+                                       block128_f block);
+size_t CRYPTO_nistcts128_encrypt(const unsigned char *in, unsigned char *out,
+                                 size_t len, const void *key,
+                                 unsigned char ivec[16], cbc128_f cbc);
+size_t CRYPTO_nistcts128_decrypt_block(const unsigned char *in,
+                                       unsigned char *out, size_t len,
+                                       const void *key,
+                                       unsigned char ivec[16],
+                                       block128_f block);
+size_t CRYPTO_nistcts128_decrypt(const unsigned char *in, unsigned char *out,
+                                 size_t len, const void *key,
+                                 unsigned char ivec[16], cbc128_f cbc);
+
+typedef struct gcm128_context GCM128_CONTEXT;
+
+GCM128_CONTEXT *CRYPTO_gcm128_new(void *key, block128_f block);
+void CRYPTO_gcm128_init(GCM128_CONTEXT *ctx, void *key, block128_f block);
+void CRYPTO_gcm128_setiv(GCM128_CONTEXT *ctx, const unsigned char *iv,
+                         size_t len);
+int CRYPTO_gcm128_aad(GCM128_CONTEXT *ctx, const unsigned char *aad,
+                      size_t len);
+int CRYPTO_gcm128_encrypt(GCM128_CONTEXT *ctx,
+                          const unsigned char *in, unsigned char *out,
+                          size_t len);
+int CRYPTO_gcm128_decrypt(GCM128_CONTEXT *ctx,
+                          const unsigned char *in, unsigned char *out,
+                          size_t len);
+int CRYPTO_gcm128_encrypt_ctr32(GCM128_CONTEXT *ctx,
+                                const unsigned char *in, unsigned char *out,
+                                size_t len, ctr128_f stream);
+int CRYPTO_gcm128_decrypt_ctr32(GCM128_CONTEXT *ctx,
+                                const unsigned char *in, unsigned char *out,
+                                size_t len, ctr128_f stream);
+int CRYPTO_gcm128_finish(GCM128_CONTEXT *ctx, const unsigned char *tag,
+                         size_t len);
+void CRYPTO_gcm128_tag(GCM128_CONTEXT *ctx, unsigned char *tag, size_t len);
+void CRYPTO_gcm128_release(GCM128_CONTEXT *ctx);
+
+typedef struct ccm128_context CCM128_CONTEXT;
+
+void CRYPTO_ccm128_init(CCM128_CONTEXT *ctx,
+                        unsigned int M, unsigned int L, void *key,
+                        block128_f block);
+int CRYPTO_ccm128_setiv(CCM128_CONTEXT *ctx, const unsigned char *nonce,
+                        size_t nlen, size_t mlen);
+void CRYPTO_ccm128_aad(CCM128_CONTEXT *ctx, const unsigned char *aad,
+                       size_t alen);
+int CRYPTO_ccm128_encrypt(CCM128_CONTEXT *ctx, const unsigned char *inp,
+                          unsigned char *out, size_t len);
+int CRYPTO_ccm128_decrypt(CCM128_CONTEXT *ctx, const unsigned char *inp,
+                          unsigned char *out, size_t len);
+int CRYPTO_ccm128_encrypt_ccm64(CCM128_CONTEXT *ctx, const unsigned char *inp,
+                                unsigned char *out, size_t len,
+                                ccm128_f stream);
+int CRYPTO_ccm128_decrypt_ccm64(CCM128_CONTEXT *ctx, const unsigned char *inp,
+                                unsigned char *out, size_t len,
+                                ccm128_f stream);
+size_t CRYPTO_ccm128_tag(CCM128_CONTEXT *ctx, unsigned char *tag, size_t len);
+
+typedef struct xts128_context XTS128_CONTEXT;
+
+int CRYPTO_xts128_encrypt(const XTS128_CONTEXT *ctx,
+                          const unsigned char iv[16],
+                          const unsigned char *inp, unsigned char *out,
+                          size_t len, int enc);
+
+size_t CRYPTO_128_wrap(void *key, const unsigned char *iv,
+                       unsigned char *out,
+                       const unsigned char *in, size_t inlen,
+                       block128_f block);
+
+size_t CRYPTO_128_unwrap(void *key, const unsigned char *iv,
+                         unsigned char *out,
+                         const unsigned char *in, size_t inlen,
+                         block128_f block);
+
+#ifdef  __cplusplus
+}
+#endif

+ 4194 - 0
libssh2/openssl/include/openssl/obj_mac.h

@@ -0,0 +1,4194 @@
+/* crypto/objects/obj_mac.h */
+
+/*
+ * THIS FILE IS GENERATED FROM objects.txt by objects.pl via the following
+ * command: perl objects.pl objects.txt obj_mac.num obj_mac.h
+ */
+
+/* Copyright (C) 1995-1997 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * 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 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. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    "This product includes cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``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 AUTHOR OR CONTRIBUTORS 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.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+#define SN_undef                        "UNDEF"
+#define LN_undef                        "undefined"
+#define NID_undef                       0
+#define OBJ_undef                       0L
+
+#define SN_itu_t                "ITU-T"
+#define LN_itu_t                "itu-t"
+#define NID_itu_t               645
+#define OBJ_itu_t               0L
+
+#define NID_ccitt               404
+#define OBJ_ccitt               OBJ_itu_t
+
+#define SN_iso          "ISO"
+#define LN_iso          "iso"
+#define NID_iso         181
+#define OBJ_iso         1L
+
+#define SN_joint_iso_itu_t              "JOINT-ISO-ITU-T"
+#define LN_joint_iso_itu_t              "joint-iso-itu-t"
+#define NID_joint_iso_itu_t             646
+#define OBJ_joint_iso_itu_t             2L
+
+#define NID_joint_iso_ccitt             393
+#define OBJ_joint_iso_ccitt             OBJ_joint_iso_itu_t
+
+#define SN_member_body          "member-body"
+#define LN_member_body          "ISO Member Body"
+#define NID_member_body         182
+#define OBJ_member_body         OBJ_iso,2L
+
+#define SN_identified_organization              "identified-organization"
+#define NID_identified_organization             676
+#define OBJ_identified_organization             OBJ_iso,3L
+
+#define SN_hmac_md5             "HMAC-MD5"
+#define LN_hmac_md5             "hmac-md5"
+#define NID_hmac_md5            780
+#define OBJ_hmac_md5            OBJ_identified_organization,6L,1L,5L,5L,8L,1L,1L
+
+#define SN_hmac_sha1            "HMAC-SHA1"
+#define LN_hmac_sha1            "hmac-sha1"
+#define NID_hmac_sha1           781
+#define OBJ_hmac_sha1           OBJ_identified_organization,6L,1L,5L,5L,8L,1L,2L
+
+#define SN_certicom_arc         "certicom-arc"
+#define NID_certicom_arc                677
+#define OBJ_certicom_arc                OBJ_identified_organization,132L
+
+#define SN_international_organizations          "international-organizations"
+#define LN_international_organizations          "International Organizations"
+#define NID_international_organizations         647
+#define OBJ_international_organizations         OBJ_joint_iso_itu_t,23L
+
+#define SN_wap          "wap"
+#define NID_wap         678
+#define OBJ_wap         OBJ_international_organizations,43L
+
+#define SN_wap_wsg              "wap-wsg"
+#define NID_wap_wsg             679
+#define OBJ_wap_wsg             OBJ_wap,1L
+
+#define SN_selected_attribute_types             "selected-attribute-types"
+#define LN_selected_attribute_types             "Selected Attribute Types"
+#define NID_selected_attribute_types            394
+#define OBJ_selected_attribute_types            OBJ_joint_iso_itu_t,5L,1L,5L
+
+#define SN_clearance            "clearance"
+#define NID_clearance           395
+#define OBJ_clearance           OBJ_selected_attribute_types,55L
+
+#define SN_ISO_US               "ISO-US"
+#define LN_ISO_US               "ISO US Member Body"
+#define NID_ISO_US              183
+#define OBJ_ISO_US              OBJ_member_body,840L
+
+#define SN_X9_57                "X9-57"
+#define LN_X9_57                "X9.57"
+#define NID_X9_57               184
+#define OBJ_X9_57               OBJ_ISO_US,10040L
+
+#define SN_X9cm         "X9cm"
+#define LN_X9cm         "X9.57 CM ?"
+#define NID_X9cm                185
+#define OBJ_X9cm                OBJ_X9_57,4L
+
+#define SN_dsa          "DSA"
+#define LN_dsa          "dsaEncryption"
+#define NID_dsa         116
+#define OBJ_dsa         OBJ_X9cm,1L
+
+#define SN_dsaWithSHA1          "DSA-SHA1"
+#define LN_dsaWithSHA1          "dsaWithSHA1"
+#define NID_dsaWithSHA1         113
+#define OBJ_dsaWithSHA1         OBJ_X9cm,3L
+
+#define SN_ansi_X9_62           "ansi-X9-62"
+#define LN_ansi_X9_62           "ANSI X9.62"
+#define NID_ansi_X9_62          405
+#define OBJ_ansi_X9_62          OBJ_ISO_US,10045L
+
+#define OBJ_X9_62_id_fieldType          OBJ_ansi_X9_62,1L
+
+#define SN_X9_62_prime_field            "prime-field"
+#define NID_X9_62_prime_field           406
+#define OBJ_X9_62_prime_field           OBJ_X9_62_id_fieldType,1L
+
+#define SN_X9_62_characteristic_two_field               "characteristic-two-field"
+#define NID_X9_62_characteristic_two_field              407
+#define OBJ_X9_62_characteristic_two_field              OBJ_X9_62_id_fieldType,2L
+
+#define SN_X9_62_id_characteristic_two_basis            "id-characteristic-two-basis"
+#define NID_X9_62_id_characteristic_two_basis           680
+#define OBJ_X9_62_id_characteristic_two_basis           OBJ_X9_62_characteristic_two_field,3L
+
+#define SN_X9_62_onBasis                "onBasis"
+#define NID_X9_62_onBasis               681
+#define OBJ_X9_62_onBasis               OBJ_X9_62_id_characteristic_two_basis,1L
+
+#define SN_X9_62_tpBasis                "tpBasis"
+#define NID_X9_62_tpBasis               682
+#define OBJ_X9_62_tpBasis               OBJ_X9_62_id_characteristic_two_basis,2L
+
+#define SN_X9_62_ppBasis                "ppBasis"
+#define NID_X9_62_ppBasis               683
+#define OBJ_X9_62_ppBasis               OBJ_X9_62_id_characteristic_two_basis,3L
+
+#define OBJ_X9_62_id_publicKeyType              OBJ_ansi_X9_62,2L
+
+#define SN_X9_62_id_ecPublicKey         "id-ecPublicKey"
+#define NID_X9_62_id_ecPublicKey                408
+#define OBJ_X9_62_id_ecPublicKey                OBJ_X9_62_id_publicKeyType,1L
+
+#define OBJ_X9_62_ellipticCurve         OBJ_ansi_X9_62,3L
+
+#define OBJ_X9_62_c_TwoCurve            OBJ_X9_62_ellipticCurve,0L
+
+#define SN_X9_62_c2pnb163v1             "c2pnb163v1"
+#define NID_X9_62_c2pnb163v1            684
+#define OBJ_X9_62_c2pnb163v1            OBJ_X9_62_c_TwoCurve,1L
+
+#define SN_X9_62_c2pnb163v2             "c2pnb163v2"
+#define NID_X9_62_c2pnb163v2            685
+#define OBJ_X9_62_c2pnb163v2            OBJ_X9_62_c_TwoCurve,2L
+
+#define SN_X9_62_c2pnb163v3             "c2pnb163v3"
+#define NID_X9_62_c2pnb163v3            686
+#define OBJ_X9_62_c2pnb163v3            OBJ_X9_62_c_TwoCurve,3L
+
+#define SN_X9_62_c2pnb176v1             "c2pnb176v1"
+#define NID_X9_62_c2pnb176v1            687
+#define OBJ_X9_62_c2pnb176v1            OBJ_X9_62_c_TwoCurve,4L
+
+#define SN_X9_62_c2tnb191v1             "c2tnb191v1"
+#define NID_X9_62_c2tnb191v1            688
+#define OBJ_X9_62_c2tnb191v1            OBJ_X9_62_c_TwoCurve,5L
+
+#define SN_X9_62_c2tnb191v2             "c2tnb191v2"
+#define NID_X9_62_c2tnb191v2            689
+#define OBJ_X9_62_c2tnb191v2            OBJ_X9_62_c_TwoCurve,6L
+
+#define SN_X9_62_c2tnb191v3             "c2tnb191v3"
+#define NID_X9_62_c2tnb191v3            690
+#define OBJ_X9_62_c2tnb191v3            OBJ_X9_62_c_TwoCurve,7L
+
+#define SN_X9_62_c2onb191v4             "c2onb191v4"
+#define NID_X9_62_c2onb191v4            691
+#define OBJ_X9_62_c2onb191v4            OBJ_X9_62_c_TwoCurve,8L
+
+#define SN_X9_62_c2onb191v5             "c2onb191v5"
+#define NID_X9_62_c2onb191v5            692
+#define OBJ_X9_62_c2onb191v5            OBJ_X9_62_c_TwoCurve,9L
+
+#define SN_X9_62_c2pnb208w1             "c2pnb208w1"
+#define NID_X9_62_c2pnb208w1            693
+#define OBJ_X9_62_c2pnb208w1            OBJ_X9_62_c_TwoCurve,10L
+
+#define SN_X9_62_c2tnb239v1             "c2tnb239v1"
+#define NID_X9_62_c2tnb239v1            694
+#define OBJ_X9_62_c2tnb239v1            OBJ_X9_62_c_TwoCurve,11L
+
+#define SN_X9_62_c2tnb239v2             "c2tnb239v2"
+#define NID_X9_62_c2tnb239v2            695
+#define OBJ_X9_62_c2tnb239v2            OBJ_X9_62_c_TwoCurve,12L
+
+#define SN_X9_62_c2tnb239v3             "c2tnb239v3"
+#define NID_X9_62_c2tnb239v3            696
+#define OBJ_X9_62_c2tnb239v3            OBJ_X9_62_c_TwoCurve,13L
+
+#define SN_X9_62_c2onb239v4             "c2onb239v4"
+#define NID_X9_62_c2onb239v4            697
+#define OBJ_X9_62_c2onb239v4            OBJ_X9_62_c_TwoCurve,14L
+
+#define SN_X9_62_c2onb239v5             "c2onb239v5"
+#define NID_X9_62_c2onb239v5            698
+#define OBJ_X9_62_c2onb239v5            OBJ_X9_62_c_TwoCurve,15L
+
+#define SN_X9_62_c2pnb272w1             "c2pnb272w1"
+#define NID_X9_62_c2pnb272w1            699
+#define OBJ_X9_62_c2pnb272w1            OBJ_X9_62_c_TwoCurve,16L
+
+#define SN_X9_62_c2pnb304w1             "c2pnb304w1"
+#define NID_X9_62_c2pnb304w1            700
+#define OBJ_X9_62_c2pnb304w1            OBJ_X9_62_c_TwoCurve,17L
+
+#define SN_X9_62_c2tnb359v1             "c2tnb359v1"
+#define NID_X9_62_c2tnb359v1            701
+#define OBJ_X9_62_c2tnb359v1            OBJ_X9_62_c_TwoCurve,18L
+
+#define SN_X9_62_c2pnb368w1             "c2pnb368w1"
+#define NID_X9_62_c2pnb368w1            702
+#define OBJ_X9_62_c2pnb368w1            OBJ_X9_62_c_TwoCurve,19L
+
+#define SN_X9_62_c2tnb431r1             "c2tnb431r1"
+#define NID_X9_62_c2tnb431r1            703
+#define OBJ_X9_62_c2tnb431r1            OBJ_X9_62_c_TwoCurve,20L
+
+#define OBJ_X9_62_primeCurve            OBJ_X9_62_ellipticCurve,1L
+
+#define SN_X9_62_prime192v1             "prime192v1"
+#define NID_X9_62_prime192v1            409
+#define OBJ_X9_62_prime192v1            OBJ_X9_62_primeCurve,1L
+
+#define SN_X9_62_prime192v2             "prime192v2"
+#define NID_X9_62_prime192v2            410
+#define OBJ_X9_62_prime192v2            OBJ_X9_62_primeCurve,2L
+
+#define SN_X9_62_prime192v3             "prime192v3"
+#define NID_X9_62_prime192v3            411
+#define OBJ_X9_62_prime192v3            OBJ_X9_62_primeCurve,3L
+
+#define SN_X9_62_prime239v1             "prime239v1"
+#define NID_X9_62_prime239v1            412
+#define OBJ_X9_62_prime239v1            OBJ_X9_62_primeCurve,4L
+
+#define SN_X9_62_prime239v2             "prime239v2"
+#define NID_X9_62_prime239v2            413
+#define OBJ_X9_62_prime239v2            OBJ_X9_62_primeCurve,5L
+
+#define SN_X9_62_prime239v3             "prime239v3"
+#define NID_X9_62_prime239v3            414
+#define OBJ_X9_62_prime239v3            OBJ_X9_62_primeCurve,6L
+
+#define SN_X9_62_prime256v1             "prime256v1"
+#define NID_X9_62_prime256v1            415
+#define OBJ_X9_62_prime256v1            OBJ_X9_62_primeCurve,7L
+
+#define OBJ_X9_62_id_ecSigType          OBJ_ansi_X9_62,4L
+
+#define SN_ecdsa_with_SHA1              "ecdsa-with-SHA1"
+#define NID_ecdsa_with_SHA1             416
+#define OBJ_ecdsa_with_SHA1             OBJ_X9_62_id_ecSigType,1L
+
+#define SN_ecdsa_with_Recommended               "ecdsa-with-Recommended"
+#define NID_ecdsa_with_Recommended              791
+#define OBJ_ecdsa_with_Recommended              OBJ_X9_62_id_ecSigType,2L
+
+#define SN_ecdsa_with_Specified         "ecdsa-with-Specified"
+#define NID_ecdsa_with_Specified                792
+#define OBJ_ecdsa_with_Specified                OBJ_X9_62_id_ecSigType,3L
+
+#define SN_ecdsa_with_SHA224            "ecdsa-with-SHA224"
+#define NID_ecdsa_with_SHA224           793
+#define OBJ_ecdsa_with_SHA224           OBJ_ecdsa_with_Specified,1L
+
+#define SN_ecdsa_with_SHA256            "ecdsa-with-SHA256"
+#define NID_ecdsa_with_SHA256           794
+#define OBJ_ecdsa_with_SHA256           OBJ_ecdsa_with_Specified,2L
+
+#define SN_ecdsa_with_SHA384            "ecdsa-with-SHA384"
+#define NID_ecdsa_with_SHA384           795
+#define OBJ_ecdsa_with_SHA384           OBJ_ecdsa_with_Specified,3L
+
+#define SN_ecdsa_with_SHA512            "ecdsa-with-SHA512"
+#define NID_ecdsa_with_SHA512           796
+#define OBJ_ecdsa_with_SHA512           OBJ_ecdsa_with_Specified,4L
+
+#define OBJ_secg_ellipticCurve          OBJ_certicom_arc,0L
+
+#define SN_secp112r1            "secp112r1"
+#define NID_secp112r1           704
+#define OBJ_secp112r1           OBJ_secg_ellipticCurve,6L
+
+#define SN_secp112r2            "secp112r2"
+#define NID_secp112r2           705
+#define OBJ_secp112r2           OBJ_secg_ellipticCurve,7L
+
+#define SN_secp128r1            "secp128r1"
+#define NID_secp128r1           706
+#define OBJ_secp128r1           OBJ_secg_ellipticCurve,28L
+
+#define SN_secp128r2            "secp128r2"
+#define NID_secp128r2           707
+#define OBJ_secp128r2           OBJ_secg_ellipticCurve,29L
+
+#define SN_secp160k1            "secp160k1"
+#define NID_secp160k1           708
+#define OBJ_secp160k1           OBJ_secg_ellipticCurve,9L
+
+#define SN_secp160r1            "secp160r1"
+#define NID_secp160r1           709
+#define OBJ_secp160r1           OBJ_secg_ellipticCurve,8L
+
+#define SN_secp160r2            "secp160r2"
+#define NID_secp160r2           710
+#define OBJ_secp160r2           OBJ_secg_ellipticCurve,30L
+
+#define SN_secp192k1            "secp192k1"
+#define NID_secp192k1           711
+#define OBJ_secp192k1           OBJ_secg_ellipticCurve,31L
+
+#define SN_secp224k1            "secp224k1"
+#define NID_secp224k1           712
+#define OBJ_secp224k1           OBJ_secg_ellipticCurve,32L
+
+#define SN_secp224r1            "secp224r1"
+#define NID_secp224r1           713
+#define OBJ_secp224r1           OBJ_secg_ellipticCurve,33L
+
+#define SN_secp256k1            "secp256k1"
+#define NID_secp256k1           714
+#define OBJ_secp256k1           OBJ_secg_ellipticCurve,10L
+
+#define SN_secp384r1            "secp384r1"
+#define NID_secp384r1           715
+#define OBJ_secp384r1           OBJ_secg_ellipticCurve,34L
+
+#define SN_secp521r1            "secp521r1"
+#define NID_secp521r1           716
+#define OBJ_secp521r1           OBJ_secg_ellipticCurve,35L
+
+#define SN_sect113r1            "sect113r1"
+#define NID_sect113r1           717
+#define OBJ_sect113r1           OBJ_secg_ellipticCurve,4L
+
+#define SN_sect113r2            "sect113r2"
+#define NID_sect113r2           718
+#define OBJ_sect113r2           OBJ_secg_ellipticCurve,5L
+
+#define SN_sect131r1            "sect131r1"
+#define NID_sect131r1           719
+#define OBJ_sect131r1           OBJ_secg_ellipticCurve,22L
+
+#define SN_sect131r2            "sect131r2"
+#define NID_sect131r2           720
+#define OBJ_sect131r2           OBJ_secg_ellipticCurve,23L
+
+#define SN_sect163k1            "sect163k1"
+#define NID_sect163k1           721
+#define OBJ_sect163k1           OBJ_secg_ellipticCurve,1L
+
+#define SN_sect163r1            "sect163r1"
+#define NID_sect163r1           722
+#define OBJ_sect163r1           OBJ_secg_ellipticCurve,2L
+
+#define SN_sect163r2            "sect163r2"
+#define NID_sect163r2           723
+#define OBJ_sect163r2           OBJ_secg_ellipticCurve,15L
+
+#define SN_sect193r1            "sect193r1"
+#define NID_sect193r1           724
+#define OBJ_sect193r1           OBJ_secg_ellipticCurve,24L
+
+#define SN_sect193r2            "sect193r2"
+#define NID_sect193r2           725
+#define OBJ_sect193r2           OBJ_secg_ellipticCurve,25L
+
+#define SN_sect233k1            "sect233k1"
+#define NID_sect233k1           726
+#define OBJ_sect233k1           OBJ_secg_ellipticCurve,26L
+
+#define SN_sect233r1            "sect233r1"
+#define NID_sect233r1           727
+#define OBJ_sect233r1           OBJ_secg_ellipticCurve,27L
+
+#define SN_sect239k1            "sect239k1"
+#define NID_sect239k1           728
+#define OBJ_sect239k1           OBJ_secg_ellipticCurve,3L
+
+#define SN_sect283k1            "sect283k1"
+#define NID_sect283k1           729
+#define OBJ_sect283k1           OBJ_secg_ellipticCurve,16L
+
+#define SN_sect283r1            "sect283r1"
+#define NID_sect283r1           730
+#define OBJ_sect283r1           OBJ_secg_ellipticCurve,17L
+
+#define SN_sect409k1            "sect409k1"
+#define NID_sect409k1           731
+#define OBJ_sect409k1           OBJ_secg_ellipticCurve,36L
+
+#define SN_sect409r1            "sect409r1"
+#define NID_sect409r1           732
+#define OBJ_sect409r1           OBJ_secg_ellipticCurve,37L
+
+#define SN_sect571k1            "sect571k1"
+#define NID_sect571k1           733
+#define OBJ_sect571k1           OBJ_secg_ellipticCurve,38L
+
+#define SN_sect571r1            "sect571r1"
+#define NID_sect571r1           734
+#define OBJ_sect571r1           OBJ_secg_ellipticCurve,39L
+
+#define OBJ_wap_wsg_idm_ecid            OBJ_wap_wsg,4L
+
+#define SN_wap_wsg_idm_ecid_wtls1               "wap-wsg-idm-ecid-wtls1"
+#define NID_wap_wsg_idm_ecid_wtls1              735
+#define OBJ_wap_wsg_idm_ecid_wtls1              OBJ_wap_wsg_idm_ecid,1L
+
+#define SN_wap_wsg_idm_ecid_wtls3               "wap-wsg-idm-ecid-wtls3"
+#define NID_wap_wsg_idm_ecid_wtls3              736
+#define OBJ_wap_wsg_idm_ecid_wtls3              OBJ_wap_wsg_idm_ecid,3L
+
+#define SN_wap_wsg_idm_ecid_wtls4               "wap-wsg-idm-ecid-wtls4"
+#define NID_wap_wsg_idm_ecid_wtls4              737
+#define OBJ_wap_wsg_idm_ecid_wtls4              OBJ_wap_wsg_idm_ecid,4L
+
+#define SN_wap_wsg_idm_ecid_wtls5               "wap-wsg-idm-ecid-wtls5"
+#define NID_wap_wsg_idm_ecid_wtls5              738
+#define OBJ_wap_wsg_idm_ecid_wtls5              OBJ_wap_wsg_idm_ecid,5L
+
+#define SN_wap_wsg_idm_ecid_wtls6               "wap-wsg-idm-ecid-wtls6"
+#define NID_wap_wsg_idm_ecid_wtls6              739
+#define OBJ_wap_wsg_idm_ecid_wtls6              OBJ_wap_wsg_idm_ecid,6L
+
+#define SN_wap_wsg_idm_ecid_wtls7               "wap-wsg-idm-ecid-wtls7"
+#define NID_wap_wsg_idm_ecid_wtls7              740
+#define OBJ_wap_wsg_idm_ecid_wtls7              OBJ_wap_wsg_idm_ecid,7L
+
+#define SN_wap_wsg_idm_ecid_wtls8               "wap-wsg-idm-ecid-wtls8"
+#define NID_wap_wsg_idm_ecid_wtls8              741
+#define OBJ_wap_wsg_idm_ecid_wtls8              OBJ_wap_wsg_idm_ecid,8L
+
+#define SN_wap_wsg_idm_ecid_wtls9               "wap-wsg-idm-ecid-wtls9"
+#define NID_wap_wsg_idm_ecid_wtls9              742
+#define OBJ_wap_wsg_idm_ecid_wtls9              OBJ_wap_wsg_idm_ecid,9L
+
+#define SN_wap_wsg_idm_ecid_wtls10              "wap-wsg-idm-ecid-wtls10"
+#define NID_wap_wsg_idm_ecid_wtls10             743
+#define OBJ_wap_wsg_idm_ecid_wtls10             OBJ_wap_wsg_idm_ecid,10L
+
+#define SN_wap_wsg_idm_ecid_wtls11              "wap-wsg-idm-ecid-wtls11"
+#define NID_wap_wsg_idm_ecid_wtls11             744
+#define OBJ_wap_wsg_idm_ecid_wtls11             OBJ_wap_wsg_idm_ecid,11L
+
+#define SN_wap_wsg_idm_ecid_wtls12              "wap-wsg-idm-ecid-wtls12"
+#define NID_wap_wsg_idm_ecid_wtls12             745
+#define OBJ_wap_wsg_idm_ecid_wtls12             OBJ_wap_wsg_idm_ecid,12L
+
+#define SN_cast5_cbc            "CAST5-CBC"
+#define LN_cast5_cbc            "cast5-cbc"
+#define NID_cast5_cbc           108
+#define OBJ_cast5_cbc           OBJ_ISO_US,113533L,7L,66L,10L
+
+#define SN_cast5_ecb            "CAST5-ECB"
+#define LN_cast5_ecb            "cast5-ecb"
+#define NID_cast5_ecb           109
+
+#define SN_cast5_cfb64          "CAST5-CFB"
+#define LN_cast5_cfb64          "cast5-cfb"
+#define NID_cast5_cfb64         110
+
+#define SN_cast5_ofb64          "CAST5-OFB"
+#define LN_cast5_ofb64          "cast5-ofb"
+#define NID_cast5_ofb64         111
+
+#define LN_pbeWithMD5AndCast5_CBC               "pbeWithMD5AndCast5CBC"
+#define NID_pbeWithMD5AndCast5_CBC              112
+#define OBJ_pbeWithMD5AndCast5_CBC              OBJ_ISO_US,113533L,7L,66L,12L
+
+#define SN_id_PasswordBasedMAC          "id-PasswordBasedMAC"
+#define LN_id_PasswordBasedMAC          "password based MAC"
+#define NID_id_PasswordBasedMAC         782
+#define OBJ_id_PasswordBasedMAC         OBJ_ISO_US,113533L,7L,66L,13L
+
+#define SN_id_DHBasedMac                "id-DHBasedMac"
+#define LN_id_DHBasedMac                "Diffie-Hellman based MAC"
+#define NID_id_DHBasedMac               783
+#define OBJ_id_DHBasedMac               OBJ_ISO_US,113533L,7L,66L,30L
+
+#define SN_rsadsi               "rsadsi"
+#define LN_rsadsi               "RSA Data Security, Inc."
+#define NID_rsadsi              1
+#define OBJ_rsadsi              OBJ_ISO_US,113549L
+
+#define SN_pkcs         "pkcs"
+#define LN_pkcs         "RSA Data Security, Inc. PKCS"
+#define NID_pkcs                2
+#define OBJ_pkcs                OBJ_rsadsi,1L
+
+#define SN_pkcs1                "pkcs1"
+#define NID_pkcs1               186
+#define OBJ_pkcs1               OBJ_pkcs,1L
+
+#define LN_rsaEncryption                "rsaEncryption"
+#define NID_rsaEncryption               6
+#define OBJ_rsaEncryption               OBJ_pkcs1,1L
+
+#define SN_md2WithRSAEncryption         "RSA-MD2"
+#define LN_md2WithRSAEncryption         "md2WithRSAEncryption"
+#define NID_md2WithRSAEncryption                7
+#define OBJ_md2WithRSAEncryption                OBJ_pkcs1,2L
+
+#define SN_md4WithRSAEncryption         "RSA-MD4"
+#define LN_md4WithRSAEncryption         "md4WithRSAEncryption"
+#define NID_md4WithRSAEncryption                396
+#define OBJ_md4WithRSAEncryption                OBJ_pkcs1,3L
+
+#define SN_md5WithRSAEncryption         "RSA-MD5"
+#define LN_md5WithRSAEncryption         "md5WithRSAEncryption"
+#define NID_md5WithRSAEncryption                8
+#define OBJ_md5WithRSAEncryption                OBJ_pkcs1,4L
+
+#define SN_sha1WithRSAEncryption                "RSA-SHA1"
+#define LN_sha1WithRSAEncryption                "sha1WithRSAEncryption"
+#define NID_sha1WithRSAEncryption               65
+#define OBJ_sha1WithRSAEncryption               OBJ_pkcs1,5L
+
+#define SN_rsaesOaep            "RSAES-OAEP"
+#define LN_rsaesOaep            "rsaesOaep"
+#define NID_rsaesOaep           919
+#define OBJ_rsaesOaep           OBJ_pkcs1,7L
+
+#define SN_mgf1         "MGF1"
+#define LN_mgf1         "mgf1"
+#define NID_mgf1                911
+#define OBJ_mgf1                OBJ_pkcs1,8L
+
+#define SN_pSpecified           "PSPECIFIED"
+#define LN_pSpecified           "pSpecified"
+#define NID_pSpecified          935
+#define OBJ_pSpecified          OBJ_pkcs1,9L
+
+#define SN_rsassaPss            "RSASSA-PSS"
+#define LN_rsassaPss            "rsassaPss"
+#define NID_rsassaPss           912
+#define OBJ_rsassaPss           OBJ_pkcs1,10L
+
+#define SN_sha256WithRSAEncryption              "RSA-SHA256"
+#define LN_sha256WithRSAEncryption              "sha256WithRSAEncryption"
+#define NID_sha256WithRSAEncryption             668
+#define OBJ_sha256WithRSAEncryption             OBJ_pkcs1,11L
+
+#define SN_sha384WithRSAEncryption              "RSA-SHA384"
+#define LN_sha384WithRSAEncryption              "sha384WithRSAEncryption"
+#define NID_sha384WithRSAEncryption             669
+#define OBJ_sha384WithRSAEncryption             OBJ_pkcs1,12L
+
+#define SN_sha512WithRSAEncryption              "RSA-SHA512"
+#define LN_sha512WithRSAEncryption              "sha512WithRSAEncryption"
+#define NID_sha512WithRSAEncryption             670
+#define OBJ_sha512WithRSAEncryption             OBJ_pkcs1,13L
+
+#define SN_sha224WithRSAEncryption              "RSA-SHA224"
+#define LN_sha224WithRSAEncryption              "sha224WithRSAEncryption"
+#define NID_sha224WithRSAEncryption             671
+#define OBJ_sha224WithRSAEncryption             OBJ_pkcs1,14L
+
+#define SN_pkcs3                "pkcs3"
+#define NID_pkcs3               27
+#define OBJ_pkcs3               OBJ_pkcs,3L
+
+#define LN_dhKeyAgreement               "dhKeyAgreement"
+#define NID_dhKeyAgreement              28
+#define OBJ_dhKeyAgreement              OBJ_pkcs3,1L
+
+#define SN_pkcs5                "pkcs5"
+#define NID_pkcs5               187
+#define OBJ_pkcs5               OBJ_pkcs,5L
+
+#define SN_pbeWithMD2AndDES_CBC         "PBE-MD2-DES"
+#define LN_pbeWithMD2AndDES_CBC         "pbeWithMD2AndDES-CBC"
+#define NID_pbeWithMD2AndDES_CBC                9
+#define OBJ_pbeWithMD2AndDES_CBC                OBJ_pkcs5,1L
+
+#define SN_pbeWithMD5AndDES_CBC         "PBE-MD5-DES"
+#define LN_pbeWithMD5AndDES_CBC         "pbeWithMD5AndDES-CBC"
+#define NID_pbeWithMD5AndDES_CBC                10
+#define OBJ_pbeWithMD5AndDES_CBC                OBJ_pkcs5,3L
+
+#define SN_pbeWithMD2AndRC2_CBC         "PBE-MD2-RC2-64"
+#define LN_pbeWithMD2AndRC2_CBC         "pbeWithMD2AndRC2-CBC"
+#define NID_pbeWithMD2AndRC2_CBC                168
+#define OBJ_pbeWithMD2AndRC2_CBC                OBJ_pkcs5,4L
+
+#define SN_pbeWithMD5AndRC2_CBC         "PBE-MD5-RC2-64"
+#define LN_pbeWithMD5AndRC2_CBC         "pbeWithMD5AndRC2-CBC"
+#define NID_pbeWithMD5AndRC2_CBC                169
+#define OBJ_pbeWithMD5AndRC2_CBC                OBJ_pkcs5,6L
+
+#define SN_pbeWithSHA1AndDES_CBC                "PBE-SHA1-DES"
+#define LN_pbeWithSHA1AndDES_CBC                "pbeWithSHA1AndDES-CBC"
+#define NID_pbeWithSHA1AndDES_CBC               170
+#define OBJ_pbeWithSHA1AndDES_CBC               OBJ_pkcs5,10L
+
+#define SN_pbeWithSHA1AndRC2_CBC                "PBE-SHA1-RC2-64"
+#define LN_pbeWithSHA1AndRC2_CBC                "pbeWithSHA1AndRC2-CBC"
+#define NID_pbeWithSHA1AndRC2_CBC               68
+#define OBJ_pbeWithSHA1AndRC2_CBC               OBJ_pkcs5,11L
+
+#define LN_id_pbkdf2            "PBKDF2"
+#define NID_id_pbkdf2           69
+#define OBJ_id_pbkdf2           OBJ_pkcs5,12L
+
+#define LN_pbes2                "PBES2"
+#define NID_pbes2               161
+#define OBJ_pbes2               OBJ_pkcs5,13L
+
+#define LN_pbmac1               "PBMAC1"
+#define NID_pbmac1              162
+#define OBJ_pbmac1              OBJ_pkcs5,14L
+
+#define SN_pkcs7                "pkcs7"
+#define NID_pkcs7               20
+#define OBJ_pkcs7               OBJ_pkcs,7L
+
+#define LN_pkcs7_data           "pkcs7-data"
+#define NID_pkcs7_data          21
+#define OBJ_pkcs7_data          OBJ_pkcs7,1L
+
+#define LN_pkcs7_signed         "pkcs7-signedData"
+#define NID_pkcs7_signed                22
+#define OBJ_pkcs7_signed                OBJ_pkcs7,2L
+
+#define LN_pkcs7_enveloped              "pkcs7-envelopedData"
+#define NID_pkcs7_enveloped             23
+#define OBJ_pkcs7_enveloped             OBJ_pkcs7,3L
+
+#define LN_pkcs7_signedAndEnveloped             "pkcs7-signedAndEnvelopedData"
+#define NID_pkcs7_signedAndEnveloped            24
+#define OBJ_pkcs7_signedAndEnveloped            OBJ_pkcs7,4L
+
+#define LN_pkcs7_digest         "pkcs7-digestData"
+#define NID_pkcs7_digest                25
+#define OBJ_pkcs7_digest                OBJ_pkcs7,5L
+
+#define LN_pkcs7_encrypted              "pkcs7-encryptedData"
+#define NID_pkcs7_encrypted             26
+#define OBJ_pkcs7_encrypted             OBJ_pkcs7,6L
+
+#define SN_pkcs9                "pkcs9"
+#define NID_pkcs9               47
+#define OBJ_pkcs9               OBJ_pkcs,9L
+
+#define LN_pkcs9_emailAddress           "emailAddress"
+#define NID_pkcs9_emailAddress          48
+#define OBJ_pkcs9_emailAddress          OBJ_pkcs9,1L
+
+#define LN_pkcs9_unstructuredName               "unstructuredName"
+#define NID_pkcs9_unstructuredName              49
+#define OBJ_pkcs9_unstructuredName              OBJ_pkcs9,2L
+
+#define LN_pkcs9_contentType            "contentType"
+#define NID_pkcs9_contentType           50
+#define OBJ_pkcs9_contentType           OBJ_pkcs9,3L
+
+#define LN_pkcs9_messageDigest          "messageDigest"
+#define NID_pkcs9_messageDigest         51
+#define OBJ_pkcs9_messageDigest         OBJ_pkcs9,4L
+
+#define LN_pkcs9_signingTime            "signingTime"
+#define NID_pkcs9_signingTime           52
+#define OBJ_pkcs9_signingTime           OBJ_pkcs9,5L
+
+#define LN_pkcs9_countersignature               "countersignature"
+#define NID_pkcs9_countersignature              53
+#define OBJ_pkcs9_countersignature              OBJ_pkcs9,6L
+
+#define LN_pkcs9_challengePassword              "challengePassword"
+#define NID_pkcs9_challengePassword             54
+#define OBJ_pkcs9_challengePassword             OBJ_pkcs9,7L
+
+#define LN_pkcs9_unstructuredAddress            "unstructuredAddress"
+#define NID_pkcs9_unstructuredAddress           55
+#define OBJ_pkcs9_unstructuredAddress           OBJ_pkcs9,8L
+
+#define LN_pkcs9_extCertAttributes              "extendedCertificateAttributes"
+#define NID_pkcs9_extCertAttributes             56
+#define OBJ_pkcs9_extCertAttributes             OBJ_pkcs9,9L
+
+#define SN_ext_req              "extReq"
+#define LN_ext_req              "Extension Request"
+#define NID_ext_req             172
+#define OBJ_ext_req             OBJ_pkcs9,14L
+
+#define SN_SMIMECapabilities            "SMIME-CAPS"
+#define LN_SMIMECapabilities            "S/MIME Capabilities"
+#define NID_SMIMECapabilities           167
+#define OBJ_SMIMECapabilities           OBJ_pkcs9,15L
+
+#define SN_SMIME                "SMIME"
+#define LN_SMIME                "S/MIME"
+#define NID_SMIME               188
+#define OBJ_SMIME               OBJ_pkcs9,16L
+
+#define SN_id_smime_mod         "id-smime-mod"
+#define NID_id_smime_mod                189
+#define OBJ_id_smime_mod                OBJ_SMIME,0L
+
+#define SN_id_smime_ct          "id-smime-ct"
+#define NID_id_smime_ct         190
+#define OBJ_id_smime_ct         OBJ_SMIME,1L
+
+#define SN_id_smime_aa          "id-smime-aa"
+#define NID_id_smime_aa         191
+#define OBJ_id_smime_aa         OBJ_SMIME,2L
+
+#define SN_id_smime_alg         "id-smime-alg"
+#define NID_id_smime_alg                192
+#define OBJ_id_smime_alg                OBJ_SMIME,3L
+
+#define SN_id_smime_cd          "id-smime-cd"
+#define NID_id_smime_cd         193
+#define OBJ_id_smime_cd         OBJ_SMIME,4L
+
+#define SN_id_smime_spq         "id-smime-spq"
+#define NID_id_smime_spq                194
+#define OBJ_id_smime_spq                OBJ_SMIME,5L
+
+#define SN_id_smime_cti         "id-smime-cti"
+#define NID_id_smime_cti                195
+#define OBJ_id_smime_cti                OBJ_SMIME,6L
+
+#define SN_id_smime_mod_cms             "id-smime-mod-cms"
+#define NID_id_smime_mod_cms            196
+#define OBJ_id_smime_mod_cms            OBJ_id_smime_mod,1L
+
+#define SN_id_smime_mod_ess             "id-smime-mod-ess"
+#define NID_id_smime_mod_ess            197
+#define OBJ_id_smime_mod_ess            OBJ_id_smime_mod,2L
+
+#define SN_id_smime_mod_oid             "id-smime-mod-oid"
+#define NID_id_smime_mod_oid            198
+#define OBJ_id_smime_mod_oid            OBJ_id_smime_mod,3L
+
+#define SN_id_smime_mod_msg_v3          "id-smime-mod-msg-v3"
+#define NID_id_smime_mod_msg_v3         199
+#define OBJ_id_smime_mod_msg_v3         OBJ_id_smime_mod,4L
+
+#define SN_id_smime_mod_ets_eSignature_88               "id-smime-mod-ets-eSignature-88"
+#define NID_id_smime_mod_ets_eSignature_88              200
+#define OBJ_id_smime_mod_ets_eSignature_88              OBJ_id_smime_mod,5L
+
+#define SN_id_smime_mod_ets_eSignature_97               "id-smime-mod-ets-eSignature-97"
+#define NID_id_smime_mod_ets_eSignature_97              201
+#define OBJ_id_smime_mod_ets_eSignature_97              OBJ_id_smime_mod,6L
+
+#define SN_id_smime_mod_ets_eSigPolicy_88               "id-smime-mod-ets-eSigPolicy-88"
+#define NID_id_smime_mod_ets_eSigPolicy_88              202
+#define OBJ_id_smime_mod_ets_eSigPolicy_88              OBJ_id_smime_mod,7L
+
+#define SN_id_smime_mod_ets_eSigPolicy_97               "id-smime-mod-ets-eSigPolicy-97"
+#define NID_id_smime_mod_ets_eSigPolicy_97              203
+#define OBJ_id_smime_mod_ets_eSigPolicy_97              OBJ_id_smime_mod,8L
+
+#define SN_id_smime_ct_receipt          "id-smime-ct-receipt"
+#define NID_id_smime_ct_receipt         204
+#define OBJ_id_smime_ct_receipt         OBJ_id_smime_ct,1L
+
+#define SN_id_smime_ct_authData         "id-smime-ct-authData"
+#define NID_id_smime_ct_authData                205
+#define OBJ_id_smime_ct_authData                OBJ_id_smime_ct,2L
+
+#define SN_id_smime_ct_publishCert              "id-smime-ct-publishCert"
+#define NID_id_smime_ct_publishCert             206
+#define OBJ_id_smime_ct_publishCert             OBJ_id_smime_ct,3L
+
+#define SN_id_smime_ct_TSTInfo          "id-smime-ct-TSTInfo"
+#define NID_id_smime_ct_TSTInfo         207
+#define OBJ_id_smime_ct_TSTInfo         OBJ_id_smime_ct,4L
+
+#define SN_id_smime_ct_TDTInfo          "id-smime-ct-TDTInfo"
+#define NID_id_smime_ct_TDTInfo         208
+#define OBJ_id_smime_ct_TDTInfo         OBJ_id_smime_ct,5L
+
+#define SN_id_smime_ct_contentInfo              "id-smime-ct-contentInfo"
+#define NID_id_smime_ct_contentInfo             209
+#define OBJ_id_smime_ct_contentInfo             OBJ_id_smime_ct,6L
+
+#define SN_id_smime_ct_DVCSRequestData          "id-smime-ct-DVCSRequestData"
+#define NID_id_smime_ct_DVCSRequestData         210
+#define OBJ_id_smime_ct_DVCSRequestData         OBJ_id_smime_ct,7L
+
+#define SN_id_smime_ct_DVCSResponseData         "id-smime-ct-DVCSResponseData"
+#define NID_id_smime_ct_DVCSResponseData                211
+#define OBJ_id_smime_ct_DVCSResponseData                OBJ_id_smime_ct,8L
+
+#define SN_id_smime_ct_compressedData           "id-smime-ct-compressedData"
+#define NID_id_smime_ct_compressedData          786
+#define OBJ_id_smime_ct_compressedData          OBJ_id_smime_ct,9L
+
+#define SN_id_ct_asciiTextWithCRLF              "id-ct-asciiTextWithCRLF"
+#define NID_id_ct_asciiTextWithCRLF             787
+#define OBJ_id_ct_asciiTextWithCRLF             OBJ_id_smime_ct,27L
+
+#define SN_id_smime_aa_receiptRequest           "id-smime-aa-receiptRequest"
+#define NID_id_smime_aa_receiptRequest          212
+#define OBJ_id_smime_aa_receiptRequest          OBJ_id_smime_aa,1L
+
+#define SN_id_smime_aa_securityLabel            "id-smime-aa-securityLabel"
+#define NID_id_smime_aa_securityLabel           213
+#define OBJ_id_smime_aa_securityLabel           OBJ_id_smime_aa,2L
+
+#define SN_id_smime_aa_mlExpandHistory          "id-smime-aa-mlExpandHistory"
+#define NID_id_smime_aa_mlExpandHistory         214
+#define OBJ_id_smime_aa_mlExpandHistory         OBJ_id_smime_aa,3L
+
+#define SN_id_smime_aa_contentHint              "id-smime-aa-contentHint"
+#define NID_id_smime_aa_contentHint             215
+#define OBJ_id_smime_aa_contentHint             OBJ_id_smime_aa,4L
+
+#define SN_id_smime_aa_msgSigDigest             "id-smime-aa-msgSigDigest"
+#define NID_id_smime_aa_msgSigDigest            216
+#define OBJ_id_smime_aa_msgSigDigest            OBJ_id_smime_aa,5L
+
+#define SN_id_smime_aa_encapContentType         "id-smime-aa-encapContentType"
+#define NID_id_smime_aa_encapContentType                217
+#define OBJ_id_smime_aa_encapContentType                OBJ_id_smime_aa,6L
+
+#define SN_id_smime_aa_contentIdentifier                "id-smime-aa-contentIdentifier"
+#define NID_id_smime_aa_contentIdentifier               218
+#define OBJ_id_smime_aa_contentIdentifier               OBJ_id_smime_aa,7L
+
+#define SN_id_smime_aa_macValue         "id-smime-aa-macValue"
+#define NID_id_smime_aa_macValue                219
+#define OBJ_id_smime_aa_macValue                OBJ_id_smime_aa,8L
+
+#define SN_id_smime_aa_equivalentLabels         "id-smime-aa-equivalentLabels"
+#define NID_id_smime_aa_equivalentLabels                220
+#define OBJ_id_smime_aa_equivalentLabels                OBJ_id_smime_aa,9L
+
+#define SN_id_smime_aa_contentReference         "id-smime-aa-contentReference"
+#define NID_id_smime_aa_contentReference                221
+#define OBJ_id_smime_aa_contentReference                OBJ_id_smime_aa,10L
+
+#define SN_id_smime_aa_encrypKeyPref            "id-smime-aa-encrypKeyPref"
+#define NID_id_smime_aa_encrypKeyPref           222
+#define OBJ_id_smime_aa_encrypKeyPref           OBJ_id_smime_aa,11L
+
+#define SN_id_smime_aa_signingCertificate               "id-smime-aa-signingCertificate"
+#define NID_id_smime_aa_signingCertificate              223
+#define OBJ_id_smime_aa_signingCertificate              OBJ_id_smime_aa,12L
+
+#define SN_id_smime_aa_smimeEncryptCerts                "id-smime-aa-smimeEncryptCerts"
+#define NID_id_smime_aa_smimeEncryptCerts               224
+#define OBJ_id_smime_aa_smimeEncryptCerts               OBJ_id_smime_aa,13L
+
+#define SN_id_smime_aa_timeStampToken           "id-smime-aa-timeStampToken"
+#define NID_id_smime_aa_timeStampToken          225
+#define OBJ_id_smime_aa_timeStampToken          OBJ_id_smime_aa,14L
+
+#define SN_id_smime_aa_ets_sigPolicyId          "id-smime-aa-ets-sigPolicyId"
+#define NID_id_smime_aa_ets_sigPolicyId         226
+#define OBJ_id_smime_aa_ets_sigPolicyId         OBJ_id_smime_aa,15L
+
+#define SN_id_smime_aa_ets_commitmentType               "id-smime-aa-ets-commitmentType"
+#define NID_id_smime_aa_ets_commitmentType              227
+#define OBJ_id_smime_aa_ets_commitmentType              OBJ_id_smime_aa,16L
+
+#define SN_id_smime_aa_ets_signerLocation               "id-smime-aa-ets-signerLocation"
+#define NID_id_smime_aa_ets_signerLocation              228
+#define OBJ_id_smime_aa_ets_signerLocation              OBJ_id_smime_aa,17L
+
+#define SN_id_smime_aa_ets_signerAttr           "id-smime-aa-ets-signerAttr"
+#define NID_id_smime_aa_ets_signerAttr          229
+#define OBJ_id_smime_aa_ets_signerAttr          OBJ_id_smime_aa,18L
+
+#define SN_id_smime_aa_ets_otherSigCert         "id-smime-aa-ets-otherSigCert"
+#define NID_id_smime_aa_ets_otherSigCert                230
+#define OBJ_id_smime_aa_ets_otherSigCert                OBJ_id_smime_aa,19L
+
+#define SN_id_smime_aa_ets_contentTimestamp             "id-smime-aa-ets-contentTimestamp"
+#define NID_id_smime_aa_ets_contentTimestamp            231
+#define OBJ_id_smime_aa_ets_contentTimestamp            OBJ_id_smime_aa,20L
+
+#define SN_id_smime_aa_ets_CertificateRefs              "id-smime-aa-ets-CertificateRefs"
+#define NID_id_smime_aa_ets_CertificateRefs             232
+#define OBJ_id_smime_aa_ets_CertificateRefs             OBJ_id_smime_aa,21L
+
+#define SN_id_smime_aa_ets_RevocationRefs               "id-smime-aa-ets-RevocationRefs"
+#define NID_id_smime_aa_ets_RevocationRefs              233
+#define OBJ_id_smime_aa_ets_RevocationRefs              OBJ_id_smime_aa,22L
+
+#define SN_id_smime_aa_ets_certValues           "id-smime-aa-ets-certValues"
+#define NID_id_smime_aa_ets_certValues          234
+#define OBJ_id_smime_aa_ets_certValues          OBJ_id_smime_aa,23L
+
+#define SN_id_smime_aa_ets_revocationValues             "id-smime-aa-ets-revocationValues"
+#define NID_id_smime_aa_ets_revocationValues            235
+#define OBJ_id_smime_aa_ets_revocationValues            OBJ_id_smime_aa,24L
+
+#define SN_id_smime_aa_ets_escTimeStamp         "id-smime-aa-ets-escTimeStamp"
+#define NID_id_smime_aa_ets_escTimeStamp                236
+#define OBJ_id_smime_aa_ets_escTimeStamp                OBJ_id_smime_aa,25L
+
+#define SN_id_smime_aa_ets_certCRLTimestamp             "id-smime-aa-ets-certCRLTimestamp"
+#define NID_id_smime_aa_ets_certCRLTimestamp            237
+#define OBJ_id_smime_aa_ets_certCRLTimestamp            OBJ_id_smime_aa,26L
+
+#define SN_id_smime_aa_ets_archiveTimeStamp             "id-smime-aa-ets-archiveTimeStamp"
+#define NID_id_smime_aa_ets_archiveTimeStamp            238
+#define OBJ_id_smime_aa_ets_archiveTimeStamp            OBJ_id_smime_aa,27L
+
+#define SN_id_smime_aa_signatureType            "id-smime-aa-signatureType"
+#define NID_id_smime_aa_signatureType           239
+#define OBJ_id_smime_aa_signatureType           OBJ_id_smime_aa,28L
+
+#define SN_id_smime_aa_dvcs_dvc         "id-smime-aa-dvcs-dvc"
+#define NID_id_smime_aa_dvcs_dvc                240
+#define OBJ_id_smime_aa_dvcs_dvc                OBJ_id_smime_aa,29L
+
+#define SN_id_smime_alg_ESDHwith3DES            "id-smime-alg-ESDHwith3DES"
+#define NID_id_smime_alg_ESDHwith3DES           241
+#define OBJ_id_smime_alg_ESDHwith3DES           OBJ_id_smime_alg,1L
+
+#define SN_id_smime_alg_ESDHwithRC2             "id-smime-alg-ESDHwithRC2"
+#define NID_id_smime_alg_ESDHwithRC2            242
+#define OBJ_id_smime_alg_ESDHwithRC2            OBJ_id_smime_alg,2L
+
+#define SN_id_smime_alg_3DESwrap                "id-smime-alg-3DESwrap"
+#define NID_id_smime_alg_3DESwrap               243
+#define OBJ_id_smime_alg_3DESwrap               OBJ_id_smime_alg,3L
+
+#define SN_id_smime_alg_RC2wrap         "id-smime-alg-RC2wrap"
+#define NID_id_smime_alg_RC2wrap                244
+#define OBJ_id_smime_alg_RC2wrap                OBJ_id_smime_alg,4L
+
+#define SN_id_smime_alg_ESDH            "id-smime-alg-ESDH"
+#define NID_id_smime_alg_ESDH           245
+#define OBJ_id_smime_alg_ESDH           OBJ_id_smime_alg,5L
+
+#define SN_id_smime_alg_CMS3DESwrap             "id-smime-alg-CMS3DESwrap"
+#define NID_id_smime_alg_CMS3DESwrap            246
+#define OBJ_id_smime_alg_CMS3DESwrap            OBJ_id_smime_alg,6L
+
+#define SN_id_smime_alg_CMSRC2wrap              "id-smime-alg-CMSRC2wrap"
+#define NID_id_smime_alg_CMSRC2wrap             247
+#define OBJ_id_smime_alg_CMSRC2wrap             OBJ_id_smime_alg,7L
+
+#define SN_id_alg_PWRI_KEK              "id-alg-PWRI-KEK"
+#define NID_id_alg_PWRI_KEK             893
+#define OBJ_id_alg_PWRI_KEK             OBJ_id_smime_alg,9L
+
+#define SN_id_smime_cd_ldap             "id-smime-cd-ldap"
+#define NID_id_smime_cd_ldap            248
+#define OBJ_id_smime_cd_ldap            OBJ_id_smime_cd,1L
+
+#define SN_id_smime_spq_ets_sqt_uri             "id-smime-spq-ets-sqt-uri"
+#define NID_id_smime_spq_ets_sqt_uri            249
+#define OBJ_id_smime_spq_ets_sqt_uri            OBJ_id_smime_spq,1L
+
+#define SN_id_smime_spq_ets_sqt_unotice         "id-smime-spq-ets-sqt-unotice"
+#define NID_id_smime_spq_ets_sqt_unotice                250
+#define OBJ_id_smime_spq_ets_sqt_unotice                OBJ_id_smime_spq,2L
+
+#define SN_id_smime_cti_ets_proofOfOrigin               "id-smime-cti-ets-proofOfOrigin"
+#define NID_id_smime_cti_ets_proofOfOrigin              251
+#define OBJ_id_smime_cti_ets_proofOfOrigin              OBJ_id_smime_cti,1L
+
+#define SN_id_smime_cti_ets_proofOfReceipt              "id-smime-cti-ets-proofOfReceipt"
+#define NID_id_smime_cti_ets_proofOfReceipt             252
+#define OBJ_id_smime_cti_ets_proofOfReceipt             OBJ_id_smime_cti,2L
+
+#define SN_id_smime_cti_ets_proofOfDelivery             "id-smime-cti-ets-proofOfDelivery"
+#define NID_id_smime_cti_ets_proofOfDelivery            253
+#define OBJ_id_smime_cti_ets_proofOfDelivery            OBJ_id_smime_cti,3L
+
+#define SN_id_smime_cti_ets_proofOfSender               "id-smime-cti-ets-proofOfSender"
+#define NID_id_smime_cti_ets_proofOfSender              254
+#define OBJ_id_smime_cti_ets_proofOfSender              OBJ_id_smime_cti,4L
+
+#define SN_id_smime_cti_ets_proofOfApproval             "id-smime-cti-ets-proofOfApproval"
+#define NID_id_smime_cti_ets_proofOfApproval            255
+#define OBJ_id_smime_cti_ets_proofOfApproval            OBJ_id_smime_cti,5L
+
+#define SN_id_smime_cti_ets_proofOfCreation             "id-smime-cti-ets-proofOfCreation"
+#define NID_id_smime_cti_ets_proofOfCreation            256
+#define OBJ_id_smime_cti_ets_proofOfCreation            OBJ_id_smime_cti,6L
+
+#define LN_friendlyName         "friendlyName"
+#define NID_friendlyName                156
+#define OBJ_friendlyName                OBJ_pkcs9,20L
+
+#define LN_localKeyID           "localKeyID"
+#define NID_localKeyID          157
+#define OBJ_localKeyID          OBJ_pkcs9,21L
+
+#define SN_ms_csp_name          "CSPName"
+#define LN_ms_csp_name          "Microsoft CSP Name"
+#define NID_ms_csp_name         417
+#define OBJ_ms_csp_name         1L,3L,6L,1L,4L,1L,311L,17L,1L
+
+#define SN_LocalKeySet          "LocalKeySet"
+#define LN_LocalKeySet          "Microsoft Local Key set"
+#define NID_LocalKeySet         856
+#define OBJ_LocalKeySet         1L,3L,6L,1L,4L,1L,311L,17L,2L
+
+#define OBJ_certTypes           OBJ_pkcs9,22L
+
+#define LN_x509Certificate              "x509Certificate"
+#define NID_x509Certificate             158
+#define OBJ_x509Certificate             OBJ_certTypes,1L
+
+#define LN_sdsiCertificate              "sdsiCertificate"
+#define NID_sdsiCertificate             159
+#define OBJ_sdsiCertificate             OBJ_certTypes,2L
+
+#define OBJ_crlTypes            OBJ_pkcs9,23L
+
+#define LN_x509Crl              "x509Crl"
+#define NID_x509Crl             160
+#define OBJ_x509Crl             OBJ_crlTypes,1L
+
+#define OBJ_pkcs12              OBJ_pkcs,12L
+
+#define OBJ_pkcs12_pbeids               OBJ_pkcs12,1L
+
+#define SN_pbe_WithSHA1And128BitRC4             "PBE-SHA1-RC4-128"
+#define LN_pbe_WithSHA1And128BitRC4             "pbeWithSHA1And128BitRC4"
+#define NID_pbe_WithSHA1And128BitRC4            144
+#define OBJ_pbe_WithSHA1And128BitRC4            OBJ_pkcs12_pbeids,1L
+
+#define SN_pbe_WithSHA1And40BitRC4              "PBE-SHA1-RC4-40"
+#define LN_pbe_WithSHA1And40BitRC4              "pbeWithSHA1And40BitRC4"
+#define NID_pbe_WithSHA1And40BitRC4             145
+#define OBJ_pbe_WithSHA1And40BitRC4             OBJ_pkcs12_pbeids,2L
+
+#define SN_pbe_WithSHA1And3_Key_TripleDES_CBC           "PBE-SHA1-3DES"
+#define LN_pbe_WithSHA1And3_Key_TripleDES_CBC           "pbeWithSHA1And3-KeyTripleDES-CBC"
+#define NID_pbe_WithSHA1And3_Key_TripleDES_CBC          146
+#define OBJ_pbe_WithSHA1And3_Key_TripleDES_CBC          OBJ_pkcs12_pbeids,3L
+
+#define SN_pbe_WithSHA1And2_Key_TripleDES_CBC           "PBE-SHA1-2DES"
+#define LN_pbe_WithSHA1And2_Key_TripleDES_CBC           "pbeWithSHA1And2-KeyTripleDES-CBC"
+#define NID_pbe_WithSHA1And2_Key_TripleDES_CBC          147
+#define OBJ_pbe_WithSHA1And2_Key_TripleDES_CBC          OBJ_pkcs12_pbeids,4L
+
+#define SN_pbe_WithSHA1And128BitRC2_CBC         "PBE-SHA1-RC2-128"
+#define LN_pbe_WithSHA1And128BitRC2_CBC         "pbeWithSHA1And128BitRC2-CBC"
+#define NID_pbe_WithSHA1And128BitRC2_CBC                148
+#define OBJ_pbe_WithSHA1And128BitRC2_CBC                OBJ_pkcs12_pbeids,5L
+
+#define SN_pbe_WithSHA1And40BitRC2_CBC          "PBE-SHA1-RC2-40"
+#define LN_pbe_WithSHA1And40BitRC2_CBC          "pbeWithSHA1And40BitRC2-CBC"
+#define NID_pbe_WithSHA1And40BitRC2_CBC         149
+#define OBJ_pbe_WithSHA1And40BitRC2_CBC         OBJ_pkcs12_pbeids,6L
+
+#define OBJ_pkcs12_Version1             OBJ_pkcs12,10L
+
+#define OBJ_pkcs12_BagIds               OBJ_pkcs12_Version1,1L
+
+#define LN_keyBag               "keyBag"
+#define NID_keyBag              150
+#define OBJ_keyBag              OBJ_pkcs12_BagIds,1L
+
+#define LN_pkcs8ShroudedKeyBag          "pkcs8ShroudedKeyBag"
+#define NID_pkcs8ShroudedKeyBag         151
+#define OBJ_pkcs8ShroudedKeyBag         OBJ_pkcs12_BagIds,2L
+
+#define LN_certBag              "certBag"
+#define NID_certBag             152
+#define OBJ_certBag             OBJ_pkcs12_BagIds,3L
+
+#define LN_crlBag               "crlBag"
+#define NID_crlBag              153
+#define OBJ_crlBag              OBJ_pkcs12_BagIds,4L
+
+#define LN_secretBag            "secretBag"
+#define NID_secretBag           154
+#define OBJ_secretBag           OBJ_pkcs12_BagIds,5L
+
+#define LN_safeContentsBag              "safeContentsBag"
+#define NID_safeContentsBag             155
+#define OBJ_safeContentsBag             OBJ_pkcs12_BagIds,6L
+
+#define SN_md2          "MD2"
+#define LN_md2          "md2"
+#define NID_md2         3
+#define OBJ_md2         OBJ_rsadsi,2L,2L
+
+#define SN_md4          "MD4"
+#define LN_md4          "md4"
+#define NID_md4         257
+#define OBJ_md4         OBJ_rsadsi,2L,4L
+
+#define SN_md5          "MD5"
+#define LN_md5          "md5"
+#define NID_md5         4
+#define OBJ_md5         OBJ_rsadsi,2L,5L
+
+#define SN_md5_sha1             "MD5-SHA1"
+#define LN_md5_sha1             "md5-sha1"
+#define NID_md5_sha1            114
+
+#define LN_hmacWithMD5          "hmacWithMD5"
+#define NID_hmacWithMD5         797
+#define OBJ_hmacWithMD5         OBJ_rsadsi,2L,6L
+
+#define LN_hmacWithSHA1         "hmacWithSHA1"
+#define NID_hmacWithSHA1                163
+#define OBJ_hmacWithSHA1                OBJ_rsadsi,2L,7L
+
+#define LN_hmacWithSHA224               "hmacWithSHA224"
+#define NID_hmacWithSHA224              798
+#define OBJ_hmacWithSHA224              OBJ_rsadsi,2L,8L
+
+#define LN_hmacWithSHA256               "hmacWithSHA256"
+#define NID_hmacWithSHA256              799
+#define OBJ_hmacWithSHA256              OBJ_rsadsi,2L,9L
+
+#define LN_hmacWithSHA384               "hmacWithSHA384"
+#define NID_hmacWithSHA384              800
+#define OBJ_hmacWithSHA384              OBJ_rsadsi,2L,10L
+
+#define LN_hmacWithSHA512               "hmacWithSHA512"
+#define NID_hmacWithSHA512              801
+#define OBJ_hmacWithSHA512              OBJ_rsadsi,2L,11L
+
+#define SN_rc2_cbc              "RC2-CBC"
+#define LN_rc2_cbc              "rc2-cbc"
+#define NID_rc2_cbc             37
+#define OBJ_rc2_cbc             OBJ_rsadsi,3L,2L
+
+#define SN_rc2_ecb              "RC2-ECB"
+#define LN_rc2_ecb              "rc2-ecb"
+#define NID_rc2_ecb             38
+
+#define SN_rc2_cfb64            "RC2-CFB"
+#define LN_rc2_cfb64            "rc2-cfb"
+#define NID_rc2_cfb64           39
+
+#define SN_rc2_ofb64            "RC2-OFB"
+#define LN_rc2_ofb64            "rc2-ofb"
+#define NID_rc2_ofb64           40
+
+#define SN_rc2_40_cbc           "RC2-40-CBC"
+#define LN_rc2_40_cbc           "rc2-40-cbc"
+#define NID_rc2_40_cbc          98
+
+#define SN_rc2_64_cbc           "RC2-64-CBC"
+#define LN_rc2_64_cbc           "rc2-64-cbc"
+#define NID_rc2_64_cbc          166
+
+#define SN_rc4          "RC4"
+#define LN_rc4          "rc4"
+#define NID_rc4         5
+#define OBJ_rc4         OBJ_rsadsi,3L,4L
+
+#define SN_rc4_40               "RC4-40"
+#define LN_rc4_40               "rc4-40"
+#define NID_rc4_40              97
+
+#define SN_des_ede3_cbc         "DES-EDE3-CBC"
+#define LN_des_ede3_cbc         "des-ede3-cbc"
+#define NID_des_ede3_cbc                44
+#define OBJ_des_ede3_cbc                OBJ_rsadsi,3L,7L
+
+#define SN_rc5_cbc              "RC5-CBC"
+#define LN_rc5_cbc              "rc5-cbc"
+#define NID_rc5_cbc             120
+#define OBJ_rc5_cbc             OBJ_rsadsi,3L,8L
+
+#define SN_rc5_ecb              "RC5-ECB"
+#define LN_rc5_ecb              "rc5-ecb"
+#define NID_rc5_ecb             121
+
+#define SN_rc5_cfb64            "RC5-CFB"
+#define LN_rc5_cfb64            "rc5-cfb"
+#define NID_rc5_cfb64           122
+
+#define SN_rc5_ofb64            "RC5-OFB"
+#define LN_rc5_ofb64            "rc5-ofb"
+#define NID_rc5_ofb64           123
+
+#define SN_ms_ext_req           "msExtReq"
+#define LN_ms_ext_req           "Microsoft Extension Request"
+#define NID_ms_ext_req          171
+#define OBJ_ms_ext_req          1L,3L,6L,1L,4L,1L,311L,2L,1L,14L
+
+#define SN_ms_code_ind          "msCodeInd"
+#define LN_ms_code_ind          "Microsoft Individual Code Signing"
+#define NID_ms_code_ind         134
+#define OBJ_ms_code_ind         1L,3L,6L,1L,4L,1L,311L,2L,1L,21L
+
+#define SN_ms_code_com          "msCodeCom"
+#define LN_ms_code_com          "Microsoft Commercial Code Signing"
+#define NID_ms_code_com         135
+#define OBJ_ms_code_com         1L,3L,6L,1L,4L,1L,311L,2L,1L,22L
+
+#define SN_ms_ctl_sign          "msCTLSign"
+#define LN_ms_ctl_sign          "Microsoft Trust List Signing"
+#define NID_ms_ctl_sign         136
+#define OBJ_ms_ctl_sign         1L,3L,6L,1L,4L,1L,311L,10L,3L,1L
+
+#define SN_ms_sgc               "msSGC"
+#define LN_ms_sgc               "Microsoft Server Gated Crypto"
+#define NID_ms_sgc              137
+#define OBJ_ms_sgc              1L,3L,6L,1L,4L,1L,311L,10L,3L,3L
+
+#define SN_ms_efs               "msEFS"
+#define LN_ms_efs               "Microsoft Encrypted File System"
+#define NID_ms_efs              138
+#define OBJ_ms_efs              1L,3L,6L,1L,4L,1L,311L,10L,3L,4L
+
+#define SN_ms_smartcard_login           "msSmartcardLogin"
+#define LN_ms_smartcard_login           "Microsoft Smartcardlogin"
+#define NID_ms_smartcard_login          648
+#define OBJ_ms_smartcard_login          1L,3L,6L,1L,4L,1L,311L,20L,2L,2L
+
+#define SN_ms_upn               "msUPN"
+#define LN_ms_upn               "Microsoft Universal Principal Name"
+#define NID_ms_upn              649
+#define OBJ_ms_upn              1L,3L,6L,1L,4L,1L,311L,20L,2L,3L
+
+#define SN_idea_cbc             "IDEA-CBC"
+#define LN_idea_cbc             "idea-cbc"
+#define NID_idea_cbc            34
+#define OBJ_idea_cbc            1L,3L,6L,1L,4L,1L,188L,7L,1L,1L,2L
+
+#define SN_idea_ecb             "IDEA-ECB"
+#define LN_idea_ecb             "idea-ecb"
+#define NID_idea_ecb            36
+
+#define SN_idea_cfb64           "IDEA-CFB"
+#define LN_idea_cfb64           "idea-cfb"
+#define NID_idea_cfb64          35
+
+#define SN_idea_ofb64           "IDEA-OFB"
+#define LN_idea_ofb64           "idea-ofb"
+#define NID_idea_ofb64          46
+
+#define SN_bf_cbc               "BF-CBC"
+#define LN_bf_cbc               "bf-cbc"
+#define NID_bf_cbc              91
+#define OBJ_bf_cbc              1L,3L,6L,1L,4L,1L,3029L,1L,2L
+
+#define SN_bf_ecb               "BF-ECB"
+#define LN_bf_ecb               "bf-ecb"
+#define NID_bf_ecb              92
+
+#define SN_bf_cfb64             "BF-CFB"
+#define LN_bf_cfb64             "bf-cfb"
+#define NID_bf_cfb64            93
+
+#define SN_bf_ofb64             "BF-OFB"
+#define LN_bf_ofb64             "bf-ofb"
+#define NID_bf_ofb64            94
+
+#define SN_id_pkix              "PKIX"
+#define NID_id_pkix             127
+#define OBJ_id_pkix             1L,3L,6L,1L,5L,5L,7L
+
+#define SN_id_pkix_mod          "id-pkix-mod"
+#define NID_id_pkix_mod         258
+#define OBJ_id_pkix_mod         OBJ_id_pkix,0L
+
+#define SN_id_pe                "id-pe"
+#define NID_id_pe               175
+#define OBJ_id_pe               OBJ_id_pkix,1L
+
+#define SN_id_qt                "id-qt"
+#define NID_id_qt               259
+#define OBJ_id_qt               OBJ_id_pkix,2L
+
+#define SN_id_kp                "id-kp"
+#define NID_id_kp               128
+#define OBJ_id_kp               OBJ_id_pkix,3L
+
+#define SN_id_it                "id-it"
+#define NID_id_it               260
+#define OBJ_id_it               OBJ_id_pkix,4L
+
+#define SN_id_pkip              "id-pkip"
+#define NID_id_pkip             261
+#define OBJ_id_pkip             OBJ_id_pkix,5L
+
+#define SN_id_alg               "id-alg"
+#define NID_id_alg              262
+#define OBJ_id_alg              OBJ_id_pkix,6L
+
+#define SN_id_cmc               "id-cmc"
+#define NID_id_cmc              263
+#define OBJ_id_cmc              OBJ_id_pkix,7L
+
+#define SN_id_on                "id-on"
+#define NID_id_on               264
+#define OBJ_id_on               OBJ_id_pkix,8L
+
+#define SN_id_pda               "id-pda"
+#define NID_id_pda              265
+#define OBJ_id_pda              OBJ_id_pkix,9L
+
+#define SN_id_aca               "id-aca"
+#define NID_id_aca              266
+#define OBJ_id_aca              OBJ_id_pkix,10L
+
+#define SN_id_qcs               "id-qcs"
+#define NID_id_qcs              267
+#define OBJ_id_qcs              OBJ_id_pkix,11L
+
+#define SN_id_cct               "id-cct"
+#define NID_id_cct              268
+#define OBJ_id_cct              OBJ_id_pkix,12L
+
+#define SN_id_ppl               "id-ppl"
+#define NID_id_ppl              662
+#define OBJ_id_ppl              OBJ_id_pkix,21L
+
+#define SN_id_ad                "id-ad"
+#define NID_id_ad               176
+#define OBJ_id_ad               OBJ_id_pkix,48L
+
+#define SN_id_pkix1_explicit_88         "id-pkix1-explicit-88"
+#define NID_id_pkix1_explicit_88                269
+#define OBJ_id_pkix1_explicit_88                OBJ_id_pkix_mod,1L
+
+#define SN_id_pkix1_implicit_88         "id-pkix1-implicit-88"
+#define NID_id_pkix1_implicit_88                270
+#define OBJ_id_pkix1_implicit_88                OBJ_id_pkix_mod,2L
+
+#define SN_id_pkix1_explicit_93         "id-pkix1-explicit-93"
+#define NID_id_pkix1_explicit_93                271
+#define OBJ_id_pkix1_explicit_93                OBJ_id_pkix_mod,3L
+
+#define SN_id_pkix1_implicit_93         "id-pkix1-implicit-93"
+#define NID_id_pkix1_implicit_93                272
+#define OBJ_id_pkix1_implicit_93                OBJ_id_pkix_mod,4L
+
+#define SN_id_mod_crmf          "id-mod-crmf"
+#define NID_id_mod_crmf         273
+#define OBJ_id_mod_crmf         OBJ_id_pkix_mod,5L
+
+#define SN_id_mod_cmc           "id-mod-cmc"
+#define NID_id_mod_cmc          274
+#define OBJ_id_mod_cmc          OBJ_id_pkix_mod,6L
+
+#define SN_id_mod_kea_profile_88                "id-mod-kea-profile-88"
+#define NID_id_mod_kea_profile_88               275
+#define OBJ_id_mod_kea_profile_88               OBJ_id_pkix_mod,7L
+
+#define SN_id_mod_kea_profile_93                "id-mod-kea-profile-93"
+#define NID_id_mod_kea_profile_93               276
+#define OBJ_id_mod_kea_profile_93               OBJ_id_pkix_mod,8L
+
+#define SN_id_mod_cmp           "id-mod-cmp"
+#define NID_id_mod_cmp          277
+#define OBJ_id_mod_cmp          OBJ_id_pkix_mod,9L
+
+#define SN_id_mod_qualified_cert_88             "id-mod-qualified-cert-88"
+#define NID_id_mod_qualified_cert_88            278
+#define OBJ_id_mod_qualified_cert_88            OBJ_id_pkix_mod,10L
+
+#define SN_id_mod_qualified_cert_93             "id-mod-qualified-cert-93"
+#define NID_id_mod_qualified_cert_93            279
+#define OBJ_id_mod_qualified_cert_93            OBJ_id_pkix_mod,11L
+
+#define SN_id_mod_attribute_cert                "id-mod-attribute-cert"
+#define NID_id_mod_attribute_cert               280
+#define OBJ_id_mod_attribute_cert               OBJ_id_pkix_mod,12L
+
+#define SN_id_mod_timestamp_protocol            "id-mod-timestamp-protocol"
+#define NID_id_mod_timestamp_protocol           281
+#define OBJ_id_mod_timestamp_protocol           OBJ_id_pkix_mod,13L
+
+#define SN_id_mod_ocsp          "id-mod-ocsp"
+#define NID_id_mod_ocsp         282
+#define OBJ_id_mod_ocsp         OBJ_id_pkix_mod,14L
+
+#define SN_id_mod_dvcs          "id-mod-dvcs"
+#define NID_id_mod_dvcs         283
+#define OBJ_id_mod_dvcs         OBJ_id_pkix_mod,15L
+
+#define SN_id_mod_cmp2000               "id-mod-cmp2000"
+#define NID_id_mod_cmp2000              284
+#define OBJ_id_mod_cmp2000              OBJ_id_pkix_mod,16L
+
+#define SN_info_access          "authorityInfoAccess"
+#define LN_info_access          "Authority Information Access"
+#define NID_info_access         177
+#define OBJ_info_access         OBJ_id_pe,1L
+
+#define SN_biometricInfo                "biometricInfo"
+#define LN_biometricInfo                "Biometric Info"
+#define NID_biometricInfo               285
+#define OBJ_biometricInfo               OBJ_id_pe,2L
+
+#define SN_qcStatements         "qcStatements"
+#define NID_qcStatements                286
+#define OBJ_qcStatements                OBJ_id_pe,3L
+
+#define SN_ac_auditEntity               "ac-auditEntity"
+#define NID_ac_auditEntity              287
+#define OBJ_ac_auditEntity              OBJ_id_pe,4L
+
+#define SN_ac_targeting         "ac-targeting"
+#define NID_ac_targeting                288
+#define OBJ_ac_targeting                OBJ_id_pe,5L
+
+#define SN_aaControls           "aaControls"
+#define NID_aaControls          289
+#define OBJ_aaControls          OBJ_id_pe,6L
+
+#define SN_sbgp_ipAddrBlock             "sbgp-ipAddrBlock"
+#define NID_sbgp_ipAddrBlock            290
+#define OBJ_sbgp_ipAddrBlock            OBJ_id_pe,7L
+
+#define SN_sbgp_autonomousSysNum                "sbgp-autonomousSysNum"
+#define NID_sbgp_autonomousSysNum               291
+#define OBJ_sbgp_autonomousSysNum               OBJ_id_pe,8L
+
+#define SN_sbgp_routerIdentifier                "sbgp-routerIdentifier"
+#define NID_sbgp_routerIdentifier               292
+#define OBJ_sbgp_routerIdentifier               OBJ_id_pe,9L
+
+#define SN_ac_proxying          "ac-proxying"
+#define NID_ac_proxying         397
+#define OBJ_ac_proxying         OBJ_id_pe,10L
+
+#define SN_sinfo_access         "subjectInfoAccess"
+#define LN_sinfo_access         "Subject Information Access"
+#define NID_sinfo_access                398
+#define OBJ_sinfo_access                OBJ_id_pe,11L
+
+#define SN_proxyCertInfo                "proxyCertInfo"
+#define LN_proxyCertInfo                "Proxy Certificate Information"
+#define NID_proxyCertInfo               663
+#define OBJ_proxyCertInfo               OBJ_id_pe,14L
+
+#define SN_id_qt_cps            "id-qt-cps"
+#define LN_id_qt_cps            "Policy Qualifier CPS"
+#define NID_id_qt_cps           164
+#define OBJ_id_qt_cps           OBJ_id_qt,1L
+
+#define SN_id_qt_unotice                "id-qt-unotice"
+#define LN_id_qt_unotice                "Policy Qualifier User Notice"
+#define NID_id_qt_unotice               165
+#define OBJ_id_qt_unotice               OBJ_id_qt,2L
+
+#define SN_textNotice           "textNotice"
+#define NID_textNotice          293
+#define OBJ_textNotice          OBJ_id_qt,3L
+
+#define SN_server_auth          "serverAuth"
+#define LN_server_auth          "TLS Web Server Authentication"
+#define NID_server_auth         129
+#define OBJ_server_auth         OBJ_id_kp,1L
+
+#define SN_client_auth          "clientAuth"
+#define LN_client_auth          "TLS Web Client Authentication"
+#define NID_client_auth         130
+#define OBJ_client_auth         OBJ_id_kp,2L
+
+#define SN_code_sign            "codeSigning"
+#define LN_code_sign            "Code Signing"
+#define NID_code_sign           131
+#define OBJ_code_sign           OBJ_id_kp,3L
+
+#define SN_email_protect                "emailProtection"
+#define LN_email_protect                "E-mail Protection"
+#define NID_email_protect               132
+#define OBJ_email_protect               OBJ_id_kp,4L
+
+#define SN_ipsecEndSystem               "ipsecEndSystem"
+#define LN_ipsecEndSystem               "IPSec End System"
+#define NID_ipsecEndSystem              294
+#define OBJ_ipsecEndSystem              OBJ_id_kp,5L
+
+#define SN_ipsecTunnel          "ipsecTunnel"
+#define LN_ipsecTunnel          "IPSec Tunnel"
+#define NID_ipsecTunnel         295
+#define OBJ_ipsecTunnel         OBJ_id_kp,6L
+
+#define SN_ipsecUser            "ipsecUser"
+#define LN_ipsecUser            "IPSec User"
+#define NID_ipsecUser           296
+#define OBJ_ipsecUser           OBJ_id_kp,7L
+
+#define SN_time_stamp           "timeStamping"
+#define LN_time_stamp           "Time Stamping"
+#define NID_time_stamp          133
+#define OBJ_time_stamp          OBJ_id_kp,8L
+
+#define SN_OCSP_sign            "OCSPSigning"
+#define LN_OCSP_sign            "OCSP Signing"
+#define NID_OCSP_sign           180
+#define OBJ_OCSP_sign           OBJ_id_kp,9L
+
+#define SN_dvcs         "DVCS"
+#define LN_dvcs         "dvcs"
+#define NID_dvcs                297
+#define OBJ_dvcs                OBJ_id_kp,10L
+
+#define SN_id_it_caProtEncCert          "id-it-caProtEncCert"
+#define NID_id_it_caProtEncCert         298
+#define OBJ_id_it_caProtEncCert         OBJ_id_it,1L
+
+#define SN_id_it_signKeyPairTypes               "id-it-signKeyPairTypes"
+#define NID_id_it_signKeyPairTypes              299
+#define OBJ_id_it_signKeyPairTypes              OBJ_id_it,2L
+
+#define SN_id_it_encKeyPairTypes                "id-it-encKeyPairTypes"
+#define NID_id_it_encKeyPairTypes               300
+#define OBJ_id_it_encKeyPairTypes               OBJ_id_it,3L
+
+#define SN_id_it_preferredSymmAlg               "id-it-preferredSymmAlg"
+#define NID_id_it_preferredSymmAlg              301
+#define OBJ_id_it_preferredSymmAlg              OBJ_id_it,4L
+
+#define SN_id_it_caKeyUpdateInfo                "id-it-caKeyUpdateInfo"
+#define NID_id_it_caKeyUpdateInfo               302
+#define OBJ_id_it_caKeyUpdateInfo               OBJ_id_it,5L
+
+#define SN_id_it_currentCRL             "id-it-currentCRL"
+#define NID_id_it_currentCRL            303
+#define OBJ_id_it_currentCRL            OBJ_id_it,6L
+
+#define SN_id_it_unsupportedOIDs                "id-it-unsupportedOIDs"
+#define NID_id_it_unsupportedOIDs               304
+#define OBJ_id_it_unsupportedOIDs               OBJ_id_it,7L
+
+#define SN_id_it_subscriptionRequest            "id-it-subscriptionRequest"
+#define NID_id_it_subscriptionRequest           305
+#define OBJ_id_it_subscriptionRequest           OBJ_id_it,8L
+
+#define SN_id_it_subscriptionResponse           "id-it-subscriptionResponse"
+#define NID_id_it_subscriptionResponse          306
+#define OBJ_id_it_subscriptionResponse          OBJ_id_it,9L
+
+#define SN_id_it_keyPairParamReq                "id-it-keyPairParamReq"
+#define NID_id_it_keyPairParamReq               307
+#define OBJ_id_it_keyPairParamReq               OBJ_id_it,10L
+
+#define SN_id_it_keyPairParamRep                "id-it-keyPairParamRep"
+#define NID_id_it_keyPairParamRep               308
+#define OBJ_id_it_keyPairParamRep               OBJ_id_it,11L
+
+#define SN_id_it_revPassphrase          "id-it-revPassphrase"
+#define NID_id_it_revPassphrase         309
+#define OBJ_id_it_revPassphrase         OBJ_id_it,12L
+
+#define SN_id_it_implicitConfirm                "id-it-implicitConfirm"
+#define NID_id_it_implicitConfirm               310
+#define OBJ_id_it_implicitConfirm               OBJ_id_it,13L
+
+#define SN_id_it_confirmWaitTime                "id-it-confirmWaitTime"
+#define NID_id_it_confirmWaitTime               311
+#define OBJ_id_it_confirmWaitTime               OBJ_id_it,14L
+
+#define SN_id_it_origPKIMessage         "id-it-origPKIMessage"
+#define NID_id_it_origPKIMessage                312
+#define OBJ_id_it_origPKIMessage                OBJ_id_it,15L
+
+#define SN_id_it_suppLangTags           "id-it-suppLangTags"
+#define NID_id_it_suppLangTags          784
+#define OBJ_id_it_suppLangTags          OBJ_id_it,16L
+
+#define SN_id_regCtrl           "id-regCtrl"
+#define NID_id_regCtrl          313
+#define OBJ_id_regCtrl          OBJ_id_pkip,1L
+
+#define SN_id_regInfo           "id-regInfo"
+#define NID_id_regInfo          314
+#define OBJ_id_regInfo          OBJ_id_pkip,2L
+
+#define SN_id_regCtrl_regToken          "id-regCtrl-regToken"
+#define NID_id_regCtrl_regToken         315
+#define OBJ_id_regCtrl_regToken         OBJ_id_regCtrl,1L
+
+#define SN_id_regCtrl_authenticator             "id-regCtrl-authenticator"
+#define NID_id_regCtrl_authenticator            316
+#define OBJ_id_regCtrl_authenticator            OBJ_id_regCtrl,2L
+
+#define SN_id_regCtrl_pkiPublicationInfo                "id-regCtrl-pkiPublicationInfo"
+#define NID_id_regCtrl_pkiPublicationInfo               317
+#define OBJ_id_regCtrl_pkiPublicationInfo               OBJ_id_regCtrl,3L
+
+#define SN_id_regCtrl_pkiArchiveOptions         "id-regCtrl-pkiArchiveOptions"
+#define NID_id_regCtrl_pkiArchiveOptions                318
+#define OBJ_id_regCtrl_pkiArchiveOptions                OBJ_id_regCtrl,4L
+
+#define SN_id_regCtrl_oldCertID         "id-regCtrl-oldCertID"
+#define NID_id_regCtrl_oldCertID                319
+#define OBJ_id_regCtrl_oldCertID                OBJ_id_regCtrl,5L
+
+#define SN_id_regCtrl_protocolEncrKey           "id-regCtrl-protocolEncrKey"
+#define NID_id_regCtrl_protocolEncrKey          320
+#define OBJ_id_regCtrl_protocolEncrKey          OBJ_id_regCtrl,6L
+
+#define SN_id_regInfo_utf8Pairs         "id-regInfo-utf8Pairs"
+#define NID_id_regInfo_utf8Pairs                321
+#define OBJ_id_regInfo_utf8Pairs                OBJ_id_regInfo,1L
+
+#define SN_id_regInfo_certReq           "id-regInfo-certReq"
+#define NID_id_regInfo_certReq          322
+#define OBJ_id_regInfo_certReq          OBJ_id_regInfo,2L
+
+#define SN_id_alg_des40         "id-alg-des40"
+#define NID_id_alg_des40                323
+#define OBJ_id_alg_des40                OBJ_id_alg,1L
+
+#define SN_id_alg_noSignature           "id-alg-noSignature"
+#define NID_id_alg_noSignature          324
+#define OBJ_id_alg_noSignature          OBJ_id_alg,2L
+
+#define SN_id_alg_dh_sig_hmac_sha1              "id-alg-dh-sig-hmac-sha1"
+#define NID_id_alg_dh_sig_hmac_sha1             325
+#define OBJ_id_alg_dh_sig_hmac_sha1             OBJ_id_alg,3L
+
+#define SN_id_alg_dh_pop                "id-alg-dh-pop"
+#define NID_id_alg_dh_pop               326
+#define OBJ_id_alg_dh_pop               OBJ_id_alg,4L
+
+#define SN_id_cmc_statusInfo            "id-cmc-statusInfo"
+#define NID_id_cmc_statusInfo           327
+#define OBJ_id_cmc_statusInfo           OBJ_id_cmc,1L
+
+#define SN_id_cmc_identification                "id-cmc-identification"
+#define NID_id_cmc_identification               328
+#define OBJ_id_cmc_identification               OBJ_id_cmc,2L
+
+#define SN_id_cmc_identityProof         "id-cmc-identityProof"
+#define NID_id_cmc_identityProof                329
+#define OBJ_id_cmc_identityProof                OBJ_id_cmc,3L
+
+#define SN_id_cmc_dataReturn            "id-cmc-dataReturn"
+#define NID_id_cmc_dataReturn           330
+#define OBJ_id_cmc_dataReturn           OBJ_id_cmc,4L
+
+#define SN_id_cmc_transactionId         "id-cmc-transactionId"
+#define NID_id_cmc_transactionId                331
+#define OBJ_id_cmc_transactionId                OBJ_id_cmc,5L
+
+#define SN_id_cmc_senderNonce           "id-cmc-senderNonce"
+#define NID_id_cmc_senderNonce          332
+#define OBJ_id_cmc_senderNonce          OBJ_id_cmc,6L
+
+#define SN_id_cmc_recipientNonce                "id-cmc-recipientNonce"
+#define NID_id_cmc_recipientNonce               333
+#define OBJ_id_cmc_recipientNonce               OBJ_id_cmc,7L
+
+#define SN_id_cmc_addExtensions         "id-cmc-addExtensions"
+#define NID_id_cmc_addExtensions                334
+#define OBJ_id_cmc_addExtensions                OBJ_id_cmc,8L
+
+#define SN_id_cmc_encryptedPOP          "id-cmc-encryptedPOP"
+#define NID_id_cmc_encryptedPOP         335
+#define OBJ_id_cmc_encryptedPOP         OBJ_id_cmc,9L
+
+#define SN_id_cmc_decryptedPOP          "id-cmc-decryptedPOP"
+#define NID_id_cmc_decryptedPOP         336
+#define OBJ_id_cmc_decryptedPOP         OBJ_id_cmc,10L
+
+#define SN_id_cmc_lraPOPWitness         "id-cmc-lraPOPWitness"
+#define NID_id_cmc_lraPOPWitness                337
+#define OBJ_id_cmc_lraPOPWitness                OBJ_id_cmc,11L
+
+#define SN_id_cmc_getCert               "id-cmc-getCert"
+#define NID_id_cmc_getCert              338
+#define OBJ_id_cmc_getCert              OBJ_id_cmc,15L
+
+#define SN_id_cmc_getCRL                "id-cmc-getCRL"
+#define NID_id_cmc_getCRL               339
+#define OBJ_id_cmc_getCRL               OBJ_id_cmc,16L
+
+#define SN_id_cmc_revokeRequest         "id-cmc-revokeRequest"
+#define NID_id_cmc_revokeRequest                340
+#define OBJ_id_cmc_revokeRequest                OBJ_id_cmc,17L
+
+#define SN_id_cmc_regInfo               "id-cmc-regInfo"
+#define NID_id_cmc_regInfo              341
+#define OBJ_id_cmc_regInfo              OBJ_id_cmc,18L
+
+#define SN_id_cmc_responseInfo          "id-cmc-responseInfo"
+#define NID_id_cmc_responseInfo         342
+#define OBJ_id_cmc_responseInfo         OBJ_id_cmc,19L
+
+#define SN_id_cmc_queryPending          "id-cmc-queryPending"
+#define NID_id_cmc_queryPending         343
+#define OBJ_id_cmc_queryPending         OBJ_id_cmc,21L
+
+#define SN_id_cmc_popLinkRandom         "id-cmc-popLinkRandom"
+#define NID_id_cmc_popLinkRandom                344
+#define OBJ_id_cmc_popLinkRandom                OBJ_id_cmc,22L
+
+#define SN_id_cmc_popLinkWitness                "id-cmc-popLinkWitness"
+#define NID_id_cmc_popLinkWitness               345
+#define OBJ_id_cmc_popLinkWitness               OBJ_id_cmc,23L
+
+#define SN_id_cmc_confirmCertAcceptance         "id-cmc-confirmCertAcceptance"
+#define NID_id_cmc_confirmCertAcceptance                346
+#define OBJ_id_cmc_confirmCertAcceptance                OBJ_id_cmc,24L
+
+#define SN_id_on_personalData           "id-on-personalData"
+#define NID_id_on_personalData          347
+#define OBJ_id_on_personalData          OBJ_id_on,1L
+
+#define SN_id_on_permanentIdentifier            "id-on-permanentIdentifier"
+#define LN_id_on_permanentIdentifier            "Permanent Identifier"
+#define NID_id_on_permanentIdentifier           858
+#define OBJ_id_on_permanentIdentifier           OBJ_id_on,3L
+
+#define SN_id_pda_dateOfBirth           "id-pda-dateOfBirth"
+#define NID_id_pda_dateOfBirth          348
+#define OBJ_id_pda_dateOfBirth          OBJ_id_pda,1L
+
+#define SN_id_pda_placeOfBirth          "id-pda-placeOfBirth"
+#define NID_id_pda_placeOfBirth         349
+#define OBJ_id_pda_placeOfBirth         OBJ_id_pda,2L
+
+#define SN_id_pda_gender                "id-pda-gender"
+#define NID_id_pda_gender               351
+#define OBJ_id_pda_gender               OBJ_id_pda,3L
+
+#define SN_id_pda_countryOfCitizenship          "id-pda-countryOfCitizenship"
+#define NID_id_pda_countryOfCitizenship         352
+#define OBJ_id_pda_countryOfCitizenship         OBJ_id_pda,4L
+
+#define SN_id_pda_countryOfResidence            "id-pda-countryOfResidence"
+#define NID_id_pda_countryOfResidence           353
+#define OBJ_id_pda_countryOfResidence           OBJ_id_pda,5L
+
+#define SN_id_aca_authenticationInfo            "id-aca-authenticationInfo"
+#define NID_id_aca_authenticationInfo           354
+#define OBJ_id_aca_authenticationInfo           OBJ_id_aca,1L
+
+#define SN_id_aca_accessIdentity                "id-aca-accessIdentity"
+#define NID_id_aca_accessIdentity               355
+#define OBJ_id_aca_accessIdentity               OBJ_id_aca,2L
+
+#define SN_id_aca_chargingIdentity              "id-aca-chargingIdentity"
+#define NID_id_aca_chargingIdentity             356
+#define OBJ_id_aca_chargingIdentity             OBJ_id_aca,3L
+
+#define SN_id_aca_group         "id-aca-group"
+#define NID_id_aca_group                357
+#define OBJ_id_aca_group                OBJ_id_aca,4L
+
+#define SN_id_aca_role          "id-aca-role"
+#define NID_id_aca_role         358
+#define OBJ_id_aca_role         OBJ_id_aca,5L
+
+#define SN_id_aca_encAttrs              "id-aca-encAttrs"
+#define NID_id_aca_encAttrs             399
+#define OBJ_id_aca_encAttrs             OBJ_id_aca,6L
+
+#define SN_id_qcs_pkixQCSyntax_v1               "id-qcs-pkixQCSyntax-v1"
+#define NID_id_qcs_pkixQCSyntax_v1              359
+#define OBJ_id_qcs_pkixQCSyntax_v1              OBJ_id_qcs,1L
+
+#define SN_id_cct_crs           "id-cct-crs"
+#define NID_id_cct_crs          360
+#define OBJ_id_cct_crs          OBJ_id_cct,1L
+
+#define SN_id_cct_PKIData               "id-cct-PKIData"
+#define NID_id_cct_PKIData              361
+#define OBJ_id_cct_PKIData              OBJ_id_cct,2L
+
+#define SN_id_cct_PKIResponse           "id-cct-PKIResponse"
+#define NID_id_cct_PKIResponse          362
+#define OBJ_id_cct_PKIResponse          OBJ_id_cct,3L
+
+#define SN_id_ppl_anyLanguage           "id-ppl-anyLanguage"
+#define LN_id_ppl_anyLanguage           "Any language"
+#define NID_id_ppl_anyLanguage          664
+#define OBJ_id_ppl_anyLanguage          OBJ_id_ppl,0L
+
+#define SN_id_ppl_inheritAll            "id-ppl-inheritAll"
+#define LN_id_ppl_inheritAll            "Inherit all"
+#define NID_id_ppl_inheritAll           665
+#define OBJ_id_ppl_inheritAll           OBJ_id_ppl,1L
+
+#define SN_Independent          "id-ppl-independent"
+#define LN_Independent          "Independent"
+#define NID_Independent         667
+#define OBJ_Independent         OBJ_id_ppl,2L
+
+#define SN_ad_OCSP              "OCSP"
+#define LN_ad_OCSP              "OCSP"
+#define NID_ad_OCSP             178
+#define OBJ_ad_OCSP             OBJ_id_ad,1L
+
+#define SN_ad_ca_issuers                "caIssuers"
+#define LN_ad_ca_issuers                "CA Issuers"
+#define NID_ad_ca_issuers               179
+#define OBJ_ad_ca_issuers               OBJ_id_ad,2L
+
+#define SN_ad_timeStamping              "ad_timestamping"
+#define LN_ad_timeStamping              "AD Time Stamping"
+#define NID_ad_timeStamping             363
+#define OBJ_ad_timeStamping             OBJ_id_ad,3L
+
+#define SN_ad_dvcs              "AD_DVCS"
+#define LN_ad_dvcs              "ad dvcs"
+#define NID_ad_dvcs             364
+#define OBJ_ad_dvcs             OBJ_id_ad,4L
+
+#define SN_caRepository         "caRepository"
+#define LN_caRepository         "CA Repository"
+#define NID_caRepository                785
+#define OBJ_caRepository                OBJ_id_ad,5L
+
+#define OBJ_id_pkix_OCSP                OBJ_ad_OCSP
+
+#define SN_id_pkix_OCSP_basic           "basicOCSPResponse"
+#define LN_id_pkix_OCSP_basic           "Basic OCSP Response"
+#define NID_id_pkix_OCSP_basic          365
+#define OBJ_id_pkix_OCSP_basic          OBJ_id_pkix_OCSP,1L
+
+#define SN_id_pkix_OCSP_Nonce           "Nonce"
+#define LN_id_pkix_OCSP_Nonce           "OCSP Nonce"
+#define NID_id_pkix_OCSP_Nonce          366
+#define OBJ_id_pkix_OCSP_Nonce          OBJ_id_pkix_OCSP,2L
+
+#define SN_id_pkix_OCSP_CrlID           "CrlID"
+#define LN_id_pkix_OCSP_CrlID           "OCSP CRL ID"
+#define NID_id_pkix_OCSP_CrlID          367
+#define OBJ_id_pkix_OCSP_CrlID          OBJ_id_pkix_OCSP,3L
+
+#define SN_id_pkix_OCSP_acceptableResponses             "acceptableResponses"
+#define LN_id_pkix_OCSP_acceptableResponses             "Acceptable OCSP Responses"
+#define NID_id_pkix_OCSP_acceptableResponses            368
+#define OBJ_id_pkix_OCSP_acceptableResponses            OBJ_id_pkix_OCSP,4L
+
+#define SN_id_pkix_OCSP_noCheck         "noCheck"
+#define LN_id_pkix_OCSP_noCheck         "OCSP No Check"
+#define NID_id_pkix_OCSP_noCheck                369
+#define OBJ_id_pkix_OCSP_noCheck                OBJ_id_pkix_OCSP,5L
+
+#define SN_id_pkix_OCSP_archiveCutoff           "archiveCutoff"
+#define LN_id_pkix_OCSP_archiveCutoff           "OCSP Archive Cutoff"
+#define NID_id_pkix_OCSP_archiveCutoff          370
+#define OBJ_id_pkix_OCSP_archiveCutoff          OBJ_id_pkix_OCSP,6L
+
+#define SN_id_pkix_OCSP_serviceLocator          "serviceLocator"
+#define LN_id_pkix_OCSP_serviceLocator          "OCSP Service Locator"
+#define NID_id_pkix_OCSP_serviceLocator         371
+#define OBJ_id_pkix_OCSP_serviceLocator         OBJ_id_pkix_OCSP,7L
+
+#define SN_id_pkix_OCSP_extendedStatus          "extendedStatus"
+#define LN_id_pkix_OCSP_extendedStatus          "Extended OCSP Status"
+#define NID_id_pkix_OCSP_extendedStatus         372
+#define OBJ_id_pkix_OCSP_extendedStatus         OBJ_id_pkix_OCSP,8L
+
+#define SN_id_pkix_OCSP_valid           "valid"
+#define NID_id_pkix_OCSP_valid          373
+#define OBJ_id_pkix_OCSP_valid          OBJ_id_pkix_OCSP,9L
+
+#define SN_id_pkix_OCSP_path            "path"
+#define NID_id_pkix_OCSP_path           374
+#define OBJ_id_pkix_OCSP_path           OBJ_id_pkix_OCSP,10L
+
+#define SN_id_pkix_OCSP_trustRoot               "trustRoot"
+#define LN_id_pkix_OCSP_trustRoot               "Trust Root"
+#define NID_id_pkix_OCSP_trustRoot              375
+#define OBJ_id_pkix_OCSP_trustRoot              OBJ_id_pkix_OCSP,11L
+
+#define SN_algorithm            "algorithm"
+#define LN_algorithm            "algorithm"
+#define NID_algorithm           376
+#define OBJ_algorithm           1L,3L,14L,3L,2L
+
+#define SN_md5WithRSA           "RSA-NP-MD5"
+#define LN_md5WithRSA           "md5WithRSA"
+#define NID_md5WithRSA          104
+#define OBJ_md5WithRSA          OBJ_algorithm,3L
+
+#define SN_des_ecb              "DES-ECB"
+#define LN_des_ecb              "des-ecb"
+#define NID_des_ecb             29
+#define OBJ_des_ecb             OBJ_algorithm,6L
+
+#define SN_des_cbc              "DES-CBC"
+#define LN_des_cbc              "des-cbc"
+#define NID_des_cbc             31
+#define OBJ_des_cbc             OBJ_algorithm,7L
+
+#define SN_des_ofb64            "DES-OFB"
+#define LN_des_ofb64            "des-ofb"
+#define NID_des_ofb64           45
+#define OBJ_des_ofb64           OBJ_algorithm,8L
+
+#define SN_des_cfb64            "DES-CFB"
+#define LN_des_cfb64            "des-cfb"
+#define NID_des_cfb64           30
+#define OBJ_des_cfb64           OBJ_algorithm,9L
+
+#define SN_rsaSignature         "rsaSignature"
+#define NID_rsaSignature                377
+#define OBJ_rsaSignature                OBJ_algorithm,11L
+
+#define SN_dsa_2                "DSA-old"
+#define LN_dsa_2                "dsaEncryption-old"
+#define NID_dsa_2               67
+#define OBJ_dsa_2               OBJ_algorithm,12L
+
+#define SN_dsaWithSHA           "DSA-SHA"
+#define LN_dsaWithSHA           "dsaWithSHA"
+#define NID_dsaWithSHA          66
+#define OBJ_dsaWithSHA          OBJ_algorithm,13L
+
+#define SN_shaWithRSAEncryption         "RSA-SHA"
+#define LN_shaWithRSAEncryption         "shaWithRSAEncryption"
+#define NID_shaWithRSAEncryption                42
+#define OBJ_shaWithRSAEncryption                OBJ_algorithm,15L
+
+#define SN_des_ede_ecb          "DES-EDE"
+#define LN_des_ede_ecb          "des-ede"
+#define NID_des_ede_ecb         32
+#define OBJ_des_ede_ecb         OBJ_algorithm,17L
+
+#define SN_des_ede3_ecb         "DES-EDE3"
+#define LN_des_ede3_ecb         "des-ede3"
+#define NID_des_ede3_ecb                33
+
+#define SN_des_ede_cbc          "DES-EDE-CBC"
+#define LN_des_ede_cbc          "des-ede-cbc"
+#define NID_des_ede_cbc         43
+
+#define SN_des_ede_cfb64                "DES-EDE-CFB"
+#define LN_des_ede_cfb64                "des-ede-cfb"
+#define NID_des_ede_cfb64               60
+
+#define SN_des_ede3_cfb64               "DES-EDE3-CFB"
+#define LN_des_ede3_cfb64               "des-ede3-cfb"
+#define NID_des_ede3_cfb64              61
+
+#define SN_des_ede_ofb64                "DES-EDE-OFB"
+#define LN_des_ede_ofb64                "des-ede-ofb"
+#define NID_des_ede_ofb64               62
+
+#define SN_des_ede3_ofb64               "DES-EDE3-OFB"
+#define LN_des_ede3_ofb64               "des-ede3-ofb"
+#define NID_des_ede3_ofb64              63
+
+#define SN_desx_cbc             "DESX-CBC"
+#define LN_desx_cbc             "desx-cbc"
+#define NID_desx_cbc            80
+
+#define SN_sha          "SHA"
+#define LN_sha          "sha"
+#define NID_sha         41
+#define OBJ_sha         OBJ_algorithm,18L
+
+#define SN_sha1         "SHA1"
+#define LN_sha1         "sha1"
+#define NID_sha1                64
+#define OBJ_sha1                OBJ_algorithm,26L
+
+#define SN_dsaWithSHA1_2                "DSA-SHA1-old"
+#define LN_dsaWithSHA1_2                "dsaWithSHA1-old"
+#define NID_dsaWithSHA1_2               70
+#define OBJ_dsaWithSHA1_2               OBJ_algorithm,27L
+
+#define SN_sha1WithRSA          "RSA-SHA1-2"
+#define LN_sha1WithRSA          "sha1WithRSA"
+#define NID_sha1WithRSA         115
+#define OBJ_sha1WithRSA         OBJ_algorithm,29L
+
+#define SN_ripemd160            "RIPEMD160"
+#define LN_ripemd160            "ripemd160"
+#define NID_ripemd160           117
+#define OBJ_ripemd160           1L,3L,36L,3L,2L,1L
+
+#define SN_ripemd160WithRSA             "RSA-RIPEMD160"
+#define LN_ripemd160WithRSA             "ripemd160WithRSA"
+#define NID_ripemd160WithRSA            119
+#define OBJ_ripemd160WithRSA            1L,3L,36L,3L,3L,1L,2L
+
+#define SN_sxnet                "SXNetID"
+#define LN_sxnet                "Strong Extranet ID"
+#define NID_sxnet               143
+#define OBJ_sxnet               1L,3L,101L,1L,4L,1L
+
+#define SN_X500         "X500"
+#define LN_X500         "directory services (X.500)"
+#define NID_X500                11
+#define OBJ_X500                2L,5L
+
+#define SN_X509         "X509"
+#define NID_X509                12
+#define OBJ_X509                OBJ_X500,4L
+
+#define SN_commonName           "CN"
+#define LN_commonName           "commonName"
+#define NID_commonName          13
+#define OBJ_commonName          OBJ_X509,3L
+
+#define SN_surname              "SN"
+#define LN_surname              "surname"
+#define NID_surname             100
+#define OBJ_surname             OBJ_X509,4L
+
+#define LN_serialNumber         "serialNumber"
+#define NID_serialNumber                105
+#define OBJ_serialNumber                OBJ_X509,5L
+
+#define SN_countryName          "C"
+#define LN_countryName          "countryName"
+#define NID_countryName         14
+#define OBJ_countryName         OBJ_X509,6L
+
+#define SN_localityName         "L"
+#define LN_localityName         "localityName"
+#define NID_localityName                15
+#define OBJ_localityName                OBJ_X509,7L
+
+#define SN_stateOrProvinceName          "ST"
+#define LN_stateOrProvinceName          "stateOrProvinceName"
+#define NID_stateOrProvinceName         16
+#define OBJ_stateOrProvinceName         OBJ_X509,8L
+
+#define SN_streetAddress                "street"
+#define LN_streetAddress                "streetAddress"
+#define NID_streetAddress               660
+#define OBJ_streetAddress               OBJ_X509,9L
+
+#define SN_organizationName             "O"
+#define LN_organizationName             "organizationName"
+#define NID_organizationName            17
+#define OBJ_organizationName            OBJ_X509,10L
+
+#define SN_organizationalUnitName               "OU"
+#define LN_organizationalUnitName               "organizationalUnitName"
+#define NID_organizationalUnitName              18
+#define OBJ_organizationalUnitName              OBJ_X509,11L
+
+#define SN_title                "title"
+#define LN_title                "title"
+#define NID_title               106
+#define OBJ_title               OBJ_X509,12L
+
+#define LN_description          "description"
+#define NID_description         107
+#define OBJ_description         OBJ_X509,13L
+
+#define LN_searchGuide          "searchGuide"
+#define NID_searchGuide         859
+#define OBJ_searchGuide         OBJ_X509,14L
+
+#define LN_businessCategory             "businessCategory"
+#define NID_businessCategory            860
+#define OBJ_businessCategory            OBJ_X509,15L
+
+#define LN_postalAddress                "postalAddress"
+#define NID_postalAddress               861
+#define OBJ_postalAddress               OBJ_X509,16L
+
+#define LN_postalCode           "postalCode"
+#define NID_postalCode          661
+#define OBJ_postalCode          OBJ_X509,17L
+
+#define LN_postOfficeBox                "postOfficeBox"
+#define NID_postOfficeBox               862
+#define OBJ_postOfficeBox               OBJ_X509,18L
+
+#define LN_physicalDeliveryOfficeName           "physicalDeliveryOfficeName"
+#define NID_physicalDeliveryOfficeName          863
+#define OBJ_physicalDeliveryOfficeName          OBJ_X509,19L
+
+#define LN_telephoneNumber              "telephoneNumber"
+#define NID_telephoneNumber             864
+#define OBJ_telephoneNumber             OBJ_X509,20L
+
+#define LN_telexNumber          "telexNumber"
+#define NID_telexNumber         865
+#define OBJ_telexNumber         OBJ_X509,21L
+
+#define LN_teletexTerminalIdentifier            "teletexTerminalIdentifier"
+#define NID_teletexTerminalIdentifier           866
+#define OBJ_teletexTerminalIdentifier           OBJ_X509,22L
+
+#define LN_facsimileTelephoneNumber             "facsimileTelephoneNumber"
+#define NID_facsimileTelephoneNumber            867
+#define OBJ_facsimileTelephoneNumber            OBJ_X509,23L
+
+#define LN_x121Address          "x121Address"
+#define NID_x121Address         868
+#define OBJ_x121Address         OBJ_X509,24L
+
+#define LN_internationaliSDNNumber              "internationaliSDNNumber"
+#define NID_internationaliSDNNumber             869
+#define OBJ_internationaliSDNNumber             OBJ_X509,25L
+
+#define LN_registeredAddress            "registeredAddress"
+#define NID_registeredAddress           870
+#define OBJ_registeredAddress           OBJ_X509,26L
+
+#define LN_destinationIndicator         "destinationIndicator"
+#define NID_destinationIndicator                871
+#define OBJ_destinationIndicator                OBJ_X509,27L
+
+#define LN_preferredDeliveryMethod              "preferredDeliveryMethod"
+#define NID_preferredDeliveryMethod             872
+#define OBJ_preferredDeliveryMethod             OBJ_X509,28L
+
+#define LN_presentationAddress          "presentationAddress"
+#define NID_presentationAddress         873
+#define OBJ_presentationAddress         OBJ_X509,29L
+
+#define LN_supportedApplicationContext          "supportedApplicationContext"
+#define NID_supportedApplicationContext         874
+#define OBJ_supportedApplicationContext         OBJ_X509,30L
+
+#define SN_member               "member"
+#define NID_member              875
+#define OBJ_member              OBJ_X509,31L
+
+#define SN_owner                "owner"
+#define NID_owner               876
+#define OBJ_owner               OBJ_X509,32L
+
+#define LN_roleOccupant         "roleOccupant"
+#define NID_roleOccupant                877
+#define OBJ_roleOccupant                OBJ_X509,33L
+
+#define SN_seeAlso              "seeAlso"
+#define NID_seeAlso             878
+#define OBJ_seeAlso             OBJ_X509,34L
+
+#define LN_userPassword         "userPassword"
+#define NID_userPassword                879
+#define OBJ_userPassword                OBJ_X509,35L
+
+#define LN_userCertificate              "userCertificate"
+#define NID_userCertificate             880
+#define OBJ_userCertificate             OBJ_X509,36L
+
+#define LN_cACertificate                "cACertificate"
+#define NID_cACertificate               881
+#define OBJ_cACertificate               OBJ_X509,37L
+
+#define LN_authorityRevocationList              "authorityRevocationList"
+#define NID_authorityRevocationList             882
+#define OBJ_authorityRevocationList             OBJ_X509,38L
+
+#define LN_certificateRevocationList            "certificateRevocationList"
+#define NID_certificateRevocationList           883
+#define OBJ_certificateRevocationList           OBJ_X509,39L
+
+#define LN_crossCertificatePair         "crossCertificatePair"
+#define NID_crossCertificatePair                884
+#define OBJ_crossCertificatePair                OBJ_X509,40L
+
+#define SN_name         "name"
+#define LN_name         "name"
+#define NID_name                173
+#define OBJ_name                OBJ_X509,41L
+
+#define SN_givenName            "GN"
+#define LN_givenName            "givenName"
+#define NID_givenName           99
+#define OBJ_givenName           OBJ_X509,42L
+
+#define SN_initials             "initials"
+#define LN_initials             "initials"
+#define NID_initials            101
+#define OBJ_initials            OBJ_X509,43L
+
+#define LN_generationQualifier          "generationQualifier"
+#define NID_generationQualifier         509
+#define OBJ_generationQualifier         OBJ_X509,44L
+
+#define LN_x500UniqueIdentifier         "x500UniqueIdentifier"
+#define NID_x500UniqueIdentifier                503
+#define OBJ_x500UniqueIdentifier                OBJ_X509,45L
+
+#define SN_dnQualifier          "dnQualifier"
+#define LN_dnQualifier          "dnQualifier"
+#define NID_dnQualifier         174
+#define OBJ_dnQualifier         OBJ_X509,46L
+
+#define LN_enhancedSearchGuide          "enhancedSearchGuide"
+#define NID_enhancedSearchGuide         885
+#define OBJ_enhancedSearchGuide         OBJ_X509,47L
+
+#define LN_protocolInformation          "protocolInformation"
+#define NID_protocolInformation         886
+#define OBJ_protocolInformation         OBJ_X509,48L
+
+#define LN_distinguishedName            "distinguishedName"
+#define NID_distinguishedName           887
+#define OBJ_distinguishedName           OBJ_X509,49L
+
+#define LN_uniqueMember         "uniqueMember"
+#define NID_uniqueMember                888
+#define OBJ_uniqueMember                OBJ_X509,50L
+
+#define LN_houseIdentifier              "houseIdentifier"
+#define NID_houseIdentifier             889
+#define OBJ_houseIdentifier             OBJ_X509,51L
+
+#define LN_supportedAlgorithms          "supportedAlgorithms"
+#define NID_supportedAlgorithms         890
+#define OBJ_supportedAlgorithms         OBJ_X509,52L
+
+#define LN_deltaRevocationList          "deltaRevocationList"
+#define NID_deltaRevocationList         891
+#define OBJ_deltaRevocationList         OBJ_X509,53L
+
+#define SN_dmdName              "dmdName"
+#define NID_dmdName             892
+#define OBJ_dmdName             OBJ_X509,54L
+
+#define LN_pseudonym            "pseudonym"
+#define NID_pseudonym           510
+#define OBJ_pseudonym           OBJ_X509,65L
+
+#define SN_role         "role"
+#define LN_role         "role"
+#define NID_role                400
+#define OBJ_role                OBJ_X509,72L
+
+#define SN_X500algorithms               "X500algorithms"
+#define LN_X500algorithms               "directory services - algorithms"
+#define NID_X500algorithms              378
+#define OBJ_X500algorithms              OBJ_X500,8L
+
+#define SN_rsa          "RSA"
+#define LN_rsa          "rsa"
+#define NID_rsa         19
+#define OBJ_rsa         OBJ_X500algorithms,1L,1L
+
+#define SN_mdc2WithRSA          "RSA-MDC2"
+#define LN_mdc2WithRSA          "mdc2WithRSA"
+#define NID_mdc2WithRSA         96
+#define OBJ_mdc2WithRSA         OBJ_X500algorithms,3L,100L
+
+#define SN_mdc2         "MDC2"
+#define LN_mdc2         "mdc2"
+#define NID_mdc2                95
+#define OBJ_mdc2                OBJ_X500algorithms,3L,101L
+
+#define SN_id_ce                "id-ce"
+#define NID_id_ce               81
+#define OBJ_id_ce               OBJ_X500,29L
+
+#define SN_subject_directory_attributes         "subjectDirectoryAttributes"
+#define LN_subject_directory_attributes         "X509v3 Subject Directory Attributes"
+#define NID_subject_directory_attributes                769
+#define OBJ_subject_directory_attributes                OBJ_id_ce,9L
+
+#define SN_subject_key_identifier               "subjectKeyIdentifier"
+#define LN_subject_key_identifier               "X509v3 Subject Key Identifier"
+#define NID_subject_key_identifier              82
+#define OBJ_subject_key_identifier              OBJ_id_ce,14L
+
+#define SN_key_usage            "keyUsage"
+#define LN_key_usage            "X509v3 Key Usage"
+#define NID_key_usage           83
+#define OBJ_key_usage           OBJ_id_ce,15L
+
+#define SN_private_key_usage_period             "privateKeyUsagePeriod"
+#define LN_private_key_usage_period             "X509v3 Private Key Usage Period"
+#define NID_private_key_usage_period            84
+#define OBJ_private_key_usage_period            OBJ_id_ce,16L
+
+#define SN_subject_alt_name             "subjectAltName"
+#define LN_subject_alt_name             "X509v3 Subject Alternative Name"
+#define NID_subject_alt_name            85
+#define OBJ_subject_alt_name            OBJ_id_ce,17L
+
+#define SN_issuer_alt_name              "issuerAltName"
+#define LN_issuer_alt_name              "X509v3 Issuer Alternative Name"
+#define NID_issuer_alt_name             86
+#define OBJ_issuer_alt_name             OBJ_id_ce,18L
+
+#define SN_basic_constraints            "basicConstraints"
+#define LN_basic_constraints            "X509v3 Basic Constraints"
+#define NID_basic_constraints           87
+#define OBJ_basic_constraints           OBJ_id_ce,19L
+
+#define SN_crl_number           "crlNumber"
+#define LN_crl_number           "X509v3 CRL Number"
+#define NID_crl_number          88
+#define OBJ_crl_number          OBJ_id_ce,20L
+
+#define SN_crl_reason           "CRLReason"
+#define LN_crl_reason           "X509v3 CRL Reason Code"
+#define NID_crl_reason          141
+#define OBJ_crl_reason          OBJ_id_ce,21L
+
+#define SN_invalidity_date              "invalidityDate"
+#define LN_invalidity_date              "Invalidity Date"
+#define NID_invalidity_date             142
+#define OBJ_invalidity_date             OBJ_id_ce,24L
+
+#define SN_delta_crl            "deltaCRL"
+#define LN_delta_crl            "X509v3 Delta CRL Indicator"
+#define NID_delta_crl           140
+#define OBJ_delta_crl           OBJ_id_ce,27L
+
+#define SN_issuing_distribution_point           "issuingDistributionPoint"
+#define LN_issuing_distribution_point           "X509v3 Issuing Distrubution Point"
+#define NID_issuing_distribution_point          770
+#define OBJ_issuing_distribution_point          OBJ_id_ce,28L
+
+#define SN_certificate_issuer           "certificateIssuer"
+#define LN_certificate_issuer           "X509v3 Certificate Issuer"
+#define NID_certificate_issuer          771
+#define OBJ_certificate_issuer          OBJ_id_ce,29L
+
+#define SN_name_constraints             "nameConstraints"
+#define LN_name_constraints             "X509v3 Name Constraints"
+#define NID_name_constraints            666
+#define OBJ_name_constraints            OBJ_id_ce,30L
+
+#define SN_crl_distribution_points              "crlDistributionPoints"
+#define LN_crl_distribution_points              "X509v3 CRL Distribution Points"
+#define NID_crl_distribution_points             103
+#define OBJ_crl_distribution_points             OBJ_id_ce,31L
+
+#define SN_certificate_policies         "certificatePolicies"
+#define LN_certificate_policies         "X509v3 Certificate Policies"
+#define NID_certificate_policies                89
+#define OBJ_certificate_policies                OBJ_id_ce,32L
+
+#define SN_any_policy           "anyPolicy"
+#define LN_any_policy           "X509v3 Any Policy"
+#define NID_any_policy          746
+#define OBJ_any_policy          OBJ_certificate_policies,0L
+
+#define SN_policy_mappings              "policyMappings"
+#define LN_policy_mappings              "X509v3 Policy Mappings"
+#define NID_policy_mappings             747
+#define OBJ_policy_mappings             OBJ_id_ce,33L
+
+#define SN_authority_key_identifier             "authorityKeyIdentifier"
+#define LN_authority_key_identifier             "X509v3 Authority Key Identifier"
+#define NID_authority_key_identifier            90
+#define OBJ_authority_key_identifier            OBJ_id_ce,35L
+
+#define SN_policy_constraints           "policyConstraints"
+#define LN_policy_constraints           "X509v3 Policy Constraints"
+#define NID_policy_constraints          401
+#define OBJ_policy_constraints          OBJ_id_ce,36L
+
+#define SN_ext_key_usage                "extendedKeyUsage"
+#define LN_ext_key_usage                "X509v3 Extended Key Usage"
+#define NID_ext_key_usage               126
+#define OBJ_ext_key_usage               OBJ_id_ce,37L
+
+#define SN_freshest_crl         "freshestCRL"
+#define LN_freshest_crl         "X509v3 Freshest CRL"
+#define NID_freshest_crl                857
+#define OBJ_freshest_crl                OBJ_id_ce,46L
+
+#define SN_inhibit_any_policy           "inhibitAnyPolicy"
+#define LN_inhibit_any_policy           "X509v3 Inhibit Any Policy"
+#define NID_inhibit_any_policy          748
+#define OBJ_inhibit_any_policy          OBJ_id_ce,54L
+
+#define SN_target_information           "targetInformation"
+#define LN_target_information           "X509v3 AC Targeting"
+#define NID_target_information          402
+#define OBJ_target_information          OBJ_id_ce,55L
+
+#define SN_no_rev_avail         "noRevAvail"
+#define LN_no_rev_avail         "X509v3 No Revocation Available"
+#define NID_no_rev_avail                403
+#define OBJ_no_rev_avail                OBJ_id_ce,56L
+
+#define SN_anyExtendedKeyUsage          "anyExtendedKeyUsage"
+#define LN_anyExtendedKeyUsage          "Any Extended Key Usage"
+#define NID_anyExtendedKeyUsage         910
+#define OBJ_anyExtendedKeyUsage         OBJ_ext_key_usage,0L
+
+#define SN_netscape             "Netscape"
+#define LN_netscape             "Netscape Communications Corp."
+#define NID_netscape            57
+#define OBJ_netscape            2L,16L,840L,1L,113730L
+
+#define SN_netscape_cert_extension              "nsCertExt"
+#define LN_netscape_cert_extension              "Netscape Certificate Extension"
+#define NID_netscape_cert_extension             58
+#define OBJ_netscape_cert_extension             OBJ_netscape,1L
+
+#define SN_netscape_data_type           "nsDataType"
+#define LN_netscape_data_type           "Netscape Data Type"
+#define NID_netscape_data_type          59
+#define OBJ_netscape_data_type          OBJ_netscape,2L
+
+#define SN_netscape_cert_type           "nsCertType"
+#define LN_netscape_cert_type           "Netscape Cert Type"
+#define NID_netscape_cert_type          71
+#define OBJ_netscape_cert_type          OBJ_netscape_cert_extension,1L
+
+#define SN_netscape_base_url            "nsBaseUrl"
+#define LN_netscape_base_url            "Netscape Base Url"
+#define NID_netscape_base_url           72
+#define OBJ_netscape_base_url           OBJ_netscape_cert_extension,2L
+
+#define SN_netscape_revocation_url              "nsRevocationUrl"
+#define LN_netscape_revocation_url              "Netscape Revocation Url"
+#define NID_netscape_revocation_url             73
+#define OBJ_netscape_revocation_url             OBJ_netscape_cert_extension,3L
+
+#define SN_netscape_ca_revocation_url           "nsCaRevocationUrl"
+#define LN_netscape_ca_revocation_url           "Netscape CA Revocation Url"
+#define NID_netscape_ca_revocation_url          74
+#define OBJ_netscape_ca_revocation_url          OBJ_netscape_cert_extension,4L
+
+#define SN_netscape_renewal_url         "nsRenewalUrl"
+#define LN_netscape_renewal_url         "Netscape Renewal Url"
+#define NID_netscape_renewal_url                75
+#define OBJ_netscape_renewal_url                OBJ_netscape_cert_extension,7L
+
+#define SN_netscape_ca_policy_url               "nsCaPolicyUrl"
+#define LN_netscape_ca_policy_url               "Netscape CA Policy Url"
+#define NID_netscape_ca_policy_url              76
+#define OBJ_netscape_ca_policy_url              OBJ_netscape_cert_extension,8L
+
+#define SN_netscape_ssl_server_name             "nsSslServerName"
+#define LN_netscape_ssl_server_name             "Netscape SSL Server Name"
+#define NID_netscape_ssl_server_name            77
+#define OBJ_netscape_ssl_server_name            OBJ_netscape_cert_extension,12L
+
+#define SN_netscape_comment             "nsComment"
+#define LN_netscape_comment             "Netscape Comment"
+#define NID_netscape_comment            78
+#define OBJ_netscape_comment            OBJ_netscape_cert_extension,13L
+
+#define SN_netscape_cert_sequence               "nsCertSequence"
+#define LN_netscape_cert_sequence               "Netscape Certificate Sequence"
+#define NID_netscape_cert_sequence              79
+#define OBJ_netscape_cert_sequence              OBJ_netscape_data_type,5L
+
+#define SN_ns_sgc               "nsSGC"
+#define LN_ns_sgc               "Netscape Server Gated Crypto"
+#define NID_ns_sgc              139
+#define OBJ_ns_sgc              OBJ_netscape,4L,1L
+
+#define SN_org          "ORG"
+#define LN_org          "org"
+#define NID_org         379
+#define OBJ_org         OBJ_iso,3L
+
+#define SN_dod          "DOD"
+#define LN_dod          "dod"
+#define NID_dod         380
+#define OBJ_dod         OBJ_org,6L
+
+#define SN_iana         "IANA"
+#define LN_iana         "iana"
+#define NID_iana                381
+#define OBJ_iana                OBJ_dod,1L
+
+#define OBJ_internet            OBJ_iana
+
+#define SN_Directory            "directory"
+#define LN_Directory            "Directory"
+#define NID_Directory           382
+#define OBJ_Directory           OBJ_internet,1L
+
+#define SN_Management           "mgmt"
+#define LN_Management           "Management"
+#define NID_Management          383
+#define OBJ_Management          OBJ_internet,2L
+
+#define SN_Experimental         "experimental"
+#define LN_Experimental         "Experimental"
+#define NID_Experimental                384
+#define OBJ_Experimental                OBJ_internet,3L
+
+#define SN_Private              "private"
+#define LN_Private              "Private"
+#define NID_Private             385
+#define OBJ_Private             OBJ_internet,4L
+
+#define SN_Security             "security"
+#define LN_Security             "Security"
+#define NID_Security            386
+#define OBJ_Security            OBJ_internet,5L
+
+#define SN_SNMPv2               "snmpv2"
+#define LN_SNMPv2               "SNMPv2"
+#define NID_SNMPv2              387
+#define OBJ_SNMPv2              OBJ_internet,6L
+
+#define LN_Mail         "Mail"
+#define NID_Mail                388
+#define OBJ_Mail                OBJ_internet,7L
+
+#define SN_Enterprises          "enterprises"
+#define LN_Enterprises          "Enterprises"
+#define NID_Enterprises         389
+#define OBJ_Enterprises         OBJ_Private,1L
+
+#define SN_dcObject             "dcobject"
+#define LN_dcObject             "dcObject"
+#define NID_dcObject            390
+#define OBJ_dcObject            OBJ_Enterprises,1466L,344L
+
+#define SN_mime_mhs             "mime-mhs"
+#define LN_mime_mhs             "MIME MHS"
+#define NID_mime_mhs            504
+#define OBJ_mime_mhs            OBJ_Mail,1L
+
+#define SN_mime_mhs_headings            "mime-mhs-headings"
+#define LN_mime_mhs_headings            "mime-mhs-headings"
+#define NID_mime_mhs_headings           505
+#define OBJ_mime_mhs_headings           OBJ_mime_mhs,1L
+
+#define SN_mime_mhs_bodies              "mime-mhs-bodies"
+#define LN_mime_mhs_bodies              "mime-mhs-bodies"
+#define NID_mime_mhs_bodies             506
+#define OBJ_mime_mhs_bodies             OBJ_mime_mhs,2L
+
+#define SN_id_hex_partial_message               "id-hex-partial-message"
+#define LN_id_hex_partial_message               "id-hex-partial-message"
+#define NID_id_hex_partial_message              507
+#define OBJ_id_hex_partial_message              OBJ_mime_mhs_headings,1L
+
+#define SN_id_hex_multipart_message             "id-hex-multipart-message"
+#define LN_id_hex_multipart_message             "id-hex-multipart-message"
+#define NID_id_hex_multipart_message            508
+#define OBJ_id_hex_multipart_message            OBJ_mime_mhs_headings,2L
+
+#define SN_rle_compression              "RLE"
+#define LN_rle_compression              "run length compression"
+#define NID_rle_compression             124
+#define OBJ_rle_compression             1L,1L,1L,1L,666L,1L
+
+#define SN_zlib_compression             "ZLIB"
+#define LN_zlib_compression             "zlib compression"
+#define NID_zlib_compression            125
+#define OBJ_zlib_compression            OBJ_id_smime_alg,8L
+
+#define OBJ_csor                2L,16L,840L,1L,101L,3L
+
+#define OBJ_nistAlgorithms              OBJ_csor,4L
+
+#define OBJ_aes         OBJ_nistAlgorithms,1L
+
+#define SN_aes_128_ecb          "AES-128-ECB"
+#define LN_aes_128_ecb          "aes-128-ecb"
+#define NID_aes_128_ecb         418
+#define OBJ_aes_128_ecb         OBJ_aes,1L
+
+#define SN_aes_128_cbc          "AES-128-CBC"
+#define LN_aes_128_cbc          "aes-128-cbc"
+#define NID_aes_128_cbc         419
+#define OBJ_aes_128_cbc         OBJ_aes,2L
+
+#define SN_aes_128_ofb128               "AES-128-OFB"
+#define LN_aes_128_ofb128               "aes-128-ofb"
+#define NID_aes_128_ofb128              420
+#define OBJ_aes_128_ofb128              OBJ_aes,3L
+
+#define SN_aes_128_cfb128               "AES-128-CFB"
+#define LN_aes_128_cfb128               "aes-128-cfb"
+#define NID_aes_128_cfb128              421
+#define OBJ_aes_128_cfb128              OBJ_aes,4L
+
+#define SN_id_aes128_wrap               "id-aes128-wrap"
+#define NID_id_aes128_wrap              788
+#define OBJ_id_aes128_wrap              OBJ_aes,5L
+
+#define SN_aes_128_gcm          "id-aes128-GCM"
+#define LN_aes_128_gcm          "aes-128-gcm"
+#define NID_aes_128_gcm         895
+#define OBJ_aes_128_gcm         OBJ_aes,6L
+
+#define SN_aes_128_ccm          "id-aes128-CCM"
+#define LN_aes_128_ccm          "aes-128-ccm"
+#define NID_aes_128_ccm         896
+#define OBJ_aes_128_ccm         OBJ_aes,7L
+
+#define SN_id_aes128_wrap_pad           "id-aes128-wrap-pad"
+#define NID_id_aes128_wrap_pad          897
+#define OBJ_id_aes128_wrap_pad          OBJ_aes,8L
+
+#define SN_aes_192_ecb          "AES-192-ECB"
+#define LN_aes_192_ecb          "aes-192-ecb"
+#define NID_aes_192_ecb         422
+#define OBJ_aes_192_ecb         OBJ_aes,21L
+
+#define SN_aes_192_cbc          "AES-192-CBC"
+#define LN_aes_192_cbc          "aes-192-cbc"
+#define NID_aes_192_cbc         423
+#define OBJ_aes_192_cbc         OBJ_aes,22L
+
+#define SN_aes_192_ofb128               "AES-192-OFB"
+#define LN_aes_192_ofb128               "aes-192-ofb"
+#define NID_aes_192_ofb128              424
+#define OBJ_aes_192_ofb128              OBJ_aes,23L
+
+#define SN_aes_192_cfb128               "AES-192-CFB"
+#define LN_aes_192_cfb128               "aes-192-cfb"
+#define NID_aes_192_cfb128              425
+#define OBJ_aes_192_cfb128              OBJ_aes,24L
+
+#define SN_id_aes192_wrap               "id-aes192-wrap"
+#define NID_id_aes192_wrap              789
+#define OBJ_id_aes192_wrap              OBJ_aes,25L
+
+#define SN_aes_192_gcm          "id-aes192-GCM"
+#define LN_aes_192_gcm          "aes-192-gcm"
+#define NID_aes_192_gcm         898
+#define OBJ_aes_192_gcm         OBJ_aes,26L
+
+#define SN_aes_192_ccm          "id-aes192-CCM"
+#define LN_aes_192_ccm          "aes-192-ccm"
+#define NID_aes_192_ccm         899
+#define OBJ_aes_192_ccm         OBJ_aes,27L
+
+#define SN_id_aes192_wrap_pad           "id-aes192-wrap-pad"
+#define NID_id_aes192_wrap_pad          900
+#define OBJ_id_aes192_wrap_pad          OBJ_aes,28L
+
+#define SN_aes_256_ecb          "AES-256-ECB"
+#define LN_aes_256_ecb          "aes-256-ecb"
+#define NID_aes_256_ecb         426
+#define OBJ_aes_256_ecb         OBJ_aes,41L
+
+#define SN_aes_256_cbc          "AES-256-CBC"
+#define LN_aes_256_cbc          "aes-256-cbc"
+#define NID_aes_256_cbc         427
+#define OBJ_aes_256_cbc         OBJ_aes,42L
+
+#define SN_aes_256_ofb128               "AES-256-OFB"
+#define LN_aes_256_ofb128               "aes-256-ofb"
+#define NID_aes_256_ofb128              428
+#define OBJ_aes_256_ofb128              OBJ_aes,43L
+
+#define SN_aes_256_cfb128               "AES-256-CFB"
+#define LN_aes_256_cfb128               "aes-256-cfb"
+#define NID_aes_256_cfb128              429
+#define OBJ_aes_256_cfb128              OBJ_aes,44L
+
+#define SN_id_aes256_wrap               "id-aes256-wrap"
+#define NID_id_aes256_wrap              790
+#define OBJ_id_aes256_wrap              OBJ_aes,45L
+
+#define SN_aes_256_gcm          "id-aes256-GCM"
+#define LN_aes_256_gcm          "aes-256-gcm"
+#define NID_aes_256_gcm         901
+#define OBJ_aes_256_gcm         OBJ_aes,46L
+
+#define SN_aes_256_ccm          "id-aes256-CCM"
+#define LN_aes_256_ccm          "aes-256-ccm"
+#define NID_aes_256_ccm         902
+#define OBJ_aes_256_ccm         OBJ_aes,47L
+
+#define SN_id_aes256_wrap_pad           "id-aes256-wrap-pad"
+#define NID_id_aes256_wrap_pad          903
+#define OBJ_id_aes256_wrap_pad          OBJ_aes,48L
+
+#define SN_aes_128_cfb1         "AES-128-CFB1"
+#define LN_aes_128_cfb1         "aes-128-cfb1"
+#define NID_aes_128_cfb1                650
+
+#define SN_aes_192_cfb1         "AES-192-CFB1"
+#define LN_aes_192_cfb1         "aes-192-cfb1"
+#define NID_aes_192_cfb1                651
+
+#define SN_aes_256_cfb1         "AES-256-CFB1"
+#define LN_aes_256_cfb1         "aes-256-cfb1"
+#define NID_aes_256_cfb1                652
+
+#define SN_aes_128_cfb8         "AES-128-CFB8"
+#define LN_aes_128_cfb8         "aes-128-cfb8"
+#define NID_aes_128_cfb8                653
+
+#define SN_aes_192_cfb8         "AES-192-CFB8"
+#define LN_aes_192_cfb8         "aes-192-cfb8"
+#define NID_aes_192_cfb8                654
+
+#define SN_aes_256_cfb8         "AES-256-CFB8"
+#define LN_aes_256_cfb8         "aes-256-cfb8"
+#define NID_aes_256_cfb8                655
+
+#define SN_aes_128_ctr          "AES-128-CTR"
+#define LN_aes_128_ctr          "aes-128-ctr"
+#define NID_aes_128_ctr         904
+
+#define SN_aes_192_ctr          "AES-192-CTR"
+#define LN_aes_192_ctr          "aes-192-ctr"
+#define NID_aes_192_ctr         905
+
+#define SN_aes_256_ctr          "AES-256-CTR"
+#define LN_aes_256_ctr          "aes-256-ctr"
+#define NID_aes_256_ctr         906
+
+#define SN_aes_128_xts          "AES-128-XTS"
+#define LN_aes_128_xts          "aes-128-xts"
+#define NID_aes_128_xts         913
+
+#define SN_aes_256_xts          "AES-256-XTS"
+#define LN_aes_256_xts          "aes-256-xts"
+#define NID_aes_256_xts         914
+
+#define SN_des_cfb1             "DES-CFB1"
+#define LN_des_cfb1             "des-cfb1"
+#define NID_des_cfb1            656
+
+#define SN_des_cfb8             "DES-CFB8"
+#define LN_des_cfb8             "des-cfb8"
+#define NID_des_cfb8            657
+
+#define SN_des_ede3_cfb1                "DES-EDE3-CFB1"
+#define LN_des_ede3_cfb1                "des-ede3-cfb1"
+#define NID_des_ede3_cfb1               658
+
+#define SN_des_ede3_cfb8                "DES-EDE3-CFB8"
+#define LN_des_ede3_cfb8                "des-ede3-cfb8"
+#define NID_des_ede3_cfb8               659
+
+#define OBJ_nist_hashalgs               OBJ_nistAlgorithms,2L
+
+#define SN_sha256               "SHA256"
+#define LN_sha256               "sha256"
+#define NID_sha256              672
+#define OBJ_sha256              OBJ_nist_hashalgs,1L
+
+#define SN_sha384               "SHA384"
+#define LN_sha384               "sha384"
+#define NID_sha384              673
+#define OBJ_sha384              OBJ_nist_hashalgs,2L
+
+#define SN_sha512               "SHA512"
+#define LN_sha512               "sha512"
+#define NID_sha512              674
+#define OBJ_sha512              OBJ_nist_hashalgs,3L
+
+#define SN_sha224               "SHA224"
+#define LN_sha224               "sha224"
+#define NID_sha224              675
+#define OBJ_sha224              OBJ_nist_hashalgs,4L
+
+#define OBJ_dsa_with_sha2               OBJ_nistAlgorithms,3L
+
+#define SN_dsa_with_SHA224              "dsa_with_SHA224"
+#define NID_dsa_with_SHA224             802
+#define OBJ_dsa_with_SHA224             OBJ_dsa_with_sha2,1L
+
+#define SN_dsa_with_SHA256              "dsa_with_SHA256"
+#define NID_dsa_with_SHA256             803
+#define OBJ_dsa_with_SHA256             OBJ_dsa_with_sha2,2L
+
+#define SN_hold_instruction_code                "holdInstructionCode"
+#define LN_hold_instruction_code                "Hold Instruction Code"
+#define NID_hold_instruction_code               430
+#define OBJ_hold_instruction_code               OBJ_id_ce,23L
+
+#define OBJ_holdInstruction             OBJ_X9_57,2L
+
+#define SN_hold_instruction_none                "holdInstructionNone"
+#define LN_hold_instruction_none                "Hold Instruction None"
+#define NID_hold_instruction_none               431
+#define OBJ_hold_instruction_none               OBJ_holdInstruction,1L
+
+#define SN_hold_instruction_call_issuer         "holdInstructionCallIssuer"
+#define LN_hold_instruction_call_issuer         "Hold Instruction Call Issuer"
+#define NID_hold_instruction_call_issuer                432
+#define OBJ_hold_instruction_call_issuer                OBJ_holdInstruction,2L
+
+#define SN_hold_instruction_reject              "holdInstructionReject"
+#define LN_hold_instruction_reject              "Hold Instruction Reject"
+#define NID_hold_instruction_reject             433
+#define OBJ_hold_instruction_reject             OBJ_holdInstruction,3L
+
+#define SN_data         "data"
+#define NID_data                434
+#define OBJ_data                OBJ_itu_t,9L
+
+#define SN_pss          "pss"
+#define NID_pss         435
+#define OBJ_pss         OBJ_data,2342L
+
+#define SN_ucl          "ucl"
+#define NID_ucl         436
+#define OBJ_ucl         OBJ_pss,19200300L
+
+#define SN_pilot                "pilot"
+#define NID_pilot               437
+#define OBJ_pilot               OBJ_ucl,100L
+
+#define LN_pilotAttributeType           "pilotAttributeType"
+#define NID_pilotAttributeType          438
+#define OBJ_pilotAttributeType          OBJ_pilot,1L
+
+#define LN_pilotAttributeSyntax         "pilotAttributeSyntax"
+#define NID_pilotAttributeSyntax                439
+#define OBJ_pilotAttributeSyntax                OBJ_pilot,3L
+
+#define LN_pilotObjectClass             "pilotObjectClass"
+#define NID_pilotObjectClass            440
+#define OBJ_pilotObjectClass            OBJ_pilot,4L
+
+#define LN_pilotGroups          "pilotGroups"
+#define NID_pilotGroups         441
+#define OBJ_pilotGroups         OBJ_pilot,10L
+
+#define LN_iA5StringSyntax              "iA5StringSyntax"
+#define NID_iA5StringSyntax             442
+#define OBJ_iA5StringSyntax             OBJ_pilotAttributeSyntax,4L
+
+#define LN_caseIgnoreIA5StringSyntax            "caseIgnoreIA5StringSyntax"
+#define NID_caseIgnoreIA5StringSyntax           443
+#define OBJ_caseIgnoreIA5StringSyntax           OBJ_pilotAttributeSyntax,5L
+
+#define LN_pilotObject          "pilotObject"
+#define NID_pilotObject         444
+#define OBJ_pilotObject         OBJ_pilotObjectClass,3L
+
+#define LN_pilotPerson          "pilotPerson"
+#define NID_pilotPerson         445
+#define OBJ_pilotPerson         OBJ_pilotObjectClass,4L
+
+#define SN_account              "account"
+#define NID_account             446
+#define OBJ_account             OBJ_pilotObjectClass,5L
+
+#define SN_document             "document"
+#define NID_document            447
+#define OBJ_document            OBJ_pilotObjectClass,6L
+
+#define SN_room         "room"
+#define NID_room                448
+#define OBJ_room                OBJ_pilotObjectClass,7L
+
+#define LN_documentSeries               "documentSeries"
+#define NID_documentSeries              449
+#define OBJ_documentSeries              OBJ_pilotObjectClass,9L
+
+#define SN_Domain               "domain"
+#define LN_Domain               "Domain"
+#define NID_Domain              392
+#define OBJ_Domain              OBJ_pilotObjectClass,13L
+
+#define LN_rFC822localPart              "rFC822localPart"
+#define NID_rFC822localPart             450
+#define OBJ_rFC822localPart             OBJ_pilotObjectClass,14L
+
+#define LN_dNSDomain            "dNSDomain"
+#define NID_dNSDomain           451
+#define OBJ_dNSDomain           OBJ_pilotObjectClass,15L
+
+#define LN_domainRelatedObject          "domainRelatedObject"
+#define NID_domainRelatedObject         452
+#define OBJ_domainRelatedObject         OBJ_pilotObjectClass,17L
+
+#define LN_friendlyCountry              "friendlyCountry"
+#define NID_friendlyCountry             453
+#define OBJ_friendlyCountry             OBJ_pilotObjectClass,18L
+
+#define LN_simpleSecurityObject         "simpleSecurityObject"
+#define NID_simpleSecurityObject                454
+#define OBJ_simpleSecurityObject                OBJ_pilotObjectClass,19L
+
+#define LN_pilotOrganization            "pilotOrganization"
+#define NID_pilotOrganization           455
+#define OBJ_pilotOrganization           OBJ_pilotObjectClass,20L
+
+#define LN_pilotDSA             "pilotDSA"
+#define NID_pilotDSA            456
+#define OBJ_pilotDSA            OBJ_pilotObjectClass,21L
+
+#define LN_qualityLabelledData          "qualityLabelledData"
+#define NID_qualityLabelledData         457
+#define OBJ_qualityLabelledData         OBJ_pilotObjectClass,22L
+
+#define SN_userId               "UID"
+#define LN_userId               "userId"
+#define NID_userId              458
+#define OBJ_userId              OBJ_pilotAttributeType,1L
+
+#define LN_textEncodedORAddress         "textEncodedORAddress"
+#define NID_textEncodedORAddress                459
+#define OBJ_textEncodedORAddress                OBJ_pilotAttributeType,2L
+
+#define SN_rfc822Mailbox                "mail"
+#define LN_rfc822Mailbox                "rfc822Mailbox"
+#define NID_rfc822Mailbox               460
+#define OBJ_rfc822Mailbox               OBJ_pilotAttributeType,3L
+
+#define SN_info         "info"
+#define NID_info                461
+#define OBJ_info                OBJ_pilotAttributeType,4L
+
+#define LN_favouriteDrink               "favouriteDrink"
+#define NID_favouriteDrink              462
+#define OBJ_favouriteDrink              OBJ_pilotAttributeType,5L
+
+#define LN_roomNumber           "roomNumber"
+#define NID_roomNumber          463
+#define OBJ_roomNumber          OBJ_pilotAttributeType,6L
+
+#define SN_photo                "photo"
+#define NID_photo               464
+#define OBJ_photo               OBJ_pilotAttributeType,7L
+
+#define LN_userClass            "userClass"
+#define NID_userClass           465
+#define OBJ_userClass           OBJ_pilotAttributeType,8L
+
+#define SN_host         "host"
+#define NID_host                466
+#define OBJ_host                OBJ_pilotAttributeType,9L
+
+#define SN_manager              "manager"
+#define NID_manager             467
+#define OBJ_manager             OBJ_pilotAttributeType,10L
+
+#define LN_documentIdentifier           "documentIdentifier"
+#define NID_documentIdentifier          468
+#define OBJ_documentIdentifier          OBJ_pilotAttributeType,11L
+
+#define LN_documentTitle                "documentTitle"
+#define NID_documentTitle               469
+#define OBJ_documentTitle               OBJ_pilotAttributeType,12L
+
+#define LN_documentVersion              "documentVersion"
+#define NID_documentVersion             470
+#define OBJ_documentVersion             OBJ_pilotAttributeType,13L
+
+#define LN_documentAuthor               "documentAuthor"
+#define NID_documentAuthor              471
+#define OBJ_documentAuthor              OBJ_pilotAttributeType,14L
+
+#define LN_documentLocation             "documentLocation"
+#define NID_documentLocation            472
+#define OBJ_documentLocation            OBJ_pilotAttributeType,15L
+
+#define LN_homeTelephoneNumber          "homeTelephoneNumber"
+#define NID_homeTelephoneNumber         473
+#define OBJ_homeTelephoneNumber         OBJ_pilotAttributeType,20L
+
+#define SN_secretary            "secretary"
+#define NID_secretary           474
+#define OBJ_secretary           OBJ_pilotAttributeType,21L
+
+#define LN_otherMailbox         "otherMailbox"
+#define NID_otherMailbox                475
+#define OBJ_otherMailbox                OBJ_pilotAttributeType,22L
+
+#define LN_lastModifiedTime             "lastModifiedTime"
+#define NID_lastModifiedTime            476
+#define OBJ_lastModifiedTime            OBJ_pilotAttributeType,23L
+
+#define LN_lastModifiedBy               "lastModifiedBy"
+#define NID_lastModifiedBy              477
+#define OBJ_lastModifiedBy              OBJ_pilotAttributeType,24L
+
+#define SN_domainComponent              "DC"
+#define LN_domainComponent              "domainComponent"
+#define NID_domainComponent             391
+#define OBJ_domainComponent             OBJ_pilotAttributeType,25L
+
+#define LN_aRecord              "aRecord"
+#define NID_aRecord             478
+#define OBJ_aRecord             OBJ_pilotAttributeType,26L
+
+#define LN_pilotAttributeType27         "pilotAttributeType27"
+#define NID_pilotAttributeType27                479
+#define OBJ_pilotAttributeType27                OBJ_pilotAttributeType,27L
+
+#define LN_mXRecord             "mXRecord"
+#define NID_mXRecord            480
+#define OBJ_mXRecord            OBJ_pilotAttributeType,28L
+
+#define LN_nSRecord             "nSRecord"
+#define NID_nSRecord            481
+#define OBJ_nSRecord            OBJ_pilotAttributeType,29L
+
+#define LN_sOARecord            "sOARecord"
+#define NID_sOARecord           482
+#define OBJ_sOARecord           OBJ_pilotAttributeType,30L
+
+#define LN_cNAMERecord          "cNAMERecord"
+#define NID_cNAMERecord         483
+#define OBJ_cNAMERecord         OBJ_pilotAttributeType,31L
+
+#define LN_associatedDomain             "associatedDomain"
+#define NID_associatedDomain            484
+#define OBJ_associatedDomain            OBJ_pilotAttributeType,37L
+
+#define LN_associatedName               "associatedName"
+#define NID_associatedName              485
+#define OBJ_associatedName              OBJ_pilotAttributeType,38L
+
+#define LN_homePostalAddress            "homePostalAddress"
+#define NID_homePostalAddress           486
+#define OBJ_homePostalAddress           OBJ_pilotAttributeType,39L
+
+#define LN_personalTitle                "personalTitle"
+#define NID_personalTitle               487
+#define OBJ_personalTitle               OBJ_pilotAttributeType,40L
+
+#define LN_mobileTelephoneNumber                "mobileTelephoneNumber"
+#define NID_mobileTelephoneNumber               488
+#define OBJ_mobileTelephoneNumber               OBJ_pilotAttributeType,41L
+
+#define LN_pagerTelephoneNumber         "pagerTelephoneNumber"
+#define NID_pagerTelephoneNumber                489
+#define OBJ_pagerTelephoneNumber                OBJ_pilotAttributeType,42L
+
+#define LN_friendlyCountryName          "friendlyCountryName"
+#define NID_friendlyCountryName         490
+#define OBJ_friendlyCountryName         OBJ_pilotAttributeType,43L
+
+#define LN_organizationalStatus         "organizationalStatus"
+#define NID_organizationalStatus                491
+#define OBJ_organizationalStatus                OBJ_pilotAttributeType,45L
+
+#define LN_janetMailbox         "janetMailbox"
+#define NID_janetMailbox                492
+#define OBJ_janetMailbox                OBJ_pilotAttributeType,46L
+
+#define LN_mailPreferenceOption         "mailPreferenceOption"
+#define NID_mailPreferenceOption                493
+#define OBJ_mailPreferenceOption                OBJ_pilotAttributeType,47L
+
+#define LN_buildingName         "buildingName"
+#define NID_buildingName                494
+#define OBJ_buildingName                OBJ_pilotAttributeType,48L
+
+#define LN_dSAQuality           "dSAQuality"
+#define NID_dSAQuality          495
+#define OBJ_dSAQuality          OBJ_pilotAttributeType,49L
+
+#define LN_singleLevelQuality           "singleLevelQuality"
+#define NID_singleLevelQuality          496
+#define OBJ_singleLevelQuality          OBJ_pilotAttributeType,50L
+
+#define LN_subtreeMinimumQuality                "subtreeMinimumQuality"
+#define NID_subtreeMinimumQuality               497
+#define OBJ_subtreeMinimumQuality               OBJ_pilotAttributeType,51L
+
+#define LN_subtreeMaximumQuality                "subtreeMaximumQuality"
+#define NID_subtreeMaximumQuality               498
+#define OBJ_subtreeMaximumQuality               OBJ_pilotAttributeType,52L
+
+#define LN_personalSignature            "personalSignature"
+#define NID_personalSignature           499
+#define OBJ_personalSignature           OBJ_pilotAttributeType,53L
+
+#define LN_dITRedirect          "dITRedirect"
+#define NID_dITRedirect         500
+#define OBJ_dITRedirect         OBJ_pilotAttributeType,54L
+
+#define SN_audio                "audio"
+#define NID_audio               501
+#define OBJ_audio               OBJ_pilotAttributeType,55L
+
+#define LN_documentPublisher            "documentPublisher"
+#define NID_documentPublisher           502
+#define OBJ_documentPublisher           OBJ_pilotAttributeType,56L
+
+#define SN_id_set               "id-set"
+#define LN_id_set               "Secure Electronic Transactions"
+#define NID_id_set              512
+#define OBJ_id_set              OBJ_international_organizations,42L
+
+#define SN_set_ctype            "set-ctype"
+#define LN_set_ctype            "content types"
+#define NID_set_ctype           513
+#define OBJ_set_ctype           OBJ_id_set,0L
+
+#define SN_set_msgExt           "set-msgExt"
+#define LN_set_msgExt           "message extensions"
+#define NID_set_msgExt          514
+#define OBJ_set_msgExt          OBJ_id_set,1L
+
+#define SN_set_attr             "set-attr"
+#define NID_set_attr            515
+#define OBJ_set_attr            OBJ_id_set,3L
+
+#define SN_set_policy           "set-policy"
+#define NID_set_policy          516
+#define OBJ_set_policy          OBJ_id_set,5L
+
+#define SN_set_certExt          "set-certExt"
+#define LN_set_certExt          "certificate extensions"
+#define NID_set_certExt         517
+#define OBJ_set_certExt         OBJ_id_set,7L
+
+#define SN_set_brand            "set-brand"
+#define NID_set_brand           518
+#define OBJ_set_brand           OBJ_id_set,8L
+
+#define SN_setct_PANData                "setct-PANData"
+#define NID_setct_PANData               519
+#define OBJ_setct_PANData               OBJ_set_ctype,0L
+
+#define SN_setct_PANToken               "setct-PANToken"
+#define NID_setct_PANToken              520
+#define OBJ_setct_PANToken              OBJ_set_ctype,1L
+
+#define SN_setct_PANOnly                "setct-PANOnly"
+#define NID_setct_PANOnly               521
+#define OBJ_setct_PANOnly               OBJ_set_ctype,2L
+
+#define SN_setct_OIData         "setct-OIData"
+#define NID_setct_OIData                522
+#define OBJ_setct_OIData                OBJ_set_ctype,3L
+
+#define SN_setct_PI             "setct-PI"
+#define NID_setct_PI            523
+#define OBJ_setct_PI            OBJ_set_ctype,4L
+
+#define SN_setct_PIData         "setct-PIData"
+#define NID_setct_PIData                524
+#define OBJ_setct_PIData                OBJ_set_ctype,5L
+
+#define SN_setct_PIDataUnsigned         "setct-PIDataUnsigned"
+#define NID_setct_PIDataUnsigned                525
+#define OBJ_setct_PIDataUnsigned                OBJ_set_ctype,6L
+
+#define SN_setct_HODInput               "setct-HODInput"
+#define NID_setct_HODInput              526
+#define OBJ_setct_HODInput              OBJ_set_ctype,7L
+
+#define SN_setct_AuthResBaggage         "setct-AuthResBaggage"
+#define NID_setct_AuthResBaggage                527
+#define OBJ_setct_AuthResBaggage                OBJ_set_ctype,8L
+
+#define SN_setct_AuthRevReqBaggage              "setct-AuthRevReqBaggage"
+#define NID_setct_AuthRevReqBaggage             528
+#define OBJ_setct_AuthRevReqBaggage             OBJ_set_ctype,9L
+
+#define SN_setct_AuthRevResBaggage              "setct-AuthRevResBaggage"
+#define NID_setct_AuthRevResBaggage             529
+#define OBJ_setct_AuthRevResBaggage             OBJ_set_ctype,10L
+
+#define SN_setct_CapTokenSeq            "setct-CapTokenSeq"
+#define NID_setct_CapTokenSeq           530
+#define OBJ_setct_CapTokenSeq           OBJ_set_ctype,11L
+
+#define SN_setct_PInitResData           "setct-PInitResData"
+#define NID_setct_PInitResData          531
+#define OBJ_setct_PInitResData          OBJ_set_ctype,12L
+
+#define SN_setct_PI_TBS         "setct-PI-TBS"
+#define NID_setct_PI_TBS                532
+#define OBJ_setct_PI_TBS                OBJ_set_ctype,13L
+
+#define SN_setct_PResData               "setct-PResData"
+#define NID_setct_PResData              533
+#define OBJ_setct_PResData              OBJ_set_ctype,14L
+
+#define SN_setct_AuthReqTBS             "setct-AuthReqTBS"
+#define NID_setct_AuthReqTBS            534
+#define OBJ_setct_AuthReqTBS            OBJ_set_ctype,16L
+
+#define SN_setct_AuthResTBS             "setct-AuthResTBS"
+#define NID_setct_AuthResTBS            535
+#define OBJ_setct_AuthResTBS            OBJ_set_ctype,17L
+
+#define SN_setct_AuthResTBSX            "setct-AuthResTBSX"
+#define NID_setct_AuthResTBSX           536
+#define OBJ_setct_AuthResTBSX           OBJ_set_ctype,18L
+
+#define SN_setct_AuthTokenTBS           "setct-AuthTokenTBS"
+#define NID_setct_AuthTokenTBS          537
+#define OBJ_setct_AuthTokenTBS          OBJ_set_ctype,19L
+
+#define SN_setct_CapTokenData           "setct-CapTokenData"
+#define NID_setct_CapTokenData          538
+#define OBJ_setct_CapTokenData          OBJ_set_ctype,20L
+
+#define SN_setct_CapTokenTBS            "setct-CapTokenTBS"
+#define NID_setct_CapTokenTBS           539
+#define OBJ_setct_CapTokenTBS           OBJ_set_ctype,21L
+
+#define SN_setct_AcqCardCodeMsg         "setct-AcqCardCodeMsg"
+#define NID_setct_AcqCardCodeMsg                540
+#define OBJ_setct_AcqCardCodeMsg                OBJ_set_ctype,22L
+
+#define SN_setct_AuthRevReqTBS          "setct-AuthRevReqTBS"
+#define NID_setct_AuthRevReqTBS         541
+#define OBJ_setct_AuthRevReqTBS         OBJ_set_ctype,23L
+
+#define SN_setct_AuthRevResData         "setct-AuthRevResData"
+#define NID_setct_AuthRevResData                542
+#define OBJ_setct_AuthRevResData                OBJ_set_ctype,24L
+
+#define SN_setct_AuthRevResTBS          "setct-AuthRevResTBS"
+#define NID_setct_AuthRevResTBS         543
+#define OBJ_setct_AuthRevResTBS         OBJ_set_ctype,25L
+
+#define SN_setct_CapReqTBS              "setct-CapReqTBS"
+#define NID_setct_CapReqTBS             544
+#define OBJ_setct_CapReqTBS             OBJ_set_ctype,26L
+
+#define SN_setct_CapReqTBSX             "setct-CapReqTBSX"
+#define NID_setct_CapReqTBSX            545
+#define OBJ_setct_CapReqTBSX            OBJ_set_ctype,27L
+
+#define SN_setct_CapResData             "setct-CapResData"
+#define NID_setct_CapResData            546
+#define OBJ_setct_CapResData            OBJ_set_ctype,28L
+
+#define SN_setct_CapRevReqTBS           "setct-CapRevReqTBS"
+#define NID_setct_CapRevReqTBS          547
+#define OBJ_setct_CapRevReqTBS          OBJ_set_ctype,29L
+
+#define SN_setct_CapRevReqTBSX          "setct-CapRevReqTBSX"
+#define NID_setct_CapRevReqTBSX         548
+#define OBJ_setct_CapRevReqTBSX         OBJ_set_ctype,30L
+
+#define SN_setct_CapRevResData          "setct-CapRevResData"
+#define NID_setct_CapRevResData         549
+#define OBJ_setct_CapRevResData         OBJ_set_ctype,31L
+
+#define SN_setct_CredReqTBS             "setct-CredReqTBS"
+#define NID_setct_CredReqTBS            550
+#define OBJ_setct_CredReqTBS            OBJ_set_ctype,32L
+
+#define SN_setct_CredReqTBSX            "setct-CredReqTBSX"
+#define NID_setct_CredReqTBSX           551
+#define OBJ_setct_CredReqTBSX           OBJ_set_ctype,33L
+
+#define SN_setct_CredResData            "setct-CredResData"
+#define NID_setct_CredResData           552
+#define OBJ_setct_CredResData           OBJ_set_ctype,34L
+
+#define SN_setct_CredRevReqTBS          "setct-CredRevReqTBS"
+#define NID_setct_CredRevReqTBS         553
+#define OBJ_setct_CredRevReqTBS         OBJ_set_ctype,35L
+
+#define SN_setct_CredRevReqTBSX         "setct-CredRevReqTBSX"
+#define NID_setct_CredRevReqTBSX                554
+#define OBJ_setct_CredRevReqTBSX                OBJ_set_ctype,36L
+
+#define SN_setct_CredRevResData         "setct-CredRevResData"
+#define NID_setct_CredRevResData                555
+#define OBJ_setct_CredRevResData                OBJ_set_ctype,37L
+
+#define SN_setct_PCertReqData           "setct-PCertReqData"
+#define NID_setct_PCertReqData          556
+#define OBJ_setct_PCertReqData          OBJ_set_ctype,38L
+
+#define SN_setct_PCertResTBS            "setct-PCertResTBS"
+#define NID_setct_PCertResTBS           557
+#define OBJ_setct_PCertResTBS           OBJ_set_ctype,39L
+
+#define SN_setct_BatchAdminReqData              "setct-BatchAdminReqData"
+#define NID_setct_BatchAdminReqData             558
+#define OBJ_setct_BatchAdminReqData             OBJ_set_ctype,40L
+
+#define SN_setct_BatchAdminResData              "setct-BatchAdminResData"
+#define NID_setct_BatchAdminResData             559
+#define OBJ_setct_BatchAdminResData             OBJ_set_ctype,41L
+
+#define SN_setct_CardCInitResTBS                "setct-CardCInitResTBS"
+#define NID_setct_CardCInitResTBS               560
+#define OBJ_setct_CardCInitResTBS               OBJ_set_ctype,42L
+
+#define SN_setct_MeAqCInitResTBS                "setct-MeAqCInitResTBS"
+#define NID_setct_MeAqCInitResTBS               561
+#define OBJ_setct_MeAqCInitResTBS               OBJ_set_ctype,43L
+
+#define SN_setct_RegFormResTBS          "setct-RegFormResTBS"
+#define NID_setct_RegFormResTBS         562
+#define OBJ_setct_RegFormResTBS         OBJ_set_ctype,44L
+
+#define SN_setct_CertReqData            "setct-CertReqData"
+#define NID_setct_CertReqData           563
+#define OBJ_setct_CertReqData           OBJ_set_ctype,45L
+
+#define SN_setct_CertReqTBS             "setct-CertReqTBS"
+#define NID_setct_CertReqTBS            564
+#define OBJ_setct_CertReqTBS            OBJ_set_ctype,46L
+
+#define SN_setct_CertResData            "setct-CertResData"
+#define NID_setct_CertResData           565
+#define OBJ_setct_CertResData           OBJ_set_ctype,47L
+
+#define SN_setct_CertInqReqTBS          "setct-CertInqReqTBS"
+#define NID_setct_CertInqReqTBS         566
+#define OBJ_setct_CertInqReqTBS         OBJ_set_ctype,48L
+
+#define SN_setct_ErrorTBS               "setct-ErrorTBS"
+#define NID_setct_ErrorTBS              567
+#define OBJ_setct_ErrorTBS              OBJ_set_ctype,49L
+
+#define SN_setct_PIDualSignedTBE                "setct-PIDualSignedTBE"
+#define NID_setct_PIDualSignedTBE               568
+#define OBJ_setct_PIDualSignedTBE               OBJ_set_ctype,50L
+
+#define SN_setct_PIUnsignedTBE          "setct-PIUnsignedTBE"
+#define NID_setct_PIUnsignedTBE         569
+#define OBJ_setct_PIUnsignedTBE         OBJ_set_ctype,51L
+
+#define SN_setct_AuthReqTBE             "setct-AuthReqTBE"
+#define NID_setct_AuthReqTBE            570
+#define OBJ_setct_AuthReqTBE            OBJ_set_ctype,52L
+
+#define SN_setct_AuthResTBE             "setct-AuthResTBE"
+#define NID_setct_AuthResTBE            571
+#define OBJ_setct_AuthResTBE            OBJ_set_ctype,53L
+
+#define SN_setct_AuthResTBEX            "setct-AuthResTBEX"
+#define NID_setct_AuthResTBEX           572
+#define OBJ_setct_AuthResTBEX           OBJ_set_ctype,54L
+
+#define SN_setct_AuthTokenTBE           "setct-AuthTokenTBE"
+#define NID_setct_AuthTokenTBE          573
+#define OBJ_setct_AuthTokenTBE          OBJ_set_ctype,55L
+
+#define SN_setct_CapTokenTBE            "setct-CapTokenTBE"
+#define NID_setct_CapTokenTBE           574
+#define OBJ_setct_CapTokenTBE           OBJ_set_ctype,56L
+
+#define SN_setct_CapTokenTBEX           "setct-CapTokenTBEX"
+#define NID_setct_CapTokenTBEX          575
+#define OBJ_setct_CapTokenTBEX          OBJ_set_ctype,57L
+
+#define SN_setct_AcqCardCodeMsgTBE              "setct-AcqCardCodeMsgTBE"
+#define NID_setct_AcqCardCodeMsgTBE             576
+#define OBJ_setct_AcqCardCodeMsgTBE             OBJ_set_ctype,58L
+
+#define SN_setct_AuthRevReqTBE          "setct-AuthRevReqTBE"
+#define NID_setct_AuthRevReqTBE         577
+#define OBJ_setct_AuthRevReqTBE         OBJ_set_ctype,59L
+
+#define SN_setct_AuthRevResTBE          "setct-AuthRevResTBE"
+#define NID_setct_AuthRevResTBE         578
+#define OBJ_setct_AuthRevResTBE         OBJ_set_ctype,60L
+
+#define SN_setct_AuthRevResTBEB         "setct-AuthRevResTBEB"
+#define NID_setct_AuthRevResTBEB                579
+#define OBJ_setct_AuthRevResTBEB                OBJ_set_ctype,61L
+
+#define SN_setct_CapReqTBE              "setct-CapReqTBE"
+#define NID_setct_CapReqTBE             580
+#define OBJ_setct_CapReqTBE             OBJ_set_ctype,62L
+
+#define SN_setct_CapReqTBEX             "setct-CapReqTBEX"
+#define NID_setct_CapReqTBEX            581
+#define OBJ_setct_CapReqTBEX            OBJ_set_ctype,63L
+
+#define SN_setct_CapResTBE              "setct-CapResTBE"
+#define NID_setct_CapResTBE             582
+#define OBJ_setct_CapResTBE             OBJ_set_ctype,64L
+
+#define SN_setct_CapRevReqTBE           "setct-CapRevReqTBE"
+#define NID_setct_CapRevReqTBE          583
+#define OBJ_setct_CapRevReqTBE          OBJ_set_ctype,65L
+
+#define SN_setct_CapRevReqTBEX          "setct-CapRevReqTBEX"
+#define NID_setct_CapRevReqTBEX         584
+#define OBJ_setct_CapRevReqTBEX         OBJ_set_ctype,66L
+
+#define SN_setct_CapRevResTBE           "setct-CapRevResTBE"
+#define NID_setct_CapRevResTBE          585
+#define OBJ_setct_CapRevResTBE          OBJ_set_ctype,67L
+
+#define SN_setct_CredReqTBE             "setct-CredReqTBE"
+#define NID_setct_CredReqTBE            586
+#define OBJ_setct_CredReqTBE            OBJ_set_ctype,68L
+
+#define SN_setct_CredReqTBEX            "setct-CredReqTBEX"
+#define NID_setct_CredReqTBEX           587
+#define OBJ_setct_CredReqTBEX           OBJ_set_ctype,69L
+
+#define SN_setct_CredResTBE             "setct-CredResTBE"
+#define NID_setct_CredResTBE            588
+#define OBJ_setct_CredResTBE            OBJ_set_ctype,70L
+
+#define SN_setct_CredRevReqTBE          "setct-CredRevReqTBE"
+#define NID_setct_CredRevReqTBE         589
+#define OBJ_setct_CredRevReqTBE         OBJ_set_ctype,71L
+
+#define SN_setct_CredRevReqTBEX         "setct-CredRevReqTBEX"
+#define NID_setct_CredRevReqTBEX                590
+#define OBJ_setct_CredRevReqTBEX                OBJ_set_ctype,72L
+
+#define SN_setct_CredRevResTBE          "setct-CredRevResTBE"
+#define NID_setct_CredRevResTBE         591
+#define OBJ_setct_CredRevResTBE         OBJ_set_ctype,73L
+
+#define SN_setct_BatchAdminReqTBE               "setct-BatchAdminReqTBE"
+#define NID_setct_BatchAdminReqTBE              592
+#define OBJ_setct_BatchAdminReqTBE              OBJ_set_ctype,74L
+
+#define SN_setct_BatchAdminResTBE               "setct-BatchAdminResTBE"
+#define NID_setct_BatchAdminResTBE              593
+#define OBJ_setct_BatchAdminResTBE              OBJ_set_ctype,75L
+
+#define SN_setct_RegFormReqTBE          "setct-RegFormReqTBE"
+#define NID_setct_RegFormReqTBE         594
+#define OBJ_setct_RegFormReqTBE         OBJ_set_ctype,76L
+
+#define SN_setct_CertReqTBE             "setct-CertReqTBE"
+#define NID_setct_CertReqTBE            595
+#define OBJ_setct_CertReqTBE            OBJ_set_ctype,77L
+
+#define SN_setct_CertReqTBEX            "setct-CertReqTBEX"
+#define NID_setct_CertReqTBEX           596
+#define OBJ_setct_CertReqTBEX           OBJ_set_ctype,78L
+
+#define SN_setct_CertResTBE             "setct-CertResTBE"
+#define NID_setct_CertResTBE            597
+#define OBJ_setct_CertResTBE            OBJ_set_ctype,79L
+
+#define SN_setct_CRLNotificationTBS             "setct-CRLNotificationTBS"
+#define NID_setct_CRLNotificationTBS            598
+#define OBJ_setct_CRLNotificationTBS            OBJ_set_ctype,80L
+
+#define SN_setct_CRLNotificationResTBS          "setct-CRLNotificationResTBS"
+#define NID_setct_CRLNotificationResTBS         599
+#define OBJ_setct_CRLNotificationResTBS         OBJ_set_ctype,81L
+
+#define SN_setct_BCIDistributionTBS             "setct-BCIDistributionTBS"
+#define NID_setct_BCIDistributionTBS            600
+#define OBJ_setct_BCIDistributionTBS            OBJ_set_ctype,82L
+
+#define SN_setext_genCrypt              "setext-genCrypt"
+#define LN_setext_genCrypt              "generic cryptogram"
+#define NID_setext_genCrypt             601
+#define OBJ_setext_genCrypt             OBJ_set_msgExt,1L
+
+#define SN_setext_miAuth                "setext-miAuth"
+#define LN_setext_miAuth                "merchant initiated auth"
+#define NID_setext_miAuth               602
+#define OBJ_setext_miAuth               OBJ_set_msgExt,3L
+
+#define SN_setext_pinSecure             "setext-pinSecure"
+#define NID_setext_pinSecure            603
+#define OBJ_setext_pinSecure            OBJ_set_msgExt,4L
+
+#define SN_setext_pinAny                "setext-pinAny"
+#define NID_setext_pinAny               604
+#define OBJ_setext_pinAny               OBJ_set_msgExt,5L
+
+#define SN_setext_track2                "setext-track2"
+#define NID_setext_track2               605
+#define OBJ_setext_track2               OBJ_set_msgExt,7L
+
+#define SN_setext_cv            "setext-cv"
+#define LN_setext_cv            "additional verification"
+#define NID_setext_cv           606
+#define OBJ_setext_cv           OBJ_set_msgExt,8L
+
+#define SN_set_policy_root              "set-policy-root"
+#define NID_set_policy_root             607
+#define OBJ_set_policy_root             OBJ_set_policy,0L
+
+#define SN_setCext_hashedRoot           "setCext-hashedRoot"
+#define NID_setCext_hashedRoot          608
+#define OBJ_setCext_hashedRoot          OBJ_set_certExt,0L
+
+#define SN_setCext_certType             "setCext-certType"
+#define NID_setCext_certType            609
+#define OBJ_setCext_certType            OBJ_set_certExt,1L
+
+#define SN_setCext_merchData            "setCext-merchData"
+#define NID_setCext_merchData           610
+#define OBJ_setCext_merchData           OBJ_set_certExt,2L
+
+#define SN_setCext_cCertRequired                "setCext-cCertRequired"
+#define NID_setCext_cCertRequired               611
+#define OBJ_setCext_cCertRequired               OBJ_set_certExt,3L
+
+#define SN_setCext_tunneling            "setCext-tunneling"
+#define NID_setCext_tunneling           612
+#define OBJ_setCext_tunneling           OBJ_set_certExt,4L
+
+#define SN_setCext_setExt               "setCext-setExt"
+#define NID_setCext_setExt              613
+#define OBJ_setCext_setExt              OBJ_set_certExt,5L
+
+#define SN_setCext_setQualf             "setCext-setQualf"
+#define NID_setCext_setQualf            614
+#define OBJ_setCext_setQualf            OBJ_set_certExt,6L
+
+#define SN_setCext_PGWYcapabilities             "setCext-PGWYcapabilities"
+#define NID_setCext_PGWYcapabilities            615
+#define OBJ_setCext_PGWYcapabilities            OBJ_set_certExt,7L
+
+#define SN_setCext_TokenIdentifier              "setCext-TokenIdentifier"
+#define NID_setCext_TokenIdentifier             616
+#define OBJ_setCext_TokenIdentifier             OBJ_set_certExt,8L
+
+#define SN_setCext_Track2Data           "setCext-Track2Data"
+#define NID_setCext_Track2Data          617
+#define OBJ_setCext_Track2Data          OBJ_set_certExt,9L
+
+#define SN_setCext_TokenType            "setCext-TokenType"
+#define NID_setCext_TokenType           618
+#define OBJ_setCext_TokenType           OBJ_set_certExt,10L
+
+#define SN_setCext_IssuerCapabilities           "setCext-IssuerCapabilities"
+#define NID_setCext_IssuerCapabilities          619
+#define OBJ_setCext_IssuerCapabilities          OBJ_set_certExt,11L
+
+#define SN_setAttr_Cert         "setAttr-Cert"
+#define NID_setAttr_Cert                620
+#define OBJ_setAttr_Cert                OBJ_set_attr,0L
+
+#define SN_setAttr_PGWYcap              "setAttr-PGWYcap"
+#define LN_setAttr_PGWYcap              "payment gateway capabilities"
+#define NID_setAttr_PGWYcap             621
+#define OBJ_setAttr_PGWYcap             OBJ_set_attr,1L
+
+#define SN_setAttr_TokenType            "setAttr-TokenType"
+#define NID_setAttr_TokenType           622
+#define OBJ_setAttr_TokenType           OBJ_set_attr,2L
+
+#define SN_setAttr_IssCap               "setAttr-IssCap"
+#define LN_setAttr_IssCap               "issuer capabilities"
+#define NID_setAttr_IssCap              623
+#define OBJ_setAttr_IssCap              OBJ_set_attr,3L
+
+#define SN_set_rootKeyThumb             "set-rootKeyThumb"
+#define NID_set_rootKeyThumb            624
+#define OBJ_set_rootKeyThumb            OBJ_setAttr_Cert,0L
+
+#define SN_set_addPolicy                "set-addPolicy"
+#define NID_set_addPolicy               625
+#define OBJ_set_addPolicy               OBJ_setAttr_Cert,1L
+
+#define SN_setAttr_Token_EMV            "setAttr-Token-EMV"
+#define NID_setAttr_Token_EMV           626
+#define OBJ_setAttr_Token_EMV           OBJ_setAttr_TokenType,1L
+
+#define SN_setAttr_Token_B0Prime                "setAttr-Token-B0Prime"
+#define NID_setAttr_Token_B0Prime               627
+#define OBJ_setAttr_Token_B0Prime               OBJ_setAttr_TokenType,2L
+
+#define SN_setAttr_IssCap_CVM           "setAttr-IssCap-CVM"
+#define NID_setAttr_IssCap_CVM          628
+#define OBJ_setAttr_IssCap_CVM          OBJ_setAttr_IssCap,3L
+
+#define SN_setAttr_IssCap_T2            "setAttr-IssCap-T2"
+#define NID_setAttr_IssCap_T2           629
+#define OBJ_setAttr_IssCap_T2           OBJ_setAttr_IssCap,4L
+
+#define SN_setAttr_IssCap_Sig           "setAttr-IssCap-Sig"
+#define NID_setAttr_IssCap_Sig          630
+#define OBJ_setAttr_IssCap_Sig          OBJ_setAttr_IssCap,5L
+
+#define SN_setAttr_GenCryptgrm          "setAttr-GenCryptgrm"
+#define LN_setAttr_GenCryptgrm          "generate cryptogram"
+#define NID_setAttr_GenCryptgrm         631
+#define OBJ_setAttr_GenCryptgrm         OBJ_setAttr_IssCap_CVM,1L
+
+#define SN_setAttr_T2Enc                "setAttr-T2Enc"
+#define LN_setAttr_T2Enc                "encrypted track 2"
+#define NID_setAttr_T2Enc               632
+#define OBJ_setAttr_T2Enc               OBJ_setAttr_IssCap_T2,1L
+
+#define SN_setAttr_T2cleartxt           "setAttr-T2cleartxt"
+#define LN_setAttr_T2cleartxt           "cleartext track 2"
+#define NID_setAttr_T2cleartxt          633
+#define OBJ_setAttr_T2cleartxt          OBJ_setAttr_IssCap_T2,2L
+
+#define SN_setAttr_TokICCsig            "setAttr-TokICCsig"
+#define LN_setAttr_TokICCsig            "ICC or token signature"
+#define NID_setAttr_TokICCsig           634
+#define OBJ_setAttr_TokICCsig           OBJ_setAttr_IssCap_Sig,1L
+
+#define SN_setAttr_SecDevSig            "setAttr-SecDevSig"
+#define LN_setAttr_SecDevSig            "secure device signature"
+#define NID_setAttr_SecDevSig           635
+#define OBJ_setAttr_SecDevSig           OBJ_setAttr_IssCap_Sig,2L
+
+#define SN_set_brand_IATA_ATA           "set-brand-IATA-ATA"
+#define NID_set_brand_IATA_ATA          636
+#define OBJ_set_brand_IATA_ATA          OBJ_set_brand,1L
+
+#define SN_set_brand_Diners             "set-brand-Diners"
+#define NID_set_brand_Diners            637
+#define OBJ_set_brand_Diners            OBJ_set_brand,30L
+
+#define SN_set_brand_AmericanExpress            "set-brand-AmericanExpress"
+#define NID_set_brand_AmericanExpress           638
+#define OBJ_set_brand_AmericanExpress           OBJ_set_brand,34L
+
+#define SN_set_brand_JCB                "set-brand-JCB"
+#define NID_set_brand_JCB               639
+#define OBJ_set_brand_JCB               OBJ_set_brand,35L
+
+#define SN_set_brand_Visa               "set-brand-Visa"
+#define NID_set_brand_Visa              640
+#define OBJ_set_brand_Visa              OBJ_set_brand,4L
+
+#define SN_set_brand_MasterCard         "set-brand-MasterCard"
+#define NID_set_brand_MasterCard                641
+#define OBJ_set_brand_MasterCard                OBJ_set_brand,5L
+
+#define SN_set_brand_Novus              "set-brand-Novus"
+#define NID_set_brand_Novus             642
+#define OBJ_set_brand_Novus             OBJ_set_brand,6011L
+
+#define SN_des_cdmf             "DES-CDMF"
+#define LN_des_cdmf             "des-cdmf"
+#define NID_des_cdmf            643
+#define OBJ_des_cdmf            OBJ_rsadsi,3L,10L
+
+#define SN_rsaOAEPEncryptionSET         "rsaOAEPEncryptionSET"
+#define NID_rsaOAEPEncryptionSET                644
+#define OBJ_rsaOAEPEncryptionSET                OBJ_rsadsi,1L,1L,6L
+
+#define SN_ipsec3               "Oakley-EC2N-3"
+#define LN_ipsec3               "ipsec3"
+#define NID_ipsec3              749
+
+#define SN_ipsec4               "Oakley-EC2N-4"
+#define LN_ipsec4               "ipsec4"
+#define NID_ipsec4              750
+
+#define SN_whirlpool            "whirlpool"
+#define NID_whirlpool           804
+#define OBJ_whirlpool           OBJ_iso,0L,10118L,3L,0L,55L
+
+#define SN_cryptopro            "cryptopro"
+#define NID_cryptopro           805
+#define OBJ_cryptopro           OBJ_member_body,643L,2L,2L
+
+#define SN_cryptocom            "cryptocom"
+#define NID_cryptocom           806
+#define OBJ_cryptocom           OBJ_member_body,643L,2L,9L
+
+#define SN_id_GostR3411_94_with_GostR3410_2001          "id-GostR3411-94-with-GostR3410-2001"
+#define LN_id_GostR3411_94_with_GostR3410_2001          "GOST R 34.11-94 with GOST R 34.10-2001"
+#define NID_id_GostR3411_94_with_GostR3410_2001         807
+#define OBJ_id_GostR3411_94_with_GostR3410_2001         OBJ_cryptopro,3L
+
+#define SN_id_GostR3411_94_with_GostR3410_94            "id-GostR3411-94-with-GostR3410-94"
+#define LN_id_GostR3411_94_with_GostR3410_94            "GOST R 34.11-94 with GOST R 34.10-94"
+#define NID_id_GostR3411_94_with_GostR3410_94           808
+#define OBJ_id_GostR3411_94_with_GostR3410_94           OBJ_cryptopro,4L
+
+#define SN_id_GostR3411_94              "md_gost94"
+#define LN_id_GostR3411_94              "GOST R 34.11-94"
+#define NID_id_GostR3411_94             809
+#define OBJ_id_GostR3411_94             OBJ_cryptopro,9L
+
+#define SN_id_HMACGostR3411_94          "id-HMACGostR3411-94"
+#define LN_id_HMACGostR3411_94          "HMAC GOST 34.11-94"
+#define NID_id_HMACGostR3411_94         810
+#define OBJ_id_HMACGostR3411_94         OBJ_cryptopro,10L
+
+#define SN_id_GostR3410_2001            "gost2001"
+#define LN_id_GostR3410_2001            "GOST R 34.10-2001"
+#define NID_id_GostR3410_2001           811
+#define OBJ_id_GostR3410_2001           OBJ_cryptopro,19L
+
+#define SN_id_GostR3410_94              "gost94"
+#define LN_id_GostR3410_94              "GOST R 34.10-94"
+#define NID_id_GostR3410_94             812
+#define OBJ_id_GostR3410_94             OBJ_cryptopro,20L
+
+#define SN_id_Gost28147_89              "gost89"
+#define LN_id_Gost28147_89              "GOST 28147-89"
+#define NID_id_Gost28147_89             813
+#define OBJ_id_Gost28147_89             OBJ_cryptopro,21L
+
+#define SN_gost89_cnt           "gost89-cnt"
+#define NID_gost89_cnt          814
+
+#define SN_id_Gost28147_89_MAC          "gost-mac"
+#define LN_id_Gost28147_89_MAC          "GOST 28147-89 MAC"
+#define NID_id_Gost28147_89_MAC         815
+#define OBJ_id_Gost28147_89_MAC         OBJ_cryptopro,22L
+
+#define SN_id_GostR3411_94_prf          "prf-gostr3411-94"
+#define LN_id_GostR3411_94_prf          "GOST R 34.11-94 PRF"
+#define NID_id_GostR3411_94_prf         816
+#define OBJ_id_GostR3411_94_prf         OBJ_cryptopro,23L
+
+#define SN_id_GostR3410_2001DH          "id-GostR3410-2001DH"
+#define LN_id_GostR3410_2001DH          "GOST R 34.10-2001 DH"
+#define NID_id_GostR3410_2001DH         817
+#define OBJ_id_GostR3410_2001DH         OBJ_cryptopro,98L
+
+#define SN_id_GostR3410_94DH            "id-GostR3410-94DH"
+#define LN_id_GostR3410_94DH            "GOST R 34.10-94 DH"
+#define NID_id_GostR3410_94DH           818
+#define OBJ_id_GostR3410_94DH           OBJ_cryptopro,99L
+
+#define SN_id_Gost28147_89_CryptoPro_KeyMeshing         "id-Gost28147-89-CryptoPro-KeyMeshing"
+#define NID_id_Gost28147_89_CryptoPro_KeyMeshing                819
+#define OBJ_id_Gost28147_89_CryptoPro_KeyMeshing                OBJ_cryptopro,14L,1L
+
+#define SN_id_Gost28147_89_None_KeyMeshing              "id-Gost28147-89-None-KeyMeshing"
+#define NID_id_Gost28147_89_None_KeyMeshing             820
+#define OBJ_id_Gost28147_89_None_KeyMeshing             OBJ_cryptopro,14L,0L
+
+#define SN_id_GostR3411_94_TestParamSet         "id-GostR3411-94-TestParamSet"
+#define NID_id_GostR3411_94_TestParamSet                821
+#define OBJ_id_GostR3411_94_TestParamSet                OBJ_cryptopro,30L,0L
+
+#define SN_id_GostR3411_94_CryptoProParamSet            "id-GostR3411-94-CryptoProParamSet"
+#define NID_id_GostR3411_94_CryptoProParamSet           822
+#define OBJ_id_GostR3411_94_CryptoProParamSet           OBJ_cryptopro,30L,1L
+
+#define SN_id_Gost28147_89_TestParamSet         "id-Gost28147-89-TestParamSet"
+#define NID_id_Gost28147_89_TestParamSet                823
+#define OBJ_id_Gost28147_89_TestParamSet                OBJ_cryptopro,31L,0L
+
+#define SN_id_Gost28147_89_CryptoPro_A_ParamSet         "id-Gost28147-89-CryptoPro-A-ParamSet"
+#define NID_id_Gost28147_89_CryptoPro_A_ParamSet                824
+#define OBJ_id_Gost28147_89_CryptoPro_A_ParamSet                OBJ_cryptopro,31L,1L
+
+#define SN_id_Gost28147_89_CryptoPro_B_ParamSet         "id-Gost28147-89-CryptoPro-B-ParamSet"
+#define NID_id_Gost28147_89_CryptoPro_B_ParamSet                825
+#define OBJ_id_Gost28147_89_CryptoPro_B_ParamSet                OBJ_cryptopro,31L,2L
+
+#define SN_id_Gost28147_89_CryptoPro_C_ParamSet         "id-Gost28147-89-CryptoPro-C-ParamSet"
+#define NID_id_Gost28147_89_CryptoPro_C_ParamSet                826
+#define OBJ_id_Gost28147_89_CryptoPro_C_ParamSet                OBJ_cryptopro,31L,3L
+
+#define SN_id_Gost28147_89_CryptoPro_D_ParamSet         "id-Gost28147-89-CryptoPro-D-ParamSet"
+#define NID_id_Gost28147_89_CryptoPro_D_ParamSet                827
+#define OBJ_id_Gost28147_89_CryptoPro_D_ParamSet                OBJ_cryptopro,31L,4L
+
+#define SN_id_Gost28147_89_CryptoPro_Oscar_1_1_ParamSet         "id-Gost28147-89-CryptoPro-Oscar-1-1-ParamSet"
+#define NID_id_Gost28147_89_CryptoPro_Oscar_1_1_ParamSet                828
+#define OBJ_id_Gost28147_89_CryptoPro_Oscar_1_1_ParamSet                OBJ_cryptopro,31L,5L
+
+#define SN_id_Gost28147_89_CryptoPro_Oscar_1_0_ParamSet         "id-Gost28147-89-CryptoPro-Oscar-1-0-ParamSet"
+#define NID_id_Gost28147_89_CryptoPro_Oscar_1_0_ParamSet                829
+#define OBJ_id_Gost28147_89_CryptoPro_Oscar_1_0_ParamSet                OBJ_cryptopro,31L,6L
+
+#define SN_id_Gost28147_89_CryptoPro_RIC_1_ParamSet             "id-Gost28147-89-CryptoPro-RIC-1-ParamSet"
+#define NID_id_Gost28147_89_CryptoPro_RIC_1_ParamSet            830
+#define OBJ_id_Gost28147_89_CryptoPro_RIC_1_ParamSet            OBJ_cryptopro,31L,7L
+
+#define SN_id_GostR3410_94_TestParamSet         "id-GostR3410-94-TestParamSet"
+#define NID_id_GostR3410_94_TestParamSet                831
+#define OBJ_id_GostR3410_94_TestParamSet                OBJ_cryptopro,32L,0L
+
+#define SN_id_GostR3410_94_CryptoPro_A_ParamSet         "id-GostR3410-94-CryptoPro-A-ParamSet"
+#define NID_id_GostR3410_94_CryptoPro_A_ParamSet                832
+#define OBJ_id_GostR3410_94_CryptoPro_A_ParamSet                OBJ_cryptopro,32L,2L
+
+#define SN_id_GostR3410_94_CryptoPro_B_ParamSet         "id-GostR3410-94-CryptoPro-B-ParamSet"
+#define NID_id_GostR3410_94_CryptoPro_B_ParamSet                833
+#define OBJ_id_GostR3410_94_CryptoPro_B_ParamSet                OBJ_cryptopro,32L,3L
+
+#define SN_id_GostR3410_94_CryptoPro_C_ParamSet         "id-GostR3410-94-CryptoPro-C-ParamSet"
+#define NID_id_GostR3410_94_CryptoPro_C_ParamSet                834
+#define OBJ_id_GostR3410_94_CryptoPro_C_ParamSet                OBJ_cryptopro,32L,4L
+
+#define SN_id_GostR3410_94_CryptoPro_D_ParamSet         "id-GostR3410-94-CryptoPro-D-ParamSet"
+#define NID_id_GostR3410_94_CryptoPro_D_ParamSet                835
+#define OBJ_id_GostR3410_94_CryptoPro_D_ParamSet                OBJ_cryptopro,32L,5L
+
+#define SN_id_GostR3410_94_CryptoPro_XchA_ParamSet              "id-GostR3410-94-CryptoPro-XchA-ParamSet"
+#define NID_id_GostR3410_94_CryptoPro_XchA_ParamSet             836
+#define OBJ_id_GostR3410_94_CryptoPro_XchA_ParamSet             OBJ_cryptopro,33L,1L
+
+#define SN_id_GostR3410_94_CryptoPro_XchB_ParamSet              "id-GostR3410-94-CryptoPro-XchB-ParamSet"
+#define NID_id_GostR3410_94_CryptoPro_XchB_ParamSet             837
+#define OBJ_id_GostR3410_94_CryptoPro_XchB_ParamSet             OBJ_cryptopro,33L,2L
+
+#define SN_id_GostR3410_94_CryptoPro_XchC_ParamSet              "id-GostR3410-94-CryptoPro-XchC-ParamSet"
+#define NID_id_GostR3410_94_CryptoPro_XchC_ParamSet             838
+#define OBJ_id_GostR3410_94_CryptoPro_XchC_ParamSet             OBJ_cryptopro,33L,3L
+
+#define SN_id_GostR3410_2001_TestParamSet               "id-GostR3410-2001-TestParamSet"
+#define NID_id_GostR3410_2001_TestParamSet              839
+#define OBJ_id_GostR3410_2001_TestParamSet              OBJ_cryptopro,35L,0L
+
+#define SN_id_GostR3410_2001_CryptoPro_A_ParamSet               "id-GostR3410-2001-CryptoPro-A-ParamSet"
+#define NID_id_GostR3410_2001_CryptoPro_A_ParamSet              840
+#define OBJ_id_GostR3410_2001_CryptoPro_A_ParamSet              OBJ_cryptopro,35L,1L
+
+#define SN_id_GostR3410_2001_CryptoPro_B_ParamSet               "id-GostR3410-2001-CryptoPro-B-ParamSet"
+#define NID_id_GostR3410_2001_CryptoPro_B_ParamSet              841
+#define OBJ_id_GostR3410_2001_CryptoPro_B_ParamSet              OBJ_cryptopro,35L,2L
+
+#define SN_id_GostR3410_2001_CryptoPro_C_ParamSet               "id-GostR3410-2001-CryptoPro-C-ParamSet"
+#define NID_id_GostR3410_2001_CryptoPro_C_ParamSet              842
+#define OBJ_id_GostR3410_2001_CryptoPro_C_ParamSet              OBJ_cryptopro,35L,3L
+
+#define SN_id_GostR3410_2001_CryptoPro_XchA_ParamSet            "id-GostR3410-2001-CryptoPro-XchA-ParamSet"
+#define NID_id_GostR3410_2001_CryptoPro_XchA_ParamSet           843
+#define OBJ_id_GostR3410_2001_CryptoPro_XchA_ParamSet           OBJ_cryptopro,36L,0L
+
+#define SN_id_GostR3410_2001_CryptoPro_XchB_ParamSet            "id-GostR3410-2001-CryptoPro-XchB-ParamSet"
+#define NID_id_GostR3410_2001_CryptoPro_XchB_ParamSet           844
+#define OBJ_id_GostR3410_2001_CryptoPro_XchB_ParamSet           OBJ_cryptopro,36L,1L
+
+#define SN_id_GostR3410_94_a            "id-GostR3410-94-a"
+#define NID_id_GostR3410_94_a           845
+#define OBJ_id_GostR3410_94_a           OBJ_id_GostR3410_94,1L
+
+#define SN_id_GostR3410_94_aBis         "id-GostR3410-94-aBis"
+#define NID_id_GostR3410_94_aBis                846
+#define OBJ_id_GostR3410_94_aBis                OBJ_id_GostR3410_94,2L
+
+#define SN_id_GostR3410_94_b            "id-GostR3410-94-b"
+#define NID_id_GostR3410_94_b           847
+#define OBJ_id_GostR3410_94_b           OBJ_id_GostR3410_94,3L
+
+#define SN_id_GostR3410_94_bBis         "id-GostR3410-94-bBis"
+#define NID_id_GostR3410_94_bBis                848
+#define OBJ_id_GostR3410_94_bBis                OBJ_id_GostR3410_94,4L
+
+#define SN_id_Gost28147_89_cc           "id-Gost28147-89-cc"
+#define LN_id_Gost28147_89_cc           "GOST 28147-89 Cryptocom ParamSet"
+#define NID_id_Gost28147_89_cc          849
+#define OBJ_id_Gost28147_89_cc          OBJ_cryptocom,1L,6L,1L
+
+#define SN_id_GostR3410_94_cc           "gost94cc"
+#define LN_id_GostR3410_94_cc           "GOST 34.10-94 Cryptocom"
+#define NID_id_GostR3410_94_cc          850
+#define OBJ_id_GostR3410_94_cc          OBJ_cryptocom,1L,5L,3L
+
+#define SN_id_GostR3410_2001_cc         "gost2001cc"
+#define LN_id_GostR3410_2001_cc         "GOST 34.10-2001 Cryptocom"
+#define NID_id_GostR3410_2001_cc                851
+#define OBJ_id_GostR3410_2001_cc                OBJ_cryptocom,1L,5L,4L
+
+#define SN_id_GostR3411_94_with_GostR3410_94_cc         "id-GostR3411-94-with-GostR3410-94-cc"
+#define LN_id_GostR3411_94_with_GostR3410_94_cc         "GOST R 34.11-94 with GOST R 34.10-94 Cryptocom"
+#define NID_id_GostR3411_94_with_GostR3410_94_cc                852
+#define OBJ_id_GostR3411_94_with_GostR3410_94_cc                OBJ_cryptocom,1L,3L,3L
+
+#define SN_id_GostR3411_94_with_GostR3410_2001_cc               "id-GostR3411-94-with-GostR3410-2001-cc"
+#define LN_id_GostR3411_94_with_GostR3410_2001_cc               "GOST R 34.11-94 with GOST R 34.10-2001 Cryptocom"
+#define NID_id_GostR3411_94_with_GostR3410_2001_cc              853
+#define OBJ_id_GostR3411_94_with_GostR3410_2001_cc              OBJ_cryptocom,1L,3L,4L
+
+#define SN_id_GostR3410_2001_ParamSet_cc                "id-GostR3410-2001-ParamSet-cc"
+#define LN_id_GostR3410_2001_ParamSet_cc                "GOST R 3410-2001 Parameter Set Cryptocom"
+#define NID_id_GostR3410_2001_ParamSet_cc               854
+#define OBJ_id_GostR3410_2001_ParamSet_cc               OBJ_cryptocom,1L,8L,1L
+
+#define SN_camellia_128_cbc             "CAMELLIA-128-CBC"
+#define LN_camellia_128_cbc             "camellia-128-cbc"
+#define NID_camellia_128_cbc            751
+#define OBJ_camellia_128_cbc            1L,2L,392L,200011L,61L,1L,1L,1L,2L
+
+#define SN_camellia_192_cbc             "CAMELLIA-192-CBC"
+#define LN_camellia_192_cbc             "camellia-192-cbc"
+#define NID_camellia_192_cbc            752
+#define OBJ_camellia_192_cbc            1L,2L,392L,200011L,61L,1L,1L,1L,3L
+
+#define SN_camellia_256_cbc             "CAMELLIA-256-CBC"
+#define LN_camellia_256_cbc             "camellia-256-cbc"
+#define NID_camellia_256_cbc            753
+#define OBJ_camellia_256_cbc            1L,2L,392L,200011L,61L,1L,1L,1L,4L
+
+#define SN_id_camellia128_wrap          "id-camellia128-wrap"
+#define NID_id_camellia128_wrap         907
+#define OBJ_id_camellia128_wrap         1L,2L,392L,200011L,61L,1L,1L,3L,2L
+
+#define SN_id_camellia192_wrap          "id-camellia192-wrap"
+#define NID_id_camellia192_wrap         908
+#define OBJ_id_camellia192_wrap         1L,2L,392L,200011L,61L,1L,1L,3L,3L
+
+#define SN_id_camellia256_wrap          "id-camellia256-wrap"
+#define NID_id_camellia256_wrap         909
+#define OBJ_id_camellia256_wrap         1L,2L,392L,200011L,61L,1L,1L,3L,4L
+
+#define OBJ_ntt_ds              0L,3L,4401L,5L
+
+#define OBJ_camellia            OBJ_ntt_ds,3L,1L,9L
+
+#define SN_camellia_128_ecb             "CAMELLIA-128-ECB"
+#define LN_camellia_128_ecb             "camellia-128-ecb"
+#define NID_camellia_128_ecb            754
+#define OBJ_camellia_128_ecb            OBJ_camellia,1L
+
+#define SN_camellia_128_ofb128          "CAMELLIA-128-OFB"
+#define LN_camellia_128_ofb128          "camellia-128-ofb"
+#define NID_camellia_128_ofb128         766
+#define OBJ_camellia_128_ofb128         OBJ_camellia,3L
+
+#define SN_camellia_128_cfb128          "CAMELLIA-128-CFB"
+#define LN_camellia_128_cfb128          "camellia-128-cfb"
+#define NID_camellia_128_cfb128         757
+#define OBJ_camellia_128_cfb128         OBJ_camellia,4L
+
+#define SN_camellia_192_ecb             "CAMELLIA-192-ECB"
+#define LN_camellia_192_ecb             "camellia-192-ecb"
+#define NID_camellia_192_ecb            755
+#define OBJ_camellia_192_ecb            OBJ_camellia,21L
+
+#define SN_camellia_192_ofb128          "CAMELLIA-192-OFB"
+#define LN_camellia_192_ofb128          "camellia-192-ofb"
+#define NID_camellia_192_ofb128         767
+#define OBJ_camellia_192_ofb128         OBJ_camellia,23L
+
+#define SN_camellia_192_cfb128          "CAMELLIA-192-CFB"
+#define LN_camellia_192_cfb128          "camellia-192-cfb"
+#define NID_camellia_192_cfb128         758
+#define OBJ_camellia_192_cfb128         OBJ_camellia,24L
+
+#define SN_camellia_256_ecb             "CAMELLIA-256-ECB"
+#define LN_camellia_256_ecb             "camellia-256-ecb"
+#define NID_camellia_256_ecb            756
+#define OBJ_camellia_256_ecb            OBJ_camellia,41L
+
+#define SN_camellia_256_ofb128          "CAMELLIA-256-OFB"
+#define LN_camellia_256_ofb128          "camellia-256-ofb"
+#define NID_camellia_256_ofb128         768
+#define OBJ_camellia_256_ofb128         OBJ_camellia,43L
+
+#define SN_camellia_256_cfb128          "CAMELLIA-256-CFB"
+#define LN_camellia_256_cfb128          "camellia-256-cfb"
+#define NID_camellia_256_cfb128         759
+#define OBJ_camellia_256_cfb128         OBJ_camellia,44L
+
+#define SN_camellia_128_cfb1            "CAMELLIA-128-CFB1"
+#define LN_camellia_128_cfb1            "camellia-128-cfb1"
+#define NID_camellia_128_cfb1           760
+
+#define SN_camellia_192_cfb1            "CAMELLIA-192-CFB1"
+#define LN_camellia_192_cfb1            "camellia-192-cfb1"
+#define NID_camellia_192_cfb1           761
+
+#define SN_camellia_256_cfb1            "CAMELLIA-256-CFB1"
+#define LN_camellia_256_cfb1            "camellia-256-cfb1"
+#define NID_camellia_256_cfb1           762
+
+#define SN_camellia_128_cfb8            "CAMELLIA-128-CFB8"
+#define LN_camellia_128_cfb8            "camellia-128-cfb8"
+#define NID_camellia_128_cfb8           763
+
+#define SN_camellia_192_cfb8            "CAMELLIA-192-CFB8"
+#define LN_camellia_192_cfb8            "camellia-192-cfb8"
+#define NID_camellia_192_cfb8           764
+
+#define SN_camellia_256_cfb8            "CAMELLIA-256-CFB8"
+#define LN_camellia_256_cfb8            "camellia-256-cfb8"
+#define NID_camellia_256_cfb8           765
+
+#define SN_kisa         "KISA"
+#define LN_kisa         "kisa"
+#define NID_kisa                773
+#define OBJ_kisa                OBJ_member_body,410L,200004L
+
+#define SN_seed_ecb             "SEED-ECB"
+#define LN_seed_ecb             "seed-ecb"
+#define NID_seed_ecb            776
+#define OBJ_seed_ecb            OBJ_kisa,1L,3L
+
+#define SN_seed_cbc             "SEED-CBC"
+#define LN_seed_cbc             "seed-cbc"
+#define NID_seed_cbc            777
+#define OBJ_seed_cbc            OBJ_kisa,1L,4L
+
+#define SN_seed_cfb128          "SEED-CFB"
+#define LN_seed_cfb128          "seed-cfb"
+#define NID_seed_cfb128         779
+#define OBJ_seed_cfb128         OBJ_kisa,1L,5L
+
+#define SN_seed_ofb128          "SEED-OFB"
+#define LN_seed_ofb128          "seed-ofb"
+#define NID_seed_ofb128         778
+#define OBJ_seed_ofb128         OBJ_kisa,1L,6L
+
+#define SN_hmac         "HMAC"
+#define LN_hmac         "hmac"
+#define NID_hmac                855
+
+#define SN_cmac         "CMAC"
+#define LN_cmac         "cmac"
+#define NID_cmac                894
+
+#define SN_rc4_hmac_md5         "RC4-HMAC-MD5"
+#define LN_rc4_hmac_md5         "rc4-hmac-md5"
+#define NID_rc4_hmac_md5                915
+
+#define SN_aes_128_cbc_hmac_sha1                "AES-128-CBC-HMAC-SHA1"
+#define LN_aes_128_cbc_hmac_sha1                "aes-128-cbc-hmac-sha1"
+#define NID_aes_128_cbc_hmac_sha1               916
+
+#define SN_aes_192_cbc_hmac_sha1                "AES-192-CBC-HMAC-SHA1"
+#define LN_aes_192_cbc_hmac_sha1                "aes-192-cbc-hmac-sha1"
+#define NID_aes_192_cbc_hmac_sha1               917
+
+#define SN_aes_256_cbc_hmac_sha1                "AES-256-CBC-HMAC-SHA1"
+#define LN_aes_256_cbc_hmac_sha1                "aes-256-cbc-hmac-sha1"
+#define NID_aes_256_cbc_hmac_sha1               918
+
+#define SN_aes_128_cbc_hmac_sha256              "AES-128-CBC-HMAC-SHA256"
+#define LN_aes_128_cbc_hmac_sha256              "aes-128-cbc-hmac-sha256"
+#define NID_aes_128_cbc_hmac_sha256             948
+
+#define SN_aes_192_cbc_hmac_sha256              "AES-192-CBC-HMAC-SHA256"
+#define LN_aes_192_cbc_hmac_sha256              "aes-192-cbc-hmac-sha256"
+#define NID_aes_192_cbc_hmac_sha256             949
+
+#define SN_aes_256_cbc_hmac_sha256              "AES-256-CBC-HMAC-SHA256"
+#define LN_aes_256_cbc_hmac_sha256              "aes-256-cbc-hmac-sha256"
+#define NID_aes_256_cbc_hmac_sha256             950
+
+#define SN_dhpublicnumber               "dhpublicnumber"
+#define LN_dhpublicnumber               "X9.42 DH"
+#define NID_dhpublicnumber              920
+#define OBJ_dhpublicnumber              OBJ_ISO_US,10046L,2L,1L
+
+#define SN_brainpoolP160r1              "brainpoolP160r1"
+#define NID_brainpoolP160r1             921
+#define OBJ_brainpoolP160r1             1L,3L,36L,3L,3L,2L,8L,1L,1L,1L
+
+#define SN_brainpoolP160t1              "brainpoolP160t1"
+#define NID_brainpoolP160t1             922
+#define OBJ_brainpoolP160t1             1L,3L,36L,3L,3L,2L,8L,1L,1L,2L
+
+#define SN_brainpoolP192r1              "brainpoolP192r1"
+#define NID_brainpoolP192r1             923
+#define OBJ_brainpoolP192r1             1L,3L,36L,3L,3L,2L,8L,1L,1L,3L
+
+#define SN_brainpoolP192t1              "brainpoolP192t1"
+#define NID_brainpoolP192t1             924
+#define OBJ_brainpoolP192t1             1L,3L,36L,3L,3L,2L,8L,1L,1L,4L
+
+#define SN_brainpoolP224r1              "brainpoolP224r1"
+#define NID_brainpoolP224r1             925
+#define OBJ_brainpoolP224r1             1L,3L,36L,3L,3L,2L,8L,1L,1L,5L
+
+#define SN_brainpoolP224t1              "brainpoolP224t1"
+#define NID_brainpoolP224t1             926
+#define OBJ_brainpoolP224t1             1L,3L,36L,3L,3L,2L,8L,1L,1L,6L
+
+#define SN_brainpoolP256r1              "brainpoolP256r1"
+#define NID_brainpoolP256r1             927
+#define OBJ_brainpoolP256r1             1L,3L,36L,3L,3L,2L,8L,1L,1L,7L
+
+#define SN_brainpoolP256t1              "brainpoolP256t1"
+#define NID_brainpoolP256t1             928
+#define OBJ_brainpoolP256t1             1L,3L,36L,3L,3L,2L,8L,1L,1L,8L
+
+#define SN_brainpoolP320r1              "brainpoolP320r1"
+#define NID_brainpoolP320r1             929
+#define OBJ_brainpoolP320r1             1L,3L,36L,3L,3L,2L,8L,1L,1L,9L
+
+#define SN_brainpoolP320t1              "brainpoolP320t1"
+#define NID_brainpoolP320t1             930
+#define OBJ_brainpoolP320t1             1L,3L,36L,3L,3L,2L,8L,1L,1L,10L
+
+#define SN_brainpoolP384r1              "brainpoolP384r1"
+#define NID_brainpoolP384r1             931
+#define OBJ_brainpoolP384r1             1L,3L,36L,3L,3L,2L,8L,1L,1L,11L
+
+#define SN_brainpoolP384t1              "brainpoolP384t1"
+#define NID_brainpoolP384t1             932
+#define OBJ_brainpoolP384t1             1L,3L,36L,3L,3L,2L,8L,1L,1L,12L
+
+#define SN_brainpoolP512r1              "brainpoolP512r1"
+#define NID_brainpoolP512r1             933
+#define OBJ_brainpoolP512r1             1L,3L,36L,3L,3L,2L,8L,1L,1L,13L
+
+#define SN_brainpoolP512t1              "brainpoolP512t1"
+#define NID_brainpoolP512t1             934
+#define OBJ_brainpoolP512t1             1L,3L,36L,3L,3L,2L,8L,1L,1L,14L
+
+#define OBJ_x9_63_scheme                1L,3L,133L,16L,840L,63L,0L
+
+#define OBJ_secg_scheme         OBJ_certicom_arc,1L
+
+#define SN_dhSinglePass_stdDH_sha1kdf_scheme            "dhSinglePass-stdDH-sha1kdf-scheme"
+#define NID_dhSinglePass_stdDH_sha1kdf_scheme           936
+#define OBJ_dhSinglePass_stdDH_sha1kdf_scheme           OBJ_x9_63_scheme,2L
+
+#define SN_dhSinglePass_stdDH_sha224kdf_scheme          "dhSinglePass-stdDH-sha224kdf-scheme"
+#define NID_dhSinglePass_stdDH_sha224kdf_scheme         937
+#define OBJ_dhSinglePass_stdDH_sha224kdf_scheme         OBJ_secg_scheme,11L,0L
+
+#define SN_dhSinglePass_stdDH_sha256kdf_scheme          "dhSinglePass-stdDH-sha256kdf-scheme"
+#define NID_dhSinglePass_stdDH_sha256kdf_scheme         938
+#define OBJ_dhSinglePass_stdDH_sha256kdf_scheme         OBJ_secg_scheme,11L,1L
+
+#define SN_dhSinglePass_stdDH_sha384kdf_scheme          "dhSinglePass-stdDH-sha384kdf-scheme"
+#define NID_dhSinglePass_stdDH_sha384kdf_scheme         939
+#define OBJ_dhSinglePass_stdDH_sha384kdf_scheme         OBJ_secg_scheme,11L,2L
+
+#define SN_dhSinglePass_stdDH_sha512kdf_scheme          "dhSinglePass-stdDH-sha512kdf-scheme"
+#define NID_dhSinglePass_stdDH_sha512kdf_scheme         940
+#define OBJ_dhSinglePass_stdDH_sha512kdf_scheme         OBJ_secg_scheme,11L,3L
+
+#define SN_dhSinglePass_cofactorDH_sha1kdf_scheme               "dhSinglePass-cofactorDH-sha1kdf-scheme"
+#define NID_dhSinglePass_cofactorDH_sha1kdf_scheme              941
+#define OBJ_dhSinglePass_cofactorDH_sha1kdf_scheme              OBJ_x9_63_scheme,3L
+
+#define SN_dhSinglePass_cofactorDH_sha224kdf_scheme             "dhSinglePass-cofactorDH-sha224kdf-scheme"
+#define NID_dhSinglePass_cofactorDH_sha224kdf_scheme            942
+#define OBJ_dhSinglePass_cofactorDH_sha224kdf_scheme            OBJ_secg_scheme,14L,0L
+
+#define SN_dhSinglePass_cofactorDH_sha256kdf_scheme             "dhSinglePass-cofactorDH-sha256kdf-scheme"
+#define NID_dhSinglePass_cofactorDH_sha256kdf_scheme            943
+#define OBJ_dhSinglePass_cofactorDH_sha256kdf_scheme            OBJ_secg_scheme,14L,1L
+
+#define SN_dhSinglePass_cofactorDH_sha384kdf_scheme             "dhSinglePass-cofactorDH-sha384kdf-scheme"
+#define NID_dhSinglePass_cofactorDH_sha384kdf_scheme            944
+#define OBJ_dhSinglePass_cofactorDH_sha384kdf_scheme            OBJ_secg_scheme,14L,2L
+
+#define SN_dhSinglePass_cofactorDH_sha512kdf_scheme             "dhSinglePass-cofactorDH-sha512kdf-scheme"
+#define NID_dhSinglePass_cofactorDH_sha512kdf_scheme            945
+#define OBJ_dhSinglePass_cofactorDH_sha512kdf_scheme            OBJ_secg_scheme,14L,3L
+
+#define SN_dh_std_kdf           "dh-std-kdf"
+#define NID_dh_std_kdf          946
+
+#define SN_dh_cofactor_kdf              "dh-cofactor-kdf"
+#define NID_dh_cofactor_kdf             947
+
+#define SN_ct_precert_scts              "ct_precert_scts"
+#define LN_ct_precert_scts              "CT Precertificate SCTs"
+#define NID_ct_precert_scts             951
+#define OBJ_ct_precert_scts             1L,3L,6L,1L,4L,1L,11129L,2L,4L,2L
+
+#define SN_ct_precert_poison            "ct_precert_poison"
+#define LN_ct_precert_poison            "CT Precertificate Poison"
+#define NID_ct_precert_poison           952
+#define OBJ_ct_precert_poison           1L,3L,6L,1L,4L,1L,11129L,2L,4L,3L
+
+#define SN_ct_precert_signer            "ct_precert_signer"
+#define LN_ct_precert_signer            "CT Precertificate Signer"
+#define NID_ct_precert_signer           953
+#define OBJ_ct_precert_signer           1L,3L,6L,1L,4L,1L,11129L,2L,4L,4L
+
+#define SN_ct_cert_scts         "ct_cert_scts"
+#define LN_ct_cert_scts         "CT Certificate SCTs"
+#define NID_ct_cert_scts                954
+#define OBJ_ct_cert_scts                1L,3L,6L,1L,4L,1L,11129L,2L,4L,5L
+
+#define SN_jurisdictionLocalityName             "jurisdictionL"
+#define LN_jurisdictionLocalityName             "jurisdictionLocalityName"
+#define NID_jurisdictionLocalityName            955
+#define OBJ_jurisdictionLocalityName            1L,3L,6L,1L,4L,1L,311L,60L,2L,1L,1L
+
+#define SN_jurisdictionStateOrProvinceName              "jurisdictionST"
+#define LN_jurisdictionStateOrProvinceName              "jurisdictionStateOrProvinceName"
+#define NID_jurisdictionStateOrProvinceName             956
+#define OBJ_jurisdictionStateOrProvinceName             1L,3L,6L,1L,4L,1L,311L,60L,2L,1L,2L
+
+#define SN_jurisdictionCountryName              "jurisdictionC"
+#define LN_jurisdictionCountryName              "jurisdictionCountryName"
+#define NID_jurisdictionCountryName             957
+#define OBJ_jurisdictionCountryName             1L,3L,6L,1L,4L,1L,311L,60L,2L,1L,3L

+ 1143 - 0
libssh2/openssl/include/openssl/objects.h

@@ -0,0 +1,1143 @@
+/* crypto/objects/objects.h */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * 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 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. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    "This product includes cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``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 AUTHOR OR CONTRIBUTORS 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.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+#ifndef HEADER_OBJECTS_H
+# define HEADER_OBJECTS_H
+
+# define USE_OBJ_MAC
+
+# ifdef USE_OBJ_MAC
+#  include <openssl/obj_mac.h>
+# else
+#  define SN_undef                        "UNDEF"
+#  define LN_undef                        "undefined"
+#  define NID_undef                       0
+#  define OBJ_undef                       0L
+
+#  define SN_Algorithm                    "Algorithm"
+#  define LN_algorithm                    "algorithm"
+#  define NID_algorithm                   38
+#  define OBJ_algorithm                   1L,3L,14L,3L,2L
+
+#  define LN_rsadsi                       "rsadsi"
+#  define NID_rsadsi                      1
+#  define OBJ_rsadsi                      1L,2L,840L,113549L
+
+#  define LN_pkcs                         "pkcs"
+#  define NID_pkcs                        2
+#  define OBJ_pkcs                        OBJ_rsadsi,1L
+
+#  define SN_md2                          "MD2"
+#  define LN_md2                          "md2"
+#  define NID_md2                         3
+#  define OBJ_md2                         OBJ_rsadsi,2L,2L
+
+#  define SN_md5                          "MD5"
+#  define LN_md5                          "md5"
+#  define NID_md5                         4
+#  define OBJ_md5                         OBJ_rsadsi,2L,5L
+
+#  define SN_rc4                          "RC4"
+#  define LN_rc4                          "rc4"
+#  define NID_rc4                         5
+#  define OBJ_rc4                         OBJ_rsadsi,3L,4L
+
+#  define LN_rsaEncryption                "rsaEncryption"
+#  define NID_rsaEncryption               6
+#  define OBJ_rsaEncryption               OBJ_pkcs,1L,1L
+
+#  define SN_md2WithRSAEncryption         "RSA-MD2"
+#  define LN_md2WithRSAEncryption         "md2WithRSAEncryption"
+#  define NID_md2WithRSAEncryption        7
+#  define OBJ_md2WithRSAEncryption        OBJ_pkcs,1L,2L
+
+#  define SN_md5WithRSAEncryption         "RSA-MD5"
+#  define LN_md5WithRSAEncryption         "md5WithRSAEncryption"
+#  define NID_md5WithRSAEncryption        8
+#  define OBJ_md5WithRSAEncryption        OBJ_pkcs,1L,4L
+
+#  define SN_pbeWithMD2AndDES_CBC         "PBE-MD2-DES"
+#  define LN_pbeWithMD2AndDES_CBC         "pbeWithMD2AndDES-CBC"
+#  define NID_pbeWithMD2AndDES_CBC        9
+#  define OBJ_pbeWithMD2AndDES_CBC        OBJ_pkcs,5L,1L
+
+#  define SN_pbeWithMD5AndDES_CBC         "PBE-MD5-DES"
+#  define LN_pbeWithMD5AndDES_CBC         "pbeWithMD5AndDES-CBC"
+#  define NID_pbeWithMD5AndDES_CBC        10
+#  define OBJ_pbeWithMD5AndDES_CBC        OBJ_pkcs,5L,3L
+
+#  define LN_X500                         "X500"
+#  define NID_X500                        11
+#  define OBJ_X500                        2L,5L
+
+#  define LN_X509                         "X509"
+#  define NID_X509                        12
+#  define OBJ_X509                        OBJ_X500,4L
+
+#  define SN_commonName                   "CN"
+#  define LN_commonName                   "commonName"
+#  define NID_commonName                  13
+#  define OBJ_commonName                  OBJ_X509,3L
+
+#  define SN_countryName                  "C"
+#  define LN_countryName                  "countryName"
+#  define NID_countryName                 14
+#  define OBJ_countryName                 OBJ_X509,6L
+
+#  define SN_localityName                 "L"
+#  define LN_localityName                 "localityName"
+#  define NID_localityName                15
+#  define OBJ_localityName                OBJ_X509,7L
+
+/* Postal Address? PA */
+
+/* should be "ST" (rfc1327) but MS uses 'S' */
+#  define SN_stateOrProvinceName          "ST"
+#  define LN_stateOrProvinceName          "stateOrProvinceName"
+#  define NID_stateOrProvinceName         16
+#  define OBJ_stateOrProvinceName         OBJ_X509,8L
+
+#  define SN_organizationName             "O"
+#  define LN_organizationName             "organizationName"
+#  define NID_organizationName            17
+#  define OBJ_organizationName            OBJ_X509,10L
+
+#  define SN_organizationalUnitName       "OU"
+#  define LN_organizationalUnitName       "organizationalUnitName"
+#  define NID_organizationalUnitName      18
+#  define OBJ_organizationalUnitName      OBJ_X509,11L
+
+#  define SN_rsa                          "RSA"
+#  define LN_rsa                          "rsa"
+#  define NID_rsa                         19
+#  define OBJ_rsa                         OBJ_X500,8L,1L,1L
+
+#  define LN_pkcs7                        "pkcs7"
+#  define NID_pkcs7                       20
+#  define OBJ_pkcs7                       OBJ_pkcs,7L
+
+#  define LN_pkcs7_data                   "pkcs7-data"
+#  define NID_pkcs7_data                  21
+#  define OBJ_pkcs7_data                  OBJ_pkcs7,1L
+
+#  define LN_pkcs7_signed                 "pkcs7-signedData"
+#  define NID_pkcs7_signed                22
+#  define OBJ_pkcs7_signed                OBJ_pkcs7,2L
+
+#  define LN_pkcs7_enveloped              "pkcs7-envelopedData"
+#  define NID_pkcs7_enveloped             23
+#  define OBJ_pkcs7_enveloped             OBJ_pkcs7,3L
+
+#  define LN_pkcs7_signedAndEnveloped     "pkcs7-signedAndEnvelopedData"
+#  define NID_pkcs7_signedAndEnveloped    24
+#  define OBJ_pkcs7_signedAndEnveloped    OBJ_pkcs7,4L
+
+#  define LN_pkcs7_digest                 "pkcs7-digestData"
+#  define NID_pkcs7_digest                25
+#  define OBJ_pkcs7_digest                OBJ_pkcs7,5L
+
+#  define LN_pkcs7_encrypted              "pkcs7-encryptedData"
+#  define NID_pkcs7_encrypted             26
+#  define OBJ_pkcs7_encrypted             OBJ_pkcs7,6L
+
+#  define LN_pkcs3                        "pkcs3"
+#  define NID_pkcs3                       27
+#  define OBJ_pkcs3                       OBJ_pkcs,3L
+
+#  define LN_dhKeyAgreement               "dhKeyAgreement"
+#  define NID_dhKeyAgreement              28
+#  define OBJ_dhKeyAgreement              OBJ_pkcs3,1L
+
+#  define SN_des_ecb                      "DES-ECB"
+#  define LN_des_ecb                      "des-ecb"
+#  define NID_des_ecb                     29
+#  define OBJ_des_ecb                     OBJ_algorithm,6L
+
+#  define SN_des_cfb64                    "DES-CFB"
+#  define LN_des_cfb64                    "des-cfb"
+#  define NID_des_cfb64                   30
+/* IV + num */
+#  define OBJ_des_cfb64                   OBJ_algorithm,9L
+
+#  define SN_des_cbc                      "DES-CBC"
+#  define LN_des_cbc                      "des-cbc"
+#  define NID_des_cbc                     31
+/* IV */
+#  define OBJ_des_cbc                     OBJ_algorithm,7L
+
+#  define SN_des_ede                      "DES-EDE"
+#  define LN_des_ede                      "des-ede"
+#  define NID_des_ede                     32
+/* ?? */
+#  define OBJ_des_ede                     OBJ_algorithm,17L
+
+#  define SN_des_ede3                     "DES-EDE3"
+#  define LN_des_ede3                     "des-ede3"
+#  define NID_des_ede3                    33
+
+#  define SN_idea_cbc                     "IDEA-CBC"
+#  define LN_idea_cbc                     "idea-cbc"
+#  define NID_idea_cbc                    34
+#  define OBJ_idea_cbc                    1L,3L,6L,1L,4L,1L,188L,7L,1L,1L,2L
+
+#  define SN_idea_cfb64                   "IDEA-CFB"
+#  define LN_idea_cfb64                   "idea-cfb"
+#  define NID_idea_cfb64                  35
+
+#  define SN_idea_ecb                     "IDEA-ECB"
+#  define LN_idea_ecb                     "idea-ecb"
+#  define NID_idea_ecb                    36
+
+#  define SN_rc2_cbc                      "RC2-CBC"
+#  define LN_rc2_cbc                      "rc2-cbc"
+#  define NID_rc2_cbc                     37
+#  define OBJ_rc2_cbc                     OBJ_rsadsi,3L,2L
+
+#  define SN_rc2_ecb                      "RC2-ECB"
+#  define LN_rc2_ecb                      "rc2-ecb"
+#  define NID_rc2_ecb                     38
+
+#  define SN_rc2_cfb64                    "RC2-CFB"
+#  define LN_rc2_cfb64                    "rc2-cfb"
+#  define NID_rc2_cfb64                   39
+
+#  define SN_rc2_ofb64                    "RC2-OFB"
+#  define LN_rc2_ofb64                    "rc2-ofb"
+#  define NID_rc2_ofb64                   40
+
+#  define SN_sha                          "SHA"
+#  define LN_sha                          "sha"
+#  define NID_sha                         41
+#  define OBJ_sha                         OBJ_algorithm,18L
+
+#  define SN_shaWithRSAEncryption         "RSA-SHA"
+#  define LN_shaWithRSAEncryption         "shaWithRSAEncryption"
+#  define NID_shaWithRSAEncryption        42
+#  define OBJ_shaWithRSAEncryption        OBJ_algorithm,15L
+
+#  define SN_des_ede_cbc                  "DES-EDE-CBC"
+#  define LN_des_ede_cbc                  "des-ede-cbc"
+#  define NID_des_ede_cbc                 43
+
+#  define SN_des_ede3_cbc                 "DES-EDE3-CBC"
+#  define LN_des_ede3_cbc                 "des-ede3-cbc"
+#  define NID_des_ede3_cbc                44
+#  define OBJ_des_ede3_cbc                OBJ_rsadsi,3L,7L
+
+#  define SN_des_ofb64                    "DES-OFB"
+#  define LN_des_ofb64                    "des-ofb"
+#  define NID_des_ofb64                   45
+#  define OBJ_des_ofb64                   OBJ_algorithm,8L
+
+#  define SN_idea_ofb64                   "IDEA-OFB"
+#  define LN_idea_ofb64                   "idea-ofb"
+#  define NID_idea_ofb64                  46
+
+#  define LN_pkcs9                        "pkcs9"
+#  define NID_pkcs9                       47
+#  define OBJ_pkcs9                       OBJ_pkcs,9L
+
+#  define SN_pkcs9_emailAddress           "Email"
+#  define LN_pkcs9_emailAddress           "emailAddress"
+#  define NID_pkcs9_emailAddress          48
+#  define OBJ_pkcs9_emailAddress          OBJ_pkcs9,1L
+
+#  define LN_pkcs9_unstructuredName       "unstructuredName"
+#  define NID_pkcs9_unstructuredName      49
+#  define OBJ_pkcs9_unstructuredName      OBJ_pkcs9,2L
+
+#  define LN_pkcs9_contentType            "contentType"
+#  define NID_pkcs9_contentType           50
+#  define OBJ_pkcs9_contentType           OBJ_pkcs9,3L
+
+#  define LN_pkcs9_messageDigest          "messageDigest"
+#  define NID_pkcs9_messageDigest         51
+#  define OBJ_pkcs9_messageDigest         OBJ_pkcs9,4L
+
+#  define LN_pkcs9_signingTime            "signingTime"
+#  define NID_pkcs9_signingTime           52
+#  define OBJ_pkcs9_signingTime           OBJ_pkcs9,5L
+
+#  define LN_pkcs9_countersignature       "countersignature"
+#  define NID_pkcs9_countersignature      53
+#  define OBJ_pkcs9_countersignature      OBJ_pkcs9,6L
+
+#  define LN_pkcs9_challengePassword      "challengePassword"
+#  define NID_pkcs9_challengePassword     54
+#  define OBJ_pkcs9_challengePassword     OBJ_pkcs9,7L
+
+#  define LN_pkcs9_unstructuredAddress    "unstructuredAddress"
+#  define NID_pkcs9_unstructuredAddress   55
+#  define OBJ_pkcs9_unstructuredAddress   OBJ_pkcs9,8L
+
+#  define LN_pkcs9_extCertAttributes      "extendedCertificateAttributes"
+#  define NID_pkcs9_extCertAttributes     56
+#  define OBJ_pkcs9_extCertAttributes     OBJ_pkcs9,9L
+
+#  define SN_netscape                     "Netscape"
+#  define LN_netscape                     "Netscape Communications Corp."
+#  define NID_netscape                    57
+#  define OBJ_netscape                    2L,16L,840L,1L,113730L
+
+#  define SN_netscape_cert_extension      "nsCertExt"
+#  define LN_netscape_cert_extension      "Netscape Certificate Extension"
+#  define NID_netscape_cert_extension     58
+#  define OBJ_netscape_cert_extension     OBJ_netscape,1L
+
+#  define SN_netscape_data_type           "nsDataType"
+#  define LN_netscape_data_type           "Netscape Data Type"
+#  define NID_netscape_data_type          59
+#  define OBJ_netscape_data_type          OBJ_netscape,2L
+
+#  define SN_des_ede_cfb64                "DES-EDE-CFB"
+#  define LN_des_ede_cfb64                "des-ede-cfb"
+#  define NID_des_ede_cfb64               60
+
+#  define SN_des_ede3_cfb64               "DES-EDE3-CFB"
+#  define LN_des_ede3_cfb64               "des-ede3-cfb"
+#  define NID_des_ede3_cfb64              61
+
+#  define SN_des_ede_ofb64                "DES-EDE-OFB"
+#  define LN_des_ede_ofb64                "des-ede-ofb"
+#  define NID_des_ede_ofb64               62
+
+#  define SN_des_ede3_ofb64               "DES-EDE3-OFB"
+#  define LN_des_ede3_ofb64               "des-ede3-ofb"
+#  define NID_des_ede3_ofb64              63
+
+/* I'm not sure about the object ID */
+#  define SN_sha1                         "SHA1"
+#  define LN_sha1                         "sha1"
+#  define NID_sha1                        64
+#  define OBJ_sha1                        OBJ_algorithm,26L
+/* 28 Jun 1996 - eay */
+/* #define OBJ_sha1                     1L,3L,14L,2L,26L,05L <- wrong */
+
+#  define SN_sha1WithRSAEncryption        "RSA-SHA1"
+#  define LN_sha1WithRSAEncryption        "sha1WithRSAEncryption"
+#  define NID_sha1WithRSAEncryption       65
+#  define OBJ_sha1WithRSAEncryption       OBJ_pkcs,1L,5L
+
+#  define SN_dsaWithSHA                   "DSA-SHA"
+#  define LN_dsaWithSHA                   "dsaWithSHA"
+#  define NID_dsaWithSHA                  66
+#  define OBJ_dsaWithSHA                  OBJ_algorithm,13L
+
+#  define SN_dsa_2                        "DSA-old"
+#  define LN_dsa_2                        "dsaEncryption-old"
+#  define NID_dsa_2                       67
+#  define OBJ_dsa_2                       OBJ_algorithm,12L
+
+/* proposed by microsoft to RSA */
+#  define SN_pbeWithSHA1AndRC2_CBC        "PBE-SHA1-RC2-64"
+#  define LN_pbeWithSHA1AndRC2_CBC        "pbeWithSHA1AndRC2-CBC"
+#  define NID_pbeWithSHA1AndRC2_CBC       68
+#  define OBJ_pbeWithSHA1AndRC2_CBC       OBJ_pkcs,5L,11L
+
+/*
+ * proposed by microsoft to RSA as pbeWithSHA1AndRC4: it is now defined
+ * explicitly in PKCS#5 v2.0 as id-PBKDF2 which is something completely
+ * different.
+ */
+#  define LN_id_pbkdf2                    "PBKDF2"
+#  define NID_id_pbkdf2                   69
+#  define OBJ_id_pbkdf2                   OBJ_pkcs,5L,12L
+
+#  define SN_dsaWithSHA1_2                "DSA-SHA1-old"
+#  define LN_dsaWithSHA1_2                "dsaWithSHA1-old"
+#  define NID_dsaWithSHA1_2               70
+/* Got this one from 'sdn706r20.pdf' which is actually an NSA document :-) */
+#  define OBJ_dsaWithSHA1_2               OBJ_algorithm,27L
+
+#  define SN_netscape_cert_type           "nsCertType"
+#  define LN_netscape_cert_type           "Netscape Cert Type"
+#  define NID_netscape_cert_type          71
+#  define OBJ_netscape_cert_type          OBJ_netscape_cert_extension,1L
+
+#  define SN_netscape_base_url            "nsBaseUrl"
+#  define LN_netscape_base_url            "Netscape Base Url"
+#  define NID_netscape_base_url           72
+#  define OBJ_netscape_base_url           OBJ_netscape_cert_extension,2L
+
+#  define SN_netscape_revocation_url      "nsRevocationUrl"
+#  define LN_netscape_revocation_url      "Netscape Revocation Url"
+#  define NID_netscape_revocation_url     73
+#  define OBJ_netscape_revocation_url     OBJ_netscape_cert_extension,3L
+
+#  define SN_netscape_ca_revocation_url   "nsCaRevocationUrl"
+#  define LN_netscape_ca_revocation_url   "Netscape CA Revocation Url"
+#  define NID_netscape_ca_revocation_url  74
+#  define OBJ_netscape_ca_revocation_url  OBJ_netscape_cert_extension,4L
+
+#  define SN_netscape_renewal_url         "nsRenewalUrl"
+#  define LN_netscape_renewal_url         "Netscape Renewal Url"
+#  define NID_netscape_renewal_url        75
+#  define OBJ_netscape_renewal_url        OBJ_netscape_cert_extension,7L
+
+#  define SN_netscape_ca_policy_url       "nsCaPolicyUrl"
+#  define LN_netscape_ca_policy_url       "Netscape CA Policy Url"
+#  define NID_netscape_ca_policy_url      76
+#  define OBJ_netscape_ca_policy_url      OBJ_netscape_cert_extension,8L
+
+#  define SN_netscape_ssl_server_name     "nsSslServerName"
+#  define LN_netscape_ssl_server_name     "Netscape SSL Server Name"
+#  define NID_netscape_ssl_server_name    77
+#  define OBJ_netscape_ssl_server_name    OBJ_netscape_cert_extension,12L
+
+#  define SN_netscape_comment             "nsComment"
+#  define LN_netscape_comment             "Netscape Comment"
+#  define NID_netscape_comment            78
+#  define OBJ_netscape_comment            OBJ_netscape_cert_extension,13L
+
+#  define SN_netscape_cert_sequence       "nsCertSequence"
+#  define LN_netscape_cert_sequence       "Netscape Certificate Sequence"
+#  define NID_netscape_cert_sequence      79
+#  define OBJ_netscape_cert_sequence      OBJ_netscape_data_type,5L
+
+#  define SN_desx_cbc                     "DESX-CBC"
+#  define LN_desx_cbc                     "desx-cbc"
+#  define NID_desx_cbc                    80
+
+#  define SN_id_ce                        "id-ce"
+#  define NID_id_ce                       81
+#  define OBJ_id_ce                       2L,5L,29L
+
+#  define SN_subject_key_identifier       "subjectKeyIdentifier"
+#  define LN_subject_key_identifier       "X509v3 Subject Key Identifier"
+#  define NID_subject_key_identifier      82
+#  define OBJ_subject_key_identifier      OBJ_id_ce,14L
+
+#  define SN_key_usage                    "keyUsage"
+#  define LN_key_usage                    "X509v3 Key Usage"
+#  define NID_key_usage                   83
+#  define OBJ_key_usage                   OBJ_id_ce,15L
+
+#  define SN_private_key_usage_period     "privateKeyUsagePeriod"
+#  define LN_private_key_usage_period     "X509v3 Private Key Usage Period"
+#  define NID_private_key_usage_period    84
+#  define OBJ_private_key_usage_period    OBJ_id_ce,16L
+
+#  define SN_subject_alt_name             "subjectAltName"
+#  define LN_subject_alt_name             "X509v3 Subject Alternative Name"
+#  define NID_subject_alt_name            85
+#  define OBJ_subject_alt_name            OBJ_id_ce,17L
+
+#  define SN_issuer_alt_name              "issuerAltName"
+#  define LN_issuer_alt_name              "X509v3 Issuer Alternative Name"
+#  define NID_issuer_alt_name             86
+#  define OBJ_issuer_alt_name             OBJ_id_ce,18L
+
+#  define SN_basic_constraints            "basicConstraints"
+#  define LN_basic_constraints            "X509v3 Basic Constraints"
+#  define NID_basic_constraints           87
+#  define OBJ_basic_constraints           OBJ_id_ce,19L
+
+#  define SN_crl_number                   "crlNumber"
+#  define LN_crl_number                   "X509v3 CRL Number"
+#  define NID_crl_number                  88
+#  define OBJ_crl_number                  OBJ_id_ce,20L
+
+#  define SN_certificate_policies         "certificatePolicies"
+#  define LN_certificate_policies         "X509v3 Certificate Policies"
+#  define NID_certificate_policies        89
+#  define OBJ_certificate_policies        OBJ_id_ce,32L
+
+#  define SN_authority_key_identifier     "authorityKeyIdentifier"
+#  define LN_authority_key_identifier     "X509v3 Authority Key Identifier"
+#  define NID_authority_key_identifier    90
+#  define OBJ_authority_key_identifier    OBJ_id_ce,35L
+
+#  define SN_bf_cbc                       "BF-CBC"
+#  define LN_bf_cbc                       "bf-cbc"
+#  define NID_bf_cbc                      91
+#  define OBJ_bf_cbc                      1L,3L,6L,1L,4L,1L,3029L,1L,2L
+
+#  define SN_bf_ecb                       "BF-ECB"
+#  define LN_bf_ecb                       "bf-ecb"
+#  define NID_bf_ecb                      92
+
+#  define SN_bf_cfb64                     "BF-CFB"
+#  define LN_bf_cfb64                     "bf-cfb"
+#  define NID_bf_cfb64                    93
+
+#  define SN_bf_ofb64                     "BF-OFB"
+#  define LN_bf_ofb64                     "bf-ofb"
+#  define NID_bf_ofb64                    94
+
+#  define SN_mdc2                         "MDC2"
+#  define LN_mdc2                         "mdc2"
+#  define NID_mdc2                        95
+#  define OBJ_mdc2                        2L,5L,8L,3L,101L
+/* An alternative?                      1L,3L,14L,3L,2L,19L */
+
+#  define SN_mdc2WithRSA                  "RSA-MDC2"
+#  define LN_mdc2WithRSA                  "mdc2withRSA"
+#  define NID_mdc2WithRSA                 96
+#  define OBJ_mdc2WithRSA                 2L,5L,8L,3L,100L
+
+#  define SN_rc4_40                       "RC4-40"
+#  define LN_rc4_40                       "rc4-40"
+#  define NID_rc4_40                      97
+
+#  define SN_rc2_40_cbc                   "RC2-40-CBC"
+#  define LN_rc2_40_cbc                   "rc2-40-cbc"
+#  define NID_rc2_40_cbc                  98
+
+#  define SN_givenName                    "G"
+#  define LN_givenName                    "givenName"
+#  define NID_givenName                   99
+#  define OBJ_givenName                   OBJ_X509,42L
+
+#  define SN_surname                      "S"
+#  define LN_surname                      "surname"
+#  define NID_surname                     100
+#  define OBJ_surname                     OBJ_X509,4L
+
+#  define SN_initials                     "I"
+#  define LN_initials                     "initials"
+#  define NID_initials                    101
+#  define OBJ_initials                    OBJ_X509,43L
+
+#  define SN_uniqueIdentifier             "UID"
+#  define LN_uniqueIdentifier             "uniqueIdentifier"
+#  define NID_uniqueIdentifier            102
+#  define OBJ_uniqueIdentifier            OBJ_X509,45L
+
+#  define SN_crl_distribution_points      "crlDistributionPoints"
+#  define LN_crl_distribution_points      "X509v3 CRL Distribution Points"
+#  define NID_crl_distribution_points     103
+#  define OBJ_crl_distribution_points     OBJ_id_ce,31L
+
+#  define SN_md5WithRSA                   "RSA-NP-MD5"
+#  define LN_md5WithRSA                   "md5WithRSA"
+#  define NID_md5WithRSA                  104
+#  define OBJ_md5WithRSA                  OBJ_algorithm,3L
+
+#  define SN_serialNumber                 "SN"
+#  define LN_serialNumber                 "serialNumber"
+#  define NID_serialNumber                105
+#  define OBJ_serialNumber                OBJ_X509,5L
+
+#  define SN_title                        "T"
+#  define LN_title                        "title"
+#  define NID_title                       106
+#  define OBJ_title                       OBJ_X509,12L
+
+#  define SN_description                  "D"
+#  define LN_description                  "description"
+#  define NID_description                 107
+#  define OBJ_description                 OBJ_X509,13L
+
+/* CAST5 is CAST-128, I'm just sticking with the documentation */
+#  define SN_cast5_cbc                    "CAST5-CBC"
+#  define LN_cast5_cbc                    "cast5-cbc"
+#  define NID_cast5_cbc                   108
+#  define OBJ_cast5_cbc                   1L,2L,840L,113533L,7L,66L,10L
+
+#  define SN_cast5_ecb                    "CAST5-ECB"
+#  define LN_cast5_ecb                    "cast5-ecb"
+#  define NID_cast5_ecb                   109
+
+#  define SN_cast5_cfb64                  "CAST5-CFB"
+#  define LN_cast5_cfb64                  "cast5-cfb"
+#  define NID_cast5_cfb64                 110
+
+#  define SN_cast5_ofb64                  "CAST5-OFB"
+#  define LN_cast5_ofb64                  "cast5-ofb"
+#  define NID_cast5_ofb64                 111
+
+#  define LN_pbeWithMD5AndCast5_CBC       "pbeWithMD5AndCast5CBC"
+#  define NID_pbeWithMD5AndCast5_CBC      112
+#  define OBJ_pbeWithMD5AndCast5_CBC      1L,2L,840L,113533L,7L,66L,12L
+
+/*-
+ * This is one sun will soon be using :-(
+ * id-dsa-with-sha1 ID  ::= {
+ *   iso(1) member-body(2) us(840) x9-57 (10040) x9cm(4) 3 }
+ */
+#  define SN_dsaWithSHA1                  "DSA-SHA1"
+#  define LN_dsaWithSHA1                  "dsaWithSHA1"
+#  define NID_dsaWithSHA1                 113
+#  define OBJ_dsaWithSHA1                 1L,2L,840L,10040L,4L,3L
+
+#  define NID_md5_sha1                    114
+#  define SN_md5_sha1                     "MD5-SHA1"
+#  define LN_md5_sha1                     "md5-sha1"
+
+#  define SN_sha1WithRSA                  "RSA-SHA1-2"
+#  define LN_sha1WithRSA                  "sha1WithRSA"
+#  define NID_sha1WithRSA                 115
+#  define OBJ_sha1WithRSA                 OBJ_algorithm,29L
+
+#  define SN_dsa                          "DSA"
+#  define LN_dsa                          "dsaEncryption"
+#  define NID_dsa                         116
+#  define OBJ_dsa                         1L,2L,840L,10040L,4L,1L
+
+#  define SN_ripemd160                    "RIPEMD160"
+#  define LN_ripemd160                    "ripemd160"
+#  define NID_ripemd160                   117
+#  define OBJ_ripemd160                   1L,3L,36L,3L,2L,1L
+
+/*
+ * The name should actually be rsaSignatureWithripemd160, but I'm going to
+ * continue using the convention I'm using with the other ciphers
+ */
+#  define SN_ripemd160WithRSA             "RSA-RIPEMD160"
+#  define LN_ripemd160WithRSA             "ripemd160WithRSA"
+#  define NID_ripemd160WithRSA            119
+#  define OBJ_ripemd160WithRSA            1L,3L,36L,3L,3L,1L,2L
+
+/*-
+ * Taken from rfc2040
+ *  RC5_CBC_Parameters ::= SEQUENCE {
+ *      version           INTEGER (v1_0(16)),
+ *      rounds            INTEGER (8..127),
+ *      blockSizeInBits   INTEGER (64, 128),
+ *      iv                OCTET STRING OPTIONAL
+ *      }
+ */
+#  define SN_rc5_cbc                      "RC5-CBC"
+#  define LN_rc5_cbc                      "rc5-cbc"
+#  define NID_rc5_cbc                     120
+#  define OBJ_rc5_cbc                     OBJ_rsadsi,3L,8L
+
+#  define SN_rc5_ecb                      "RC5-ECB"
+#  define LN_rc5_ecb                      "rc5-ecb"
+#  define NID_rc5_ecb                     121
+
+#  define SN_rc5_cfb64                    "RC5-CFB"
+#  define LN_rc5_cfb64                    "rc5-cfb"
+#  define NID_rc5_cfb64                   122
+
+#  define SN_rc5_ofb64                    "RC5-OFB"
+#  define LN_rc5_ofb64                    "rc5-ofb"
+#  define NID_rc5_ofb64                   123
+
+#  define SN_rle_compression              "RLE"
+#  define LN_rle_compression              "run length compression"
+#  define NID_rle_compression             124
+#  define OBJ_rle_compression             1L,1L,1L,1L,666L,1L
+
+#  define SN_zlib_compression             "ZLIB"
+#  define LN_zlib_compression             "zlib compression"
+#  define NID_zlib_compression            125
+#  define OBJ_zlib_compression            1L,1L,1L,1L,666L,2L
+
+#  define SN_ext_key_usage                "extendedKeyUsage"
+#  define LN_ext_key_usage                "X509v3 Extended Key Usage"
+#  define NID_ext_key_usage               126
+#  define OBJ_ext_key_usage               OBJ_id_ce,37
+
+#  define SN_id_pkix                      "PKIX"
+#  define NID_id_pkix                     127
+#  define OBJ_id_pkix                     1L,3L,6L,1L,5L,5L,7L
+
+#  define SN_id_kp                        "id-kp"
+#  define NID_id_kp                       128
+#  define OBJ_id_kp                       OBJ_id_pkix,3L
+
+/* PKIX extended key usage OIDs */
+
+#  define SN_server_auth                  "serverAuth"
+#  define LN_server_auth                  "TLS Web Server Authentication"
+#  define NID_server_auth                 129
+#  define OBJ_server_auth                 OBJ_id_kp,1L
+
+#  define SN_client_auth                  "clientAuth"
+#  define LN_client_auth                  "TLS Web Client Authentication"
+#  define NID_client_auth                 130
+#  define OBJ_client_auth                 OBJ_id_kp,2L
+
+#  define SN_code_sign                    "codeSigning"
+#  define LN_code_sign                    "Code Signing"
+#  define NID_code_sign                   131
+#  define OBJ_code_sign                   OBJ_id_kp,3L
+
+#  define SN_email_protect                "emailProtection"
+#  define LN_email_protect                "E-mail Protection"
+#  define NID_email_protect               132
+#  define OBJ_email_protect               OBJ_id_kp,4L
+
+#  define SN_time_stamp                   "timeStamping"
+#  define LN_time_stamp                   "Time Stamping"
+#  define NID_time_stamp                  133
+#  define OBJ_time_stamp                  OBJ_id_kp,8L
+
+/* Additional extended key usage OIDs: Microsoft */
+
+#  define SN_ms_code_ind                  "msCodeInd"
+#  define LN_ms_code_ind                  "Microsoft Individual Code Signing"
+#  define NID_ms_code_ind                 134
+#  define OBJ_ms_code_ind                 1L,3L,6L,1L,4L,1L,311L,2L,1L,21L
+
+#  define SN_ms_code_com                  "msCodeCom"
+#  define LN_ms_code_com                  "Microsoft Commercial Code Signing"
+#  define NID_ms_code_com                 135
+#  define OBJ_ms_code_com                 1L,3L,6L,1L,4L,1L,311L,2L,1L,22L
+
+#  define SN_ms_ctl_sign                  "msCTLSign"
+#  define LN_ms_ctl_sign                  "Microsoft Trust List Signing"
+#  define NID_ms_ctl_sign                 136
+#  define OBJ_ms_ctl_sign                 1L,3L,6L,1L,4L,1L,311L,10L,3L,1L
+
+#  define SN_ms_sgc                       "msSGC"
+#  define LN_ms_sgc                       "Microsoft Server Gated Crypto"
+#  define NID_ms_sgc                      137
+#  define OBJ_ms_sgc                      1L,3L,6L,1L,4L,1L,311L,10L,3L,3L
+
+#  define SN_ms_efs                       "msEFS"
+#  define LN_ms_efs                       "Microsoft Encrypted File System"
+#  define NID_ms_efs                      138
+#  define OBJ_ms_efs                      1L,3L,6L,1L,4L,1L,311L,10L,3L,4L
+
+/* Additional usage: Netscape */
+
+#  define SN_ns_sgc                       "nsSGC"
+#  define LN_ns_sgc                       "Netscape Server Gated Crypto"
+#  define NID_ns_sgc                      139
+#  define OBJ_ns_sgc                      OBJ_netscape,4L,1L
+
+#  define SN_delta_crl                    "deltaCRL"
+#  define LN_delta_crl                    "X509v3 Delta CRL Indicator"
+#  define NID_delta_crl                   140
+#  define OBJ_delta_crl                   OBJ_id_ce,27L
+
+#  define SN_crl_reason                   "CRLReason"
+#  define LN_crl_reason                   "CRL Reason Code"
+#  define NID_crl_reason                  141
+#  define OBJ_crl_reason                  OBJ_id_ce,21L
+
+#  define SN_invalidity_date              "invalidityDate"
+#  define LN_invalidity_date              "Invalidity Date"
+#  define NID_invalidity_date             142
+#  define OBJ_invalidity_date             OBJ_id_ce,24L
+
+#  define SN_sxnet                        "SXNetID"
+#  define LN_sxnet                        "Strong Extranet ID"
+#  define NID_sxnet                       143
+#  define OBJ_sxnet                       1L,3L,101L,1L,4L,1L
+
+/* PKCS12 and related OBJECT IDENTIFIERS */
+
+#  define OBJ_pkcs12                      OBJ_pkcs,12L
+#  define OBJ_pkcs12_pbeids               OBJ_pkcs12, 1
+
+#  define SN_pbe_WithSHA1And128BitRC4     "PBE-SHA1-RC4-128"
+#  define LN_pbe_WithSHA1And128BitRC4     "pbeWithSHA1And128BitRC4"
+#  define NID_pbe_WithSHA1And128BitRC4    144
+#  define OBJ_pbe_WithSHA1And128BitRC4    OBJ_pkcs12_pbeids, 1L
+
+#  define SN_pbe_WithSHA1And40BitRC4      "PBE-SHA1-RC4-40"
+#  define LN_pbe_WithSHA1And40BitRC4      "pbeWithSHA1And40BitRC4"
+#  define NID_pbe_WithSHA1And40BitRC4     145
+#  define OBJ_pbe_WithSHA1And40BitRC4     OBJ_pkcs12_pbeids, 2L
+
+#  define SN_pbe_WithSHA1And3_Key_TripleDES_CBC   "PBE-SHA1-3DES"
+#  define LN_pbe_WithSHA1And3_Key_TripleDES_CBC   "pbeWithSHA1And3-KeyTripleDES-CBC"
+#  define NID_pbe_WithSHA1And3_Key_TripleDES_CBC  146
+#  define OBJ_pbe_WithSHA1And3_Key_TripleDES_CBC  OBJ_pkcs12_pbeids, 3L
+
+#  define SN_pbe_WithSHA1And2_Key_TripleDES_CBC   "PBE-SHA1-2DES"
+#  define LN_pbe_WithSHA1And2_Key_TripleDES_CBC   "pbeWithSHA1And2-KeyTripleDES-CBC"
+#  define NID_pbe_WithSHA1And2_Key_TripleDES_CBC  147
+#  define OBJ_pbe_WithSHA1And2_Key_TripleDES_CBC  OBJ_pkcs12_pbeids, 4L
+
+#  define SN_pbe_WithSHA1And128BitRC2_CBC         "PBE-SHA1-RC2-128"
+#  define LN_pbe_WithSHA1And128BitRC2_CBC         "pbeWithSHA1And128BitRC2-CBC"
+#  define NID_pbe_WithSHA1And128BitRC2_CBC        148
+#  define OBJ_pbe_WithSHA1And128BitRC2_CBC        OBJ_pkcs12_pbeids, 5L
+
+#  define SN_pbe_WithSHA1And40BitRC2_CBC  "PBE-SHA1-RC2-40"
+#  define LN_pbe_WithSHA1And40BitRC2_CBC  "pbeWithSHA1And40BitRC2-CBC"
+#  define NID_pbe_WithSHA1And40BitRC2_CBC 149
+#  define OBJ_pbe_WithSHA1And40BitRC2_CBC OBJ_pkcs12_pbeids, 6L
+
+#  define OBJ_pkcs12_Version1     OBJ_pkcs12, 10L
+
+#  define OBJ_pkcs12_BagIds       OBJ_pkcs12_Version1, 1L
+
+#  define LN_keyBag               "keyBag"
+#  define NID_keyBag              150
+#  define OBJ_keyBag              OBJ_pkcs12_BagIds, 1L
+
+#  define LN_pkcs8ShroudedKeyBag  "pkcs8ShroudedKeyBag"
+#  define NID_pkcs8ShroudedKeyBag 151
+#  define OBJ_pkcs8ShroudedKeyBag OBJ_pkcs12_BagIds, 2L
+
+#  define LN_certBag              "certBag"
+#  define NID_certBag             152
+#  define OBJ_certBag             OBJ_pkcs12_BagIds, 3L
+
+#  define LN_crlBag               "crlBag"
+#  define NID_crlBag              153
+#  define OBJ_crlBag              OBJ_pkcs12_BagIds, 4L
+
+#  define LN_secretBag            "secretBag"
+#  define NID_secretBag           154
+#  define OBJ_secretBag           OBJ_pkcs12_BagIds, 5L
+
+#  define LN_safeContentsBag      "safeContentsBag"
+#  define NID_safeContentsBag     155
+#  define OBJ_safeContentsBag     OBJ_pkcs12_BagIds, 6L
+
+#  define LN_friendlyName         "friendlyName"
+#  define NID_friendlyName        156
+#  define OBJ_friendlyName        OBJ_pkcs9, 20L
+
+#  define LN_localKeyID           "localKeyID"
+#  define NID_localKeyID          157
+#  define OBJ_localKeyID          OBJ_pkcs9, 21L
+
+#  define OBJ_certTypes           OBJ_pkcs9, 22L
+
+#  define LN_x509Certificate      "x509Certificate"
+#  define NID_x509Certificate     158
+#  define OBJ_x509Certificate     OBJ_certTypes, 1L
+
+#  define LN_sdsiCertificate      "sdsiCertificate"
+#  define NID_sdsiCertificate     159
+#  define OBJ_sdsiCertificate     OBJ_certTypes, 2L
+
+#  define OBJ_crlTypes            OBJ_pkcs9, 23L
+
+#  define LN_x509Crl              "x509Crl"
+#  define NID_x509Crl             160
+#  define OBJ_x509Crl             OBJ_crlTypes, 1L
+
+/* PKCS#5 v2 OIDs */
+
+#  define LN_pbes2                "PBES2"
+#  define NID_pbes2               161
+#  define OBJ_pbes2               OBJ_pkcs,5L,13L
+
+#  define LN_pbmac1               "PBMAC1"
+#  define NID_pbmac1              162
+#  define OBJ_pbmac1              OBJ_pkcs,5L,14L
+
+#  define LN_hmacWithSHA1         "hmacWithSHA1"
+#  define NID_hmacWithSHA1        163
+#  define OBJ_hmacWithSHA1        OBJ_rsadsi,2L,7L
+
+/* Policy Qualifier Ids */
+
+#  define LN_id_qt_cps            "Policy Qualifier CPS"
+#  define SN_id_qt_cps            "id-qt-cps"
+#  define NID_id_qt_cps           164
+#  define OBJ_id_qt_cps           OBJ_id_pkix,2L,1L
+
+#  define LN_id_qt_unotice        "Policy Qualifier User Notice"
+#  define SN_id_qt_unotice        "id-qt-unotice"
+#  define NID_id_qt_unotice       165
+#  define OBJ_id_qt_unotice       OBJ_id_pkix,2L,2L
+
+#  define SN_rc2_64_cbc                   "RC2-64-CBC"
+#  define LN_rc2_64_cbc                   "rc2-64-cbc"
+#  define NID_rc2_64_cbc                  166
+
+#  define SN_SMIMECapabilities            "SMIME-CAPS"
+#  define LN_SMIMECapabilities            "S/MIME Capabilities"
+#  define NID_SMIMECapabilities           167
+#  define OBJ_SMIMECapabilities           OBJ_pkcs9,15L
+
+#  define SN_pbeWithMD2AndRC2_CBC         "PBE-MD2-RC2-64"
+#  define LN_pbeWithMD2AndRC2_CBC         "pbeWithMD2AndRC2-CBC"
+#  define NID_pbeWithMD2AndRC2_CBC        168
+#  define OBJ_pbeWithMD2AndRC2_CBC        OBJ_pkcs,5L,4L
+
+#  define SN_pbeWithMD5AndRC2_CBC         "PBE-MD5-RC2-64"
+#  define LN_pbeWithMD5AndRC2_CBC         "pbeWithMD5AndRC2-CBC"
+#  define NID_pbeWithMD5AndRC2_CBC        169
+#  define OBJ_pbeWithMD5AndRC2_CBC        OBJ_pkcs,5L,6L
+
+#  define SN_pbeWithSHA1AndDES_CBC        "PBE-SHA1-DES"
+#  define LN_pbeWithSHA1AndDES_CBC        "pbeWithSHA1AndDES-CBC"
+#  define NID_pbeWithSHA1AndDES_CBC       170
+#  define OBJ_pbeWithSHA1AndDES_CBC       OBJ_pkcs,5L,10L
+
+/* Extension request OIDs */
+
+#  define LN_ms_ext_req                   "Microsoft Extension Request"
+#  define SN_ms_ext_req                   "msExtReq"
+#  define NID_ms_ext_req                  171
+#  define OBJ_ms_ext_req                  1L,3L,6L,1L,4L,1L,311L,2L,1L,14L
+
+#  define LN_ext_req                      "Extension Request"
+#  define SN_ext_req                      "extReq"
+#  define NID_ext_req                     172
+#  define OBJ_ext_req                     OBJ_pkcs9,14L
+
+#  define SN_name                         "name"
+#  define LN_name                         "name"
+#  define NID_name                        173
+#  define OBJ_name                        OBJ_X509,41L
+
+#  define SN_dnQualifier                  "dnQualifier"
+#  define LN_dnQualifier                  "dnQualifier"
+#  define NID_dnQualifier                 174
+#  define OBJ_dnQualifier                 OBJ_X509,46L
+
+#  define SN_id_pe                        "id-pe"
+#  define NID_id_pe                       175
+#  define OBJ_id_pe                       OBJ_id_pkix,1L
+
+#  define SN_id_ad                        "id-ad"
+#  define NID_id_ad                       176
+#  define OBJ_id_ad                       OBJ_id_pkix,48L
+
+#  define SN_info_access                  "authorityInfoAccess"
+#  define LN_info_access                  "Authority Information Access"
+#  define NID_info_access                 177
+#  define OBJ_info_access                 OBJ_id_pe,1L
+
+#  define SN_ad_OCSP                      "OCSP"
+#  define LN_ad_OCSP                      "OCSP"
+#  define NID_ad_OCSP                     178
+#  define OBJ_ad_OCSP                     OBJ_id_ad,1L
+
+#  define SN_ad_ca_issuers                "caIssuers"
+#  define LN_ad_ca_issuers                "CA Issuers"
+#  define NID_ad_ca_issuers               179
+#  define OBJ_ad_ca_issuers               OBJ_id_ad,2L
+
+#  define SN_OCSP_sign                    "OCSPSigning"
+#  define LN_OCSP_sign                    "OCSP Signing"
+#  define NID_OCSP_sign                   180
+#  define OBJ_OCSP_sign                   OBJ_id_kp,9L
+# endif                         /* USE_OBJ_MAC */
+
+# include <openssl/bio.h>
+# include <openssl/asn1.h>
+
+# define OBJ_NAME_TYPE_UNDEF             0x00
+# define OBJ_NAME_TYPE_MD_METH           0x01
+# define OBJ_NAME_TYPE_CIPHER_METH       0x02
+# define OBJ_NAME_TYPE_PKEY_METH         0x03
+# define OBJ_NAME_TYPE_COMP_METH         0x04
+# define OBJ_NAME_TYPE_NUM               0x05
+
+# define OBJ_NAME_ALIAS                  0x8000
+
+# define OBJ_BSEARCH_VALUE_ON_NOMATCH            0x01
+# define OBJ_BSEARCH_FIRST_VALUE_ON_MATCH        0x02
+
+
+#ifdef  __cplusplus
+extern "C" {
+#endif
+
+typedef struct obj_name_st {
+    int type;
+    int alias;
+    const char *name;
+    const char *data;
+} OBJ_NAME;
+
+# define         OBJ_create_and_add_object(a,b,c) OBJ_create(a,b,c)
+
+int OBJ_NAME_init(void);
+int OBJ_NAME_new_index(unsigned long (*hash_func) (const char *),
+                       int (*cmp_func) (const char *, const char *),
+                       void (*free_func) (const char *, int, const char *));
+const char *OBJ_NAME_get(const char *name, int type);
+int OBJ_NAME_add(const char *name, int type, const char *data);
+int OBJ_NAME_remove(const char *name, int type);
+void OBJ_NAME_cleanup(int type); /* -1 for everything */
+void OBJ_NAME_do_all(int type, void (*fn) (const OBJ_NAME *, void *arg),
+                     void *arg);
+void OBJ_NAME_do_all_sorted(int type,
+                            void (*fn) (const OBJ_NAME *, void *arg),
+                            void *arg);
+
+ASN1_OBJECT *OBJ_dup(const ASN1_OBJECT *o);
+ASN1_OBJECT *OBJ_nid2obj(int n);
+const char *OBJ_nid2ln(int n);
+const char *OBJ_nid2sn(int n);
+int OBJ_obj2nid(const ASN1_OBJECT *o);
+ASN1_OBJECT *OBJ_txt2obj(const char *s, int no_name);
+int OBJ_obj2txt(char *buf, int buf_len, const ASN1_OBJECT *a, int no_name);
+int OBJ_txt2nid(const char *s);
+int OBJ_ln2nid(const char *s);
+int OBJ_sn2nid(const char *s);
+int OBJ_cmp(const ASN1_OBJECT *a, const ASN1_OBJECT *b);
+const void *OBJ_bsearch_(const void *key, const void *base, int num, int size,
+                         int (*cmp) (const void *, const void *));
+const void *OBJ_bsearch_ex_(const void *key, const void *base, int num,
+                            int size,
+                            int (*cmp) (const void *, const void *),
+                            int flags);
+
+# define _DECLARE_OBJ_BSEARCH_CMP_FN(scope, type1, type2, nm)    \
+  static int nm##_cmp_BSEARCH_CMP_FN(const void *, const void *); \
+  static int nm##_cmp(type1 const *, type2 const *); \
+  scope type2 * OBJ_bsearch_##nm(type1 *key, type2 const *base, int num)
+
+# define DECLARE_OBJ_BSEARCH_CMP_FN(type1, type2, cmp)   \
+  _DECLARE_OBJ_BSEARCH_CMP_FN(static, type1, type2, cmp)
+# define DECLARE_OBJ_BSEARCH_GLOBAL_CMP_FN(type1, type2, nm)     \
+  type2 * OBJ_bsearch_##nm(type1 *key, type2 const *base, int num)
+
+/*-
+ * Unsolved problem: if a type is actually a pointer type, like
+ * nid_triple is, then its impossible to get a const where you need
+ * it. Consider:
+ *
+ * typedef int nid_triple[3];
+ * const void *a_;
+ * const nid_triple const *a = a_;
+ *
+ * The assignement discards a const because what you really want is:
+ *
+ * const int const * const *a = a_;
+ *
+ * But if you do that, you lose the fact that a is an array of 3 ints,
+ * which breaks comparison functions.
+ *
+ * Thus we end up having to cast, sadly, or unpack the
+ * declarations. Or, as I finally did in this case, delcare nid_triple
+ * to be a struct, which it should have been in the first place.
+ *
+ * Ben, August 2008.
+ *
+ * Also, strictly speaking not all types need be const, but handling
+ * the non-constness means a lot of complication, and in practice
+ * comparison routines do always not touch their arguments.
+ */
+
+# define IMPLEMENT_OBJ_BSEARCH_CMP_FN(type1, type2, nm)  \
+  static int nm##_cmp_BSEARCH_CMP_FN(const void *a_, const void *b_)    \
+      { \
+      type1 const *a = a_; \
+      type2 const *b = b_; \
+      return nm##_cmp(a,b); \
+      } \
+  static type2 *OBJ_bsearch_##nm(type1 *key, type2 const *base, int num) \
+      { \
+      return (type2 *)OBJ_bsearch_(key, base, num, sizeof(type2), \
+                                        nm##_cmp_BSEARCH_CMP_FN); \
+      } \
+      extern void dummy_prototype(void)
+
+# define IMPLEMENT_OBJ_BSEARCH_GLOBAL_CMP_FN(type1, type2, nm)   \
+  static int nm##_cmp_BSEARCH_CMP_FN(const void *a_, const void *b_)    \
+      { \
+      type1 const *a = a_; \
+      type2 const *b = b_; \
+      return nm##_cmp(a,b); \
+      } \
+  type2 *OBJ_bsearch_##nm(type1 *key, type2 const *base, int num) \
+      { \
+      return (type2 *)OBJ_bsearch_(key, base, num, sizeof(type2), \
+                                        nm##_cmp_BSEARCH_CMP_FN); \
+      } \
+      extern void dummy_prototype(void)
+
+# define OBJ_bsearch(type1,key,type2,base,num,cmp)                              \
+  ((type2 *)OBJ_bsearch_(CHECKED_PTR_OF(type1,key),CHECKED_PTR_OF(type2,base), \
+                         num,sizeof(type2),                             \
+                         ((void)CHECKED_PTR_OF(type1,cmp##_type_1),     \
+                          (void)CHECKED_PTR_OF(type2,cmp##_type_2),     \
+                          cmp##_BSEARCH_CMP_FN)))
+
+# define OBJ_bsearch_ex(type1,key,type2,base,num,cmp,flags)                      \
+  ((type2 *)OBJ_bsearch_ex_(CHECKED_PTR_OF(type1,key),CHECKED_PTR_OF(type2,base), \
+                         num,sizeof(type2),                             \
+                         ((void)CHECKED_PTR_OF(type1,cmp##_type_1),     \
+                          (void)type_2=CHECKED_PTR_OF(type2,cmp##_type_2), \
+                          cmp##_BSEARCH_CMP_FN)),flags)
+
+int OBJ_new_nid(int num);
+int OBJ_add_object(const ASN1_OBJECT *obj);
+int OBJ_create(const char *oid, const char *sn, const char *ln);
+void OBJ_cleanup(void);
+int OBJ_create_objects(BIO *in);
+
+int OBJ_find_sigid_algs(int signid, int *pdig_nid, int *ppkey_nid);
+int OBJ_find_sigid_by_algs(int *psignid, int dig_nid, int pkey_nid);
+int OBJ_add_sigid(int signid, int dig_id, int pkey_id);
+void OBJ_sigid_free(void);
+
+extern int obj_cleanup_defer;
+void check_defer(int nid);
+
+/* BEGIN ERROR CODES */
+/*
+ * The following lines are auto generated by the script mkerr.pl. Any changes
+ * made after this point may be overwritten when the script is next run.
+ */
+void ERR_load_OBJ_strings(void);
+
+/* Error codes for the OBJ functions. */
+
+/* Function codes. */
+# define OBJ_F_OBJ_ADD_OBJECT                             105
+# define OBJ_F_OBJ_CREATE                                 100
+# define OBJ_F_OBJ_DUP                                    101
+# define OBJ_F_OBJ_NAME_NEW_INDEX                         106
+# define OBJ_F_OBJ_NID2LN                                 102
+# define OBJ_F_OBJ_NID2OBJ                                103
+# define OBJ_F_OBJ_NID2SN                                 104
+
+/* Reason codes. */
+# define OBJ_R_MALLOC_FAILURE                             100
+# define OBJ_R_UNKNOWN_NID                                101
+
+#ifdef  __cplusplus
+}
+#endif
+#endif

+ 637 - 0
libssh2/openssl/include/openssl/ocsp.h

@@ -0,0 +1,637 @@
+/* ocsp.h */
+/*
+ * Written by Tom Titchener <Tom_Titchener@groove.net> for the OpenSSL
+ * project.
+ */
+
+/*
+ * History: This file was transfered to Richard Levitte from CertCo by Kathy
+ * Weinhold in mid-spring 2000 to be included in OpenSSL or released as a
+ * patch kit.
+ */
+
+/* ====================================================================
+ * Copyright (c) 1998-2000 The OpenSSL 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. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    openssl-core@openssl.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED 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 OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS 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.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com).  This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+
+#ifndef HEADER_OCSP_H
+# define HEADER_OCSP_H
+
+# include <openssl/ossl_typ.h>
+# include <openssl/x509.h>
+# include <openssl/x509v3.h>
+# include <openssl/safestack.h>
+
+#ifdef  __cplusplus
+extern "C" {
+#endif
+
+/* Various flags and values */
+
+# define OCSP_DEFAULT_NONCE_LENGTH       16
+
+# define OCSP_NOCERTS                    0x1
+# define OCSP_NOINTERN                   0x2
+# define OCSP_NOSIGS                     0x4
+# define OCSP_NOCHAIN                    0x8
+# define OCSP_NOVERIFY                   0x10
+# define OCSP_NOEXPLICIT                 0x20
+# define OCSP_NOCASIGN                   0x40
+# define OCSP_NODELEGATED                0x80
+# define OCSP_NOCHECKS                   0x100
+# define OCSP_TRUSTOTHER                 0x200
+# define OCSP_RESPID_KEY                 0x400
+# define OCSP_NOTIME                     0x800
+
+/*-  CertID ::= SEQUENCE {
+ *       hashAlgorithm            AlgorithmIdentifier,
+ *       issuerNameHash     OCTET STRING, -- Hash of Issuer's DN
+ *       issuerKeyHash      OCTET STRING, -- Hash of Issuers public key (excluding the tag & length fields)
+ *       serialNumber       CertificateSerialNumber }
+ */
+typedef struct ocsp_cert_id_st {
+    X509_ALGOR *hashAlgorithm;
+    ASN1_OCTET_STRING *issuerNameHash;
+    ASN1_OCTET_STRING *issuerKeyHash;
+    ASN1_INTEGER *serialNumber;
+} OCSP_CERTID;
+
+DECLARE_STACK_OF(OCSP_CERTID)
+
+/*-  Request ::=     SEQUENCE {
+ *       reqCert                    CertID,
+ *       singleRequestExtensions    [0] EXPLICIT Extensions OPTIONAL }
+ */
+typedef struct ocsp_one_request_st {
+    OCSP_CERTID *reqCert;
+    STACK_OF(X509_EXTENSION) *singleRequestExtensions;
+} OCSP_ONEREQ;
+
+DECLARE_STACK_OF(OCSP_ONEREQ)
+DECLARE_ASN1_SET_OF(OCSP_ONEREQ)
+
+/*-  TBSRequest      ::=     SEQUENCE {
+ *       version             [0] EXPLICIT Version DEFAULT v1,
+ *       requestorName       [1] EXPLICIT GeneralName OPTIONAL,
+ *       requestList             SEQUENCE OF Request,
+ *       requestExtensions   [2] EXPLICIT Extensions OPTIONAL }
+ */
+typedef struct ocsp_req_info_st {
+    ASN1_INTEGER *version;
+    GENERAL_NAME *requestorName;
+    STACK_OF(OCSP_ONEREQ) *requestList;
+    STACK_OF(X509_EXTENSION) *requestExtensions;
+} OCSP_REQINFO;
+
+/*-  Signature       ::=     SEQUENCE {
+ *       signatureAlgorithm   AlgorithmIdentifier,
+ *       signature            BIT STRING,
+ *       certs                [0] EXPLICIT SEQUENCE OF Certificate OPTIONAL }
+ */
+typedef struct ocsp_signature_st {
+    X509_ALGOR *signatureAlgorithm;
+    ASN1_BIT_STRING *signature;
+    STACK_OF(X509) *certs;
+} OCSP_SIGNATURE;
+
+/*-  OCSPRequest     ::=     SEQUENCE {
+ *       tbsRequest                  TBSRequest,
+ *       optionalSignature   [0]     EXPLICIT Signature OPTIONAL }
+ */
+typedef struct ocsp_request_st {
+    OCSP_REQINFO *tbsRequest;
+    OCSP_SIGNATURE *optionalSignature; /* OPTIONAL */
+} OCSP_REQUEST;
+
+/*-  OCSPResponseStatus ::= ENUMERATED {
+ *       successful            (0),      --Response has valid confirmations
+ *       malformedRequest      (1),      --Illegal confirmation request
+ *       internalError         (2),      --Internal error in issuer
+ *       tryLater              (3),      --Try again later
+ *                                       --(4) is not used
+ *       sigRequired           (5),      --Must sign the request
+ *       unauthorized          (6)       --Request unauthorized
+ *   }
+ */
+# define OCSP_RESPONSE_STATUS_SUCCESSFUL          0
+# define OCSP_RESPONSE_STATUS_MALFORMEDREQUEST     1
+# define OCSP_RESPONSE_STATUS_INTERNALERROR        2
+# define OCSP_RESPONSE_STATUS_TRYLATER             3
+# define OCSP_RESPONSE_STATUS_SIGREQUIRED          5
+# define OCSP_RESPONSE_STATUS_UNAUTHORIZED         6
+
+/*-  ResponseBytes ::=       SEQUENCE {
+ *       responseType   OBJECT IDENTIFIER,
+ *       response       OCTET STRING }
+ */
+typedef struct ocsp_resp_bytes_st {
+    ASN1_OBJECT *responseType;
+    ASN1_OCTET_STRING *response;
+} OCSP_RESPBYTES;
+
+/*-  OCSPResponse ::= SEQUENCE {
+ *      responseStatus         OCSPResponseStatus,
+ *      responseBytes          [0] EXPLICIT ResponseBytes OPTIONAL }
+ */
+struct ocsp_response_st {
+    ASN1_ENUMERATED *responseStatus;
+    OCSP_RESPBYTES *responseBytes;
+};
+
+/*-  ResponderID ::= CHOICE {
+ *      byName   [1] Name,
+ *      byKey    [2] KeyHash }
+ */
+# define V_OCSP_RESPID_NAME 0
+# define V_OCSP_RESPID_KEY  1
+struct ocsp_responder_id_st {
+    int type;
+    union {
+        X509_NAME *byName;
+        ASN1_OCTET_STRING *byKey;
+    } value;
+};
+
+DECLARE_STACK_OF(OCSP_RESPID)
+DECLARE_ASN1_FUNCTIONS(OCSP_RESPID)
+
+/*-  KeyHash ::= OCTET STRING --SHA-1 hash of responder's public key
+ *                            --(excluding the tag and length fields)
+ */
+
+/*-  RevokedInfo ::= SEQUENCE {
+ *       revocationTime              GeneralizedTime,
+ *       revocationReason    [0]     EXPLICIT CRLReason OPTIONAL }
+ */
+typedef struct ocsp_revoked_info_st {
+    ASN1_GENERALIZEDTIME *revocationTime;
+    ASN1_ENUMERATED *revocationReason;
+} OCSP_REVOKEDINFO;
+
+/*-  CertStatus ::= CHOICE {
+ *       good                [0]     IMPLICIT NULL,
+ *       revoked             [1]     IMPLICIT RevokedInfo,
+ *       unknown             [2]     IMPLICIT UnknownInfo }
+ */
+# define V_OCSP_CERTSTATUS_GOOD    0
+# define V_OCSP_CERTSTATUS_REVOKED 1
+# define V_OCSP_CERTSTATUS_UNKNOWN 2
+typedef struct ocsp_cert_status_st {
+    int type;
+    union {
+        ASN1_NULL *good;
+        OCSP_REVOKEDINFO *revoked;
+        ASN1_NULL *unknown;
+    } value;
+} OCSP_CERTSTATUS;
+
+/*-  SingleResponse ::= SEQUENCE {
+ *      certID                       CertID,
+ *      certStatus                   CertStatus,
+ *      thisUpdate                   GeneralizedTime,
+ *      nextUpdate           [0]     EXPLICIT GeneralizedTime OPTIONAL,
+ *      singleExtensions     [1]     EXPLICIT Extensions OPTIONAL }
+ */
+typedef struct ocsp_single_response_st {
+    OCSP_CERTID *certId;
+    OCSP_CERTSTATUS *certStatus;
+    ASN1_GENERALIZEDTIME *thisUpdate;
+    ASN1_GENERALIZEDTIME *nextUpdate;
+    STACK_OF(X509_EXTENSION) *singleExtensions;
+} OCSP_SINGLERESP;
+
+DECLARE_STACK_OF(OCSP_SINGLERESP)
+DECLARE_ASN1_SET_OF(OCSP_SINGLERESP)
+
+/*-  ResponseData ::= SEQUENCE {
+ *      version              [0] EXPLICIT Version DEFAULT v1,
+ *      responderID              ResponderID,
+ *      producedAt               GeneralizedTime,
+ *      responses                SEQUENCE OF SingleResponse,
+ *      responseExtensions   [1] EXPLICIT Extensions OPTIONAL }
+ */
+typedef struct ocsp_response_data_st {
+    ASN1_INTEGER *version;
+    OCSP_RESPID *responderId;
+    ASN1_GENERALIZEDTIME *producedAt;
+    STACK_OF(OCSP_SINGLERESP) *responses;
+    STACK_OF(X509_EXTENSION) *responseExtensions;
+} OCSP_RESPDATA;
+
+/*-  BasicOCSPResponse       ::= SEQUENCE {
+ *      tbsResponseData      ResponseData,
+ *      signatureAlgorithm   AlgorithmIdentifier,
+ *      signature            BIT STRING,
+ *      certs                [0] EXPLICIT SEQUENCE OF Certificate OPTIONAL }
+ */
+  /*
+   * Note 1: The value for "signature" is specified in the OCSP rfc2560 as
+   * follows: "The value for the signature SHALL be computed on the hash of
+   * the DER encoding ResponseData." This means that you must hash the
+   * DER-encoded tbsResponseData, and then run it through a crypto-signing
+   * function, which will (at least w/RSA) do a hash-'n'-private-encrypt
+   * operation.  This seems a bit odd, but that's the spec.  Also note that
+   * the data structures do not leave anywhere to independently specify the
+   * algorithm used for the initial hash. So, we look at the
+   * signature-specification algorithm, and try to do something intelligent.
+   * -- Kathy Weinhold, CertCo
+   */
+  /*
+   * Note 2: It seems that the mentioned passage from RFC 2560 (section
+   * 4.2.1) is open for interpretation.  I've done tests against another
+   * responder, and found that it doesn't do the double hashing that the RFC
+   * seems to say one should.  Therefore, all relevant functions take a flag
+   * saying which variant should be used.  -- Richard Levitte, OpenSSL team
+   * and CeloCom
+   */
+typedef struct ocsp_basic_response_st {
+    OCSP_RESPDATA *tbsResponseData;
+    X509_ALGOR *signatureAlgorithm;
+    ASN1_BIT_STRING *signature;
+    STACK_OF(X509) *certs;
+} OCSP_BASICRESP;
+
+/*-
+ *   CRLReason ::= ENUMERATED {
+ *        unspecified             (0),
+ *        keyCompromise           (1),
+ *        cACompromise            (2),
+ *        affiliationChanged      (3),
+ *        superseded              (4),
+ *        cessationOfOperation    (5),
+ *        certificateHold         (6),
+ *        removeFromCRL           (8) }
+ */
+# define OCSP_REVOKED_STATUS_NOSTATUS               -1
+# define OCSP_REVOKED_STATUS_UNSPECIFIED             0
+# define OCSP_REVOKED_STATUS_KEYCOMPROMISE           1
+# define OCSP_REVOKED_STATUS_CACOMPROMISE            2
+# define OCSP_REVOKED_STATUS_AFFILIATIONCHANGED      3
+# define OCSP_REVOKED_STATUS_SUPERSEDED              4
+# define OCSP_REVOKED_STATUS_CESSATIONOFOPERATION    5
+# define OCSP_REVOKED_STATUS_CERTIFICATEHOLD         6
+# define OCSP_REVOKED_STATUS_REMOVEFROMCRL           8
+
+/*-
+ * CrlID ::= SEQUENCE {
+ *     crlUrl               [0]     EXPLICIT IA5String OPTIONAL,
+ *     crlNum               [1]     EXPLICIT INTEGER OPTIONAL,
+ *     crlTime              [2]     EXPLICIT GeneralizedTime OPTIONAL }
+ */
+typedef struct ocsp_crl_id_st {
+    ASN1_IA5STRING *crlUrl;
+    ASN1_INTEGER *crlNum;
+    ASN1_GENERALIZEDTIME *crlTime;
+} OCSP_CRLID;
+
+/*-
+ * ServiceLocator ::= SEQUENCE {
+ *      issuer    Name,
+ *      locator   AuthorityInfoAccessSyntax OPTIONAL }
+ */
+typedef struct ocsp_service_locator_st {
+    X509_NAME *issuer;
+    STACK_OF(ACCESS_DESCRIPTION) *locator;
+} OCSP_SERVICELOC;
+
+# define PEM_STRING_OCSP_REQUEST "OCSP REQUEST"
+# define PEM_STRING_OCSP_RESPONSE "OCSP RESPONSE"
+
+# define d2i_OCSP_REQUEST_bio(bp,p) ASN1_d2i_bio_of(OCSP_REQUEST,OCSP_REQUEST_new,d2i_OCSP_REQUEST,bp,p)
+
+# define d2i_OCSP_RESPONSE_bio(bp,p) ASN1_d2i_bio_of(OCSP_RESPONSE,OCSP_RESPONSE_new,d2i_OCSP_RESPONSE,bp,p)
+
+# define PEM_read_bio_OCSP_REQUEST(bp,x,cb) (OCSP_REQUEST *)PEM_ASN1_read_bio( \
+     (char *(*)())d2i_OCSP_REQUEST,PEM_STRING_OCSP_REQUEST,bp,(char **)x,cb,NULL)
+
+# define PEM_read_bio_OCSP_RESPONSE(bp,x,cb)(OCSP_RESPONSE *)PEM_ASN1_read_bio(\
+     (char *(*)())d2i_OCSP_RESPONSE,PEM_STRING_OCSP_RESPONSE,bp,(char **)x,cb,NULL)
+
+# define PEM_write_bio_OCSP_REQUEST(bp,o) \
+    PEM_ASN1_write_bio((int (*)())i2d_OCSP_REQUEST,PEM_STRING_OCSP_REQUEST,\
+                        bp,(char *)o, NULL,NULL,0,NULL,NULL)
+
+# define PEM_write_bio_OCSP_RESPONSE(bp,o) \
+    PEM_ASN1_write_bio((int (*)())i2d_OCSP_RESPONSE,PEM_STRING_OCSP_RESPONSE,\
+                        bp,(char *)o, NULL,NULL,0,NULL,NULL)
+
+# define i2d_OCSP_RESPONSE_bio(bp,o) ASN1_i2d_bio_of(OCSP_RESPONSE,i2d_OCSP_RESPONSE,bp,o)
+
+# define i2d_OCSP_REQUEST_bio(bp,o) ASN1_i2d_bio_of(OCSP_REQUEST,i2d_OCSP_REQUEST,bp,o)
+
+# define OCSP_REQUEST_sign(o,pkey,md) \
+        ASN1_item_sign(ASN1_ITEM_rptr(OCSP_REQINFO),\
+                o->optionalSignature->signatureAlgorithm,NULL,\
+                o->optionalSignature->signature,o->tbsRequest,pkey,md)
+
+# define OCSP_BASICRESP_sign(o,pkey,md,d) \
+        ASN1_item_sign(ASN1_ITEM_rptr(OCSP_RESPDATA),o->signatureAlgorithm,NULL,\
+                o->signature,o->tbsResponseData,pkey,md)
+
+# define OCSP_REQUEST_verify(a,r) ASN1_item_verify(ASN1_ITEM_rptr(OCSP_REQINFO),\
+        a->optionalSignature->signatureAlgorithm,\
+        a->optionalSignature->signature,a->tbsRequest,r)
+
+# define OCSP_BASICRESP_verify(a,r,d) ASN1_item_verify(ASN1_ITEM_rptr(OCSP_RESPDATA),\
+        a->signatureAlgorithm,a->signature,a->tbsResponseData,r)
+
+# define ASN1_BIT_STRING_digest(data,type,md,len) \
+        ASN1_item_digest(ASN1_ITEM_rptr(ASN1_BIT_STRING),type,data,md,len)
+
+# define OCSP_CERTSTATUS_dup(cs)\
+                (OCSP_CERTSTATUS*)ASN1_dup((int(*)())i2d_OCSP_CERTSTATUS,\
+                (char *(*)())d2i_OCSP_CERTSTATUS,(char *)(cs))
+
+OCSP_CERTID *OCSP_CERTID_dup(OCSP_CERTID *id);
+
+OCSP_RESPONSE *OCSP_sendreq_bio(BIO *b, const char *path, OCSP_REQUEST *req);
+OCSP_REQ_CTX *OCSP_sendreq_new(BIO *io, const char *path, OCSP_REQUEST *req,
+                               int maxline);
+int OCSP_REQ_CTX_nbio(OCSP_REQ_CTX *rctx);
+int OCSP_sendreq_nbio(OCSP_RESPONSE **presp, OCSP_REQ_CTX *rctx);
+OCSP_REQ_CTX *OCSP_REQ_CTX_new(BIO *io, int maxline);
+void OCSP_REQ_CTX_free(OCSP_REQ_CTX *rctx);
+void OCSP_set_max_response_length(OCSP_REQ_CTX *rctx, unsigned long len);
+int OCSP_REQ_CTX_i2d(OCSP_REQ_CTX *rctx, const ASN1_ITEM *it,
+                     ASN1_VALUE *val);
+int OCSP_REQ_CTX_nbio_d2i(OCSP_REQ_CTX *rctx, ASN1_VALUE **pval,
+                          const ASN1_ITEM *it);
+BIO *OCSP_REQ_CTX_get0_mem_bio(OCSP_REQ_CTX *rctx);
+int OCSP_REQ_CTX_i2d(OCSP_REQ_CTX *rctx, const ASN1_ITEM *it,
+                     ASN1_VALUE *val);
+int OCSP_REQ_CTX_http(OCSP_REQ_CTX *rctx, const char *op, const char *path);
+int OCSP_REQ_CTX_set1_req(OCSP_REQ_CTX *rctx, OCSP_REQUEST *req);
+int OCSP_REQ_CTX_add1_header(OCSP_REQ_CTX *rctx,
+                             const char *name, const char *value);
+
+OCSP_CERTID *OCSP_cert_to_id(const EVP_MD *dgst, X509 *subject, X509 *issuer);
+
+OCSP_CERTID *OCSP_cert_id_new(const EVP_MD *dgst,
+                              X509_NAME *issuerName,
+                              ASN1_BIT_STRING *issuerKey,
+                              ASN1_INTEGER *serialNumber);
+
+OCSP_ONEREQ *OCSP_request_add0_id(OCSP_REQUEST *req, OCSP_CERTID *cid);
+
+int OCSP_request_add1_nonce(OCSP_REQUEST *req, unsigned char *val, int len);
+int OCSP_basic_add1_nonce(OCSP_BASICRESP *resp, unsigned char *val, int len);
+int OCSP_check_nonce(OCSP_REQUEST *req, OCSP_BASICRESP *bs);
+int OCSP_copy_nonce(OCSP_BASICRESP *resp, OCSP_REQUEST *req);
+
+int OCSP_request_set1_name(OCSP_REQUEST *req, X509_NAME *nm);
+int OCSP_request_add1_cert(OCSP_REQUEST *req, X509 *cert);
+
+int OCSP_request_sign(OCSP_REQUEST *req,
+                      X509 *signer,
+                      EVP_PKEY *key,
+                      const EVP_MD *dgst,
+                      STACK_OF(X509) *certs, unsigned long flags);
+
+int OCSP_response_status(OCSP_RESPONSE *resp);
+OCSP_BASICRESP *OCSP_response_get1_basic(OCSP_RESPONSE *resp);
+
+int OCSP_resp_count(OCSP_BASICRESP *bs);
+OCSP_SINGLERESP *OCSP_resp_get0(OCSP_BASICRESP *bs, int idx);
+int OCSP_resp_find(OCSP_BASICRESP *bs, OCSP_CERTID *id, int last);
+int OCSP_single_get0_status(OCSP_SINGLERESP *single, int *reason,
+                            ASN1_GENERALIZEDTIME **revtime,
+                            ASN1_GENERALIZEDTIME **thisupd,
+                            ASN1_GENERALIZEDTIME **nextupd);
+int OCSP_resp_find_status(OCSP_BASICRESP *bs, OCSP_CERTID *id, int *status,
+                          int *reason,
+                          ASN1_GENERALIZEDTIME **revtime,
+                          ASN1_GENERALIZEDTIME **thisupd,
+                          ASN1_GENERALIZEDTIME **nextupd);
+int OCSP_check_validity(ASN1_GENERALIZEDTIME *thisupd,
+                        ASN1_GENERALIZEDTIME *nextupd, long sec, long maxsec);
+
+int OCSP_request_verify(OCSP_REQUEST *req, STACK_OF(X509) *certs,
+                        X509_STORE *store, unsigned long flags);
+
+int OCSP_parse_url(const char *url, char **phost, char **pport, char **ppath,
+                   int *pssl);
+
+int OCSP_id_issuer_cmp(OCSP_CERTID *a, OCSP_CERTID *b);
+int OCSP_id_cmp(OCSP_CERTID *a, OCSP_CERTID *b);
+
+int OCSP_request_onereq_count(OCSP_REQUEST *req);
+OCSP_ONEREQ *OCSP_request_onereq_get0(OCSP_REQUEST *req, int i);
+OCSP_CERTID *OCSP_onereq_get0_id(OCSP_ONEREQ *one);
+int OCSP_id_get0_info(ASN1_OCTET_STRING **piNameHash, ASN1_OBJECT **pmd,
+                      ASN1_OCTET_STRING **pikeyHash,
+                      ASN1_INTEGER **pserial, OCSP_CERTID *cid);
+int OCSP_request_is_signed(OCSP_REQUEST *req);
+OCSP_RESPONSE *OCSP_response_create(int status, OCSP_BASICRESP *bs);
+OCSP_SINGLERESP *OCSP_basic_add1_status(OCSP_BASICRESP *rsp,
+                                        OCSP_CERTID *cid,
+                                        int status, int reason,
+                                        ASN1_TIME *revtime,
+                                        ASN1_TIME *thisupd,
+                                        ASN1_TIME *nextupd);
+int OCSP_basic_add1_cert(OCSP_BASICRESP *resp, X509 *cert);
+int OCSP_basic_sign(OCSP_BASICRESP *brsp,
+                    X509 *signer, EVP_PKEY *key, const EVP_MD *dgst,
+                    STACK_OF(X509) *certs, unsigned long flags);
+
+X509_EXTENSION *OCSP_crlID_new(char *url, long *n, char *tim);
+
+X509_EXTENSION *OCSP_accept_responses_new(char **oids);
+
+X509_EXTENSION *OCSP_archive_cutoff_new(char *tim);
+
+X509_EXTENSION *OCSP_url_svcloc_new(X509_NAME *issuer, char **urls);
+
+int OCSP_REQUEST_get_ext_count(OCSP_REQUEST *x);
+int OCSP_REQUEST_get_ext_by_NID(OCSP_REQUEST *x, int nid, int lastpos);
+int OCSP_REQUEST_get_ext_by_OBJ(OCSP_REQUEST *x, ASN1_OBJECT *obj,
+                                int lastpos);
+int OCSP_REQUEST_get_ext_by_critical(OCSP_REQUEST *x, int crit, int lastpos);
+X509_EXTENSION *OCSP_REQUEST_get_ext(OCSP_REQUEST *x, int loc);
+X509_EXTENSION *OCSP_REQUEST_delete_ext(OCSP_REQUEST *x, int loc);
+void *OCSP_REQUEST_get1_ext_d2i(OCSP_REQUEST *x, int nid, int *crit,
+                                int *idx);
+int OCSP_REQUEST_add1_ext_i2d(OCSP_REQUEST *x, int nid, void *value, int crit,
+                              unsigned long flags);
+int OCSP_REQUEST_add_ext(OCSP_REQUEST *x, X509_EXTENSION *ex, int loc);
+
+int OCSP_ONEREQ_get_ext_count(OCSP_ONEREQ *x);
+int OCSP_ONEREQ_get_ext_by_NID(OCSP_ONEREQ *x, int nid, int lastpos);
+int OCSP_ONEREQ_get_ext_by_OBJ(OCSP_ONEREQ *x, ASN1_OBJECT *obj, int lastpos);
+int OCSP_ONEREQ_get_ext_by_critical(OCSP_ONEREQ *x, int crit, int lastpos);
+X509_EXTENSION *OCSP_ONEREQ_get_ext(OCSP_ONEREQ *x, int loc);
+X509_EXTENSION *OCSP_ONEREQ_delete_ext(OCSP_ONEREQ *x, int loc);
+void *OCSP_ONEREQ_get1_ext_d2i(OCSP_ONEREQ *x, int nid, int *crit, int *idx);
+int OCSP_ONEREQ_add1_ext_i2d(OCSP_ONEREQ *x, int nid, void *value, int crit,
+                             unsigned long flags);
+int OCSP_ONEREQ_add_ext(OCSP_ONEREQ *x, X509_EXTENSION *ex, int loc);
+
+int OCSP_BASICRESP_get_ext_count(OCSP_BASICRESP *x);
+int OCSP_BASICRESP_get_ext_by_NID(OCSP_BASICRESP *x, int nid, int lastpos);
+int OCSP_BASICRESP_get_ext_by_OBJ(OCSP_BASICRESP *x, ASN1_OBJECT *obj,
+                                  int lastpos);
+int OCSP_BASICRESP_get_ext_by_critical(OCSP_BASICRESP *x, int crit,
+                                       int lastpos);
+X509_EXTENSION *OCSP_BASICRESP_get_ext(OCSP_BASICRESP *x, int loc);
+X509_EXTENSION *OCSP_BASICRESP_delete_ext(OCSP_BASICRESP *x, int loc);
+void *OCSP_BASICRESP_get1_ext_d2i(OCSP_BASICRESP *x, int nid, int *crit,
+                                  int *idx);
+int OCSP_BASICRESP_add1_ext_i2d(OCSP_BASICRESP *x, int nid, void *value,
+                                int crit, unsigned long flags);
+int OCSP_BASICRESP_add_ext(OCSP_BASICRESP *x, X509_EXTENSION *ex, int loc);
+
+int OCSP_SINGLERESP_get_ext_count(OCSP_SINGLERESP *x);
+int OCSP_SINGLERESP_get_ext_by_NID(OCSP_SINGLERESP *x, int nid, int lastpos);
+int OCSP_SINGLERESP_get_ext_by_OBJ(OCSP_SINGLERESP *x, ASN1_OBJECT *obj,
+                                   int lastpos);
+int OCSP_SINGLERESP_get_ext_by_critical(OCSP_SINGLERESP *x, int crit,
+                                        int lastpos);
+X509_EXTENSION *OCSP_SINGLERESP_get_ext(OCSP_SINGLERESP *x, int loc);
+X509_EXTENSION *OCSP_SINGLERESP_delete_ext(OCSP_SINGLERESP *x, int loc);
+void *OCSP_SINGLERESP_get1_ext_d2i(OCSP_SINGLERESP *x, int nid, int *crit,
+                                   int *idx);
+int OCSP_SINGLERESP_add1_ext_i2d(OCSP_SINGLERESP *x, int nid, void *value,
+                                 int crit, unsigned long flags);
+int OCSP_SINGLERESP_add_ext(OCSP_SINGLERESP *x, X509_EXTENSION *ex, int loc);
+
+DECLARE_ASN1_FUNCTIONS(OCSP_SINGLERESP)
+DECLARE_ASN1_FUNCTIONS(OCSP_CERTSTATUS)
+DECLARE_ASN1_FUNCTIONS(OCSP_REVOKEDINFO)
+DECLARE_ASN1_FUNCTIONS(OCSP_BASICRESP)
+DECLARE_ASN1_FUNCTIONS(OCSP_RESPDATA)
+DECLARE_ASN1_FUNCTIONS(OCSP_RESPID)
+DECLARE_ASN1_FUNCTIONS(OCSP_RESPONSE)
+DECLARE_ASN1_FUNCTIONS(OCSP_RESPBYTES)
+DECLARE_ASN1_FUNCTIONS(OCSP_ONEREQ)
+DECLARE_ASN1_FUNCTIONS(OCSP_CERTID)
+DECLARE_ASN1_FUNCTIONS(OCSP_REQUEST)
+DECLARE_ASN1_FUNCTIONS(OCSP_SIGNATURE)
+DECLARE_ASN1_FUNCTIONS(OCSP_REQINFO)
+DECLARE_ASN1_FUNCTIONS(OCSP_CRLID)
+DECLARE_ASN1_FUNCTIONS(OCSP_SERVICELOC)
+
+const char *OCSP_response_status_str(long s);
+const char *OCSP_cert_status_str(long s);
+const char *OCSP_crl_reason_str(long s);
+
+int OCSP_REQUEST_print(BIO *bp, OCSP_REQUEST *a, unsigned long flags);
+int OCSP_RESPONSE_print(BIO *bp, OCSP_RESPONSE *o, unsigned long flags);
+
+int OCSP_basic_verify(OCSP_BASICRESP *bs, STACK_OF(X509) *certs,
+                      X509_STORE *st, unsigned long flags);
+
+/* BEGIN ERROR CODES */
+/*
+ * The following lines are auto generated by the script mkerr.pl. Any changes
+ * made after this point may be overwritten when the script is next run.
+ */
+void ERR_load_OCSP_strings(void);
+
+/* Error codes for the OCSP functions. */
+
+/* Function codes. */
+# define OCSP_F_ASN1_STRING_ENCODE                        100
+# define OCSP_F_D2I_OCSP_NONCE                            102
+# define OCSP_F_OCSP_BASIC_ADD1_STATUS                    103
+# define OCSP_F_OCSP_BASIC_SIGN                           104
+# define OCSP_F_OCSP_BASIC_VERIFY                         105
+# define OCSP_F_OCSP_CERT_ID_NEW                          101
+# define OCSP_F_OCSP_CHECK_DELEGATED                      106
+# define OCSP_F_OCSP_CHECK_IDS                            107
+# define OCSP_F_OCSP_CHECK_ISSUER                         108
+# define OCSP_F_OCSP_CHECK_VALIDITY                       115
+# define OCSP_F_OCSP_MATCH_ISSUERID                       109
+# define OCSP_F_OCSP_PARSE_URL                            114
+# define OCSP_F_OCSP_REQUEST_SIGN                         110
+# define OCSP_F_OCSP_REQUEST_VERIFY                       116
+# define OCSP_F_OCSP_RESPONSE_GET1_BASIC                  111
+# define OCSP_F_OCSP_SENDREQ_BIO                          112
+# define OCSP_F_OCSP_SENDREQ_NBIO                         117
+# define OCSP_F_PARSE_HTTP_LINE1                          118
+# define OCSP_F_REQUEST_VERIFY                            113
+
+/* Reason codes. */
+# define OCSP_R_BAD_DATA                                  100
+# define OCSP_R_CERTIFICATE_VERIFY_ERROR                  101
+# define OCSP_R_DIGEST_ERR                                102
+# define OCSP_R_ERROR_IN_NEXTUPDATE_FIELD                 122
+# define OCSP_R_ERROR_IN_THISUPDATE_FIELD                 123
+# define OCSP_R_ERROR_PARSING_URL                         121
+# define OCSP_R_MISSING_OCSPSIGNING_USAGE                 103
+# define OCSP_R_NEXTUPDATE_BEFORE_THISUPDATE              124
+# define OCSP_R_NOT_BASIC_RESPONSE                        104
+# define OCSP_R_NO_CERTIFICATES_IN_CHAIN                  105
+# define OCSP_R_NO_CONTENT                                106
+# define OCSP_R_NO_PUBLIC_KEY                             107
+# define OCSP_R_NO_RESPONSE_DATA                          108
+# define OCSP_R_NO_REVOKED_TIME                           109
+# define OCSP_R_PRIVATE_KEY_DOES_NOT_MATCH_CERTIFICATE    110
+# define OCSP_R_REQUEST_NOT_SIGNED                        128
+# define OCSP_R_RESPONSE_CONTAINS_NO_REVOCATION_DATA      111
+# define OCSP_R_ROOT_CA_NOT_TRUSTED                       112
+# define OCSP_R_SERVER_READ_ERROR                         113
+# define OCSP_R_SERVER_RESPONSE_ERROR                     114
+# define OCSP_R_SERVER_RESPONSE_PARSE_ERROR               115
+# define OCSP_R_SERVER_WRITE_ERROR                        116
+# define OCSP_R_SIGNATURE_FAILURE                         117
+# define OCSP_R_SIGNER_CERTIFICATE_NOT_FOUND              118
+# define OCSP_R_STATUS_EXPIRED                            125
+# define OCSP_R_STATUS_NOT_YET_VALID                      126
+# define OCSP_R_STATUS_TOO_OLD                            127
+# define OCSP_R_UNKNOWN_MESSAGE_DIGEST                    119
+# define OCSP_R_UNKNOWN_NID                               120
+# define OCSP_R_UNSUPPORTED_REQUESTORNAME_TYPE            129
+
+#ifdef  __cplusplus
+}
+#endif
+#endif

+ 271 - 0
libssh2/openssl/include/openssl/opensslconf.h

@@ -0,0 +1,271 @@
+/* opensslconf.h */
+/* WARNING: Generated automatically from opensslconf.h.in by Configure. */
+
+#ifdef  __cplusplus
+extern "C" {
+#endif
+/* OpenSSL was configured with the following options: */
+#ifndef OPENSSL_SYSNAME_WIN32
+# define OPENSSL_SYSNAME_WIN32
+#endif
+#ifndef OPENSSL_DOING_MAKEDEPEND
+
+
+#ifndef OPENSSL_NO_EC_NISTP_64_GCC_128
+# define OPENSSL_NO_EC_NISTP_64_GCC_128
+#endif
+#ifndef OPENSSL_NO_GMP
+# define OPENSSL_NO_GMP
+#endif
+#ifndef OPENSSL_NO_JPAKE
+# define OPENSSL_NO_JPAKE
+#endif
+#ifndef OPENSSL_NO_KRB5
+# define OPENSSL_NO_KRB5
+#endif
+#ifndef OPENSSL_NO_LIBUNBOUND
+# define OPENSSL_NO_LIBUNBOUND
+#endif
+#ifndef OPENSSL_NO_MD2
+# define OPENSSL_NO_MD2
+#endif
+#ifndef OPENSSL_NO_RC5
+# define OPENSSL_NO_RC5
+#endif
+#ifndef OPENSSL_NO_RFC3779
+# define OPENSSL_NO_RFC3779
+#endif
+#ifndef OPENSSL_NO_SCTP
+# define OPENSSL_NO_SCTP
+#endif
+#ifndef OPENSSL_NO_SSL_TRACE
+# define OPENSSL_NO_SSL_TRACE
+#endif
+#ifndef OPENSSL_NO_SSL2
+# define OPENSSL_NO_SSL2
+#endif
+#ifndef OPENSSL_NO_STORE
+# define OPENSSL_NO_STORE
+#endif
+#ifndef OPENSSL_NO_UNIT_TEST
+# define OPENSSL_NO_UNIT_TEST
+#endif
+#ifndef OPENSSL_NO_WEAK_SSL_CIPHERS
+# define OPENSSL_NO_WEAK_SSL_CIPHERS
+#endif
+
+#endif /* OPENSSL_DOING_MAKEDEPEND */
+
+#ifndef OPENSSL_THREADS
+# define OPENSSL_THREADS
+#endif
+
+/* The OPENSSL_NO_* macros are also defined as NO_* if the application
+   asks for it.  This is a transient feature that is provided for those
+   who haven't had the time to do the appropriate changes in their
+   applications.  */
+#ifdef OPENSSL_ALGORITHM_DEFINES
+# if defined(OPENSSL_NO_EC_NISTP_64_GCC_128) && !defined(NO_EC_NISTP_64_GCC_128)
+#  define NO_EC_NISTP_64_GCC_128
+# endif
+# if defined(OPENSSL_NO_GMP) && !defined(NO_GMP)
+#  define NO_GMP
+# endif
+# if defined(OPENSSL_NO_JPAKE) && !defined(NO_JPAKE)
+#  define NO_JPAKE
+# endif
+# if defined(OPENSSL_NO_KRB5) && !defined(NO_KRB5)
+#  define NO_KRB5
+# endif
+# if defined(OPENSSL_NO_LIBUNBOUND) && !defined(NO_LIBUNBOUND)
+#  define NO_LIBUNBOUND
+# endif
+# if defined(OPENSSL_NO_MD2) && !defined(NO_MD2)
+#  define NO_MD2
+# endif
+# if defined(OPENSSL_NO_RC5) && !defined(NO_RC5)
+#  define NO_RC5
+# endif
+# if defined(OPENSSL_NO_RFC3779) && !defined(NO_RFC3779)
+#  define NO_RFC3779
+# endif
+# if defined(OPENSSL_NO_SCTP) && !defined(NO_SCTP)
+#  define NO_SCTP
+# endif
+# if defined(OPENSSL_NO_SSL_TRACE) && !defined(NO_SSL_TRACE)
+#  define NO_SSL_TRACE
+# endif
+# if defined(OPENSSL_NO_SSL2) && !defined(NO_SSL2)
+#  define NO_SSL2
+# endif
+# if defined(OPENSSL_NO_STORE) && !defined(NO_STORE)
+#  define NO_STORE
+# endif
+# if defined(OPENSSL_NO_UNIT_TEST) && !defined(NO_UNIT_TEST)
+#  define NO_UNIT_TEST
+# endif
+# if defined(OPENSSL_NO_WEAK_SSL_CIPHERS) && !defined(NO_WEAK_SSL_CIPHERS)
+#  define NO_WEAK_SSL_CIPHERS
+# endif
+#endif
+
+#define OPENSSL_CPUID_OBJ
+
+/* crypto/opensslconf.h.in */
+
+/* Generate 80386 code? */
+#undef I386_ONLY
+
+#if !(defined(VMS) || defined(__VMS)) /* VMS uses logical names instead */
+#if defined(HEADER_CRYPTLIB_H) && !defined(OPENSSLDIR)
+#define ENGINESDIR "g:\\openssl\\dir/lib/engines"
+#define OPENSSLDIR "g:\\openssl\\dir/ssl"
+#endif
+#endif
+
+#undef OPENSSL_UNISTD
+#define OPENSSL_UNISTD <unistd.h>
+
+#undef OPENSSL_EXPORT_VAR_AS_FUNCTION
+#define OPENSSL_EXPORT_VAR_AS_FUNCTION
+
+#if defined(HEADER_IDEA_H) && !defined(IDEA_INT)
+#define IDEA_INT unsigned int
+#endif
+
+#if defined(HEADER_MD2_H) && !defined(MD2_INT)
+#define MD2_INT unsigned int
+#endif
+
+#if defined(HEADER_RC2_H) && !defined(RC2_INT)
+/* I need to put in a mod for the alpha - eay */
+#define RC2_INT unsigned int
+#endif
+
+#if defined(HEADER_RC4_H)
+#if !defined(RC4_INT)
+/* using int types make the structure larger but make the code faster
+ * on most boxes I have tested - up to %20 faster. */
+/*
+ * I don't know what does "most" mean, but declaring "int" is a must on:
+ * - Intel P6 because partial register stalls are very expensive;
+ * - elder Alpha because it lacks byte load/store instructions;
+ */
+#define RC4_INT unsigned int
+#endif
+#if !defined(RC4_CHUNK)
+/*
+ * This enables code handling data aligned at natural CPU word
+ * boundary. See crypto/rc4/rc4_enc.c for further details.
+ */
+#undef RC4_CHUNK
+#endif
+#endif
+
+#if (defined(HEADER_NEW_DES_H) || defined(HEADER_DES_H)) && !defined(DES_LONG)
+/* If this is set to 'unsigned int' on a DEC Alpha, this gives about a
+ * %20 speed up (longs are 8 bytes, int's are 4). */
+#ifndef DES_LONG
+#define DES_LONG unsigned long
+#endif
+#endif
+
+#if defined(HEADER_BN_H) && !defined(CONFIG_HEADER_BN_H)
+#define CONFIG_HEADER_BN_H
+#define BN_LLONG
+
+/* Should we define BN_DIV2W here? */
+
+/* Only one for the following should be defined */
+#undef SIXTY_FOUR_BIT_LONG
+#undef SIXTY_FOUR_BIT
+#define THIRTY_TWO_BIT
+#endif
+
+#if defined(HEADER_RC4_LOCL_H) && !defined(CONFIG_HEADER_RC4_LOCL_H)
+#define CONFIG_HEADER_RC4_LOCL_H
+/* if this is defined data[i] is used instead of *data, this is a %20
+ * speedup on x86 */
+#define RC4_INDEX
+#endif
+
+#if defined(HEADER_BF_LOCL_H) && !defined(CONFIG_HEADER_BF_LOCL_H)
+#define CONFIG_HEADER_BF_LOCL_H
+#undef BF_PTR
+#endif /* HEADER_BF_LOCL_H */
+
+#if defined(HEADER_DES_LOCL_H) && !defined(CONFIG_HEADER_DES_LOCL_H)
+#define CONFIG_HEADER_DES_LOCL_H
+#ifndef DES_DEFAULT_OPTIONS
+/* the following is tweaked from a config script, that is why it is a
+ * protected undef/define */
+#ifndef DES_PTR
+#undef DES_PTR
+#endif
+
+/* This helps C compiler generate the correct code for multiple functional
+ * units.  It reduces register dependancies at the expense of 2 more
+ * registers */
+#ifndef DES_RISC1
+#undef DES_RISC1
+#endif
+
+#ifndef DES_RISC2
+#undef DES_RISC2
+#endif
+
+#if defined(DES_RISC1) && defined(DES_RISC2)
+#error YOU SHOULD NOT HAVE BOTH DES_RISC1 AND DES_RISC2 DEFINED!!!!!
+#endif
+
+/* Unroll the inner loop, this sometimes helps, sometimes hinders.
+ * Very mucy CPU dependant */
+#ifndef DES_UNROLL
+#undef DES_UNROLL
+#endif
+
+/* These default values were supplied by
+ * Peter Gutman <pgut001@cs.auckland.ac.nz>
+ * They are only used if nothing else has been defined */
+#if !defined(DES_PTR) && !defined(DES_RISC1) && !defined(DES_RISC2) && !defined(DES_UNROLL)
+/* Special defines which change the way the code is built depending on the
+   CPU and OS.  For SGI machines you can use _MIPS_SZLONG (32 or 64) to find
+   even newer MIPS CPU's, but at the moment one size fits all for
+   optimization options.  Older Sparc's work better with only UNROLL, but
+   there's no way to tell at compile time what it is you're running on */
+ 
+#if defined( __sun ) || defined ( sun )		/* Newer Sparc's */
+#  define DES_PTR
+#  define DES_RISC1
+#  define DES_UNROLL
+#elif defined( __ultrix )	/* Older MIPS */
+#  define DES_PTR
+#  define DES_RISC2
+#  define DES_UNROLL
+#elif defined( __osf1__ )	/* Alpha */
+#  define DES_PTR
+#  define DES_RISC2
+#elif defined ( _AIX )		/* RS6000 */
+  /* Unknown */
+#elif defined( __hpux )		/* HP-PA */
+  /* Unknown */
+#elif defined( __aux )		/* 68K */
+  /* Unknown */
+#elif defined( __dgux )		/* 88K (but P6 in latest boxes) */
+#  define DES_UNROLL
+#elif defined( __sgi )		/* Newer MIPS */
+#  define DES_PTR
+#  define DES_RISC2
+#  define DES_UNROLL
+#elif defined(i386) || defined(__i386__)	/* x86 boxes, should be gcc */
+#  define DES_PTR
+#  define DES_RISC1
+#  define DES_UNROLL
+#endif /* Systems-specific speed defines */
+#endif
+
+#endif /* DES_DEFAULT_OPTIONS */
+#endif /* HEADER_DES_LOCL_H */
+#ifdef  __cplusplus
+}
+#endif

+ 97 - 0
libssh2/openssl/include/openssl/opensslv.h

@@ -0,0 +1,97 @@
+#ifndef HEADER_OPENSSLV_H
+# define HEADER_OPENSSLV_H
+
+#ifdef  __cplusplus
+extern "C" {
+#endif
+
+/*-
+ * Numeric release version identifier:
+ * MNNFFPPS: major minor fix patch status
+ * The status nibble has one of the values 0 for development, 1 to e for betas
+ * 1 to 14, and f for release.  The patch level is exactly that.
+ * For example:
+ * 0.9.3-dev      0x00903000
+ * 0.9.3-beta1    0x00903001
+ * 0.9.3-beta2-dev 0x00903002
+ * 0.9.3-beta2    0x00903002 (same as ...beta2-dev)
+ * 0.9.3          0x0090300f
+ * 0.9.3a         0x0090301f
+ * 0.9.4          0x0090400f
+ * 1.2.3z         0x102031af
+ *
+ * For continuity reasons (because 0.9.5 is already out, and is coded
+ * 0x00905100), between 0.9.5 and 0.9.6 the coding of the patch level
+ * part is slightly different, by setting the highest bit.  This means
+ * that 0.9.5a looks like this: 0x0090581f.  At 0.9.6, we can start
+ * with 0x0090600S...
+ *
+ * (Prior to 0.9.3-dev a different scheme was used: 0.9.2b is 0x0922.)
+ * (Prior to 0.9.5a beta1, a different scheme was used: MMNNFFRBB for
+ *  major minor fix final patch/beta)
+ */
+# define OPENSSL_VERSION_NUMBER  0x1000215fL
+# ifdef OPENSSL_FIPS
+#  define OPENSSL_VERSION_TEXT    "OpenSSL 1.0.2u-fips  20 Dec 2019"
+# else
+#  define OPENSSL_VERSION_TEXT    "OpenSSL 1.0.2u  20 Dec 2019"
+# endif
+# define OPENSSL_VERSION_PTEXT   " part of " OPENSSL_VERSION_TEXT
+
+/*-
+ * The macros below are to be used for shared library (.so, .dll, ...)
+ * versioning.  That kind of versioning works a bit differently between
+ * operating systems.  The most usual scheme is to set a major and a minor
+ * number, and have the runtime loader check that the major number is equal
+ * to what it was at application link time, while the minor number has to
+ * be greater or equal to what it was at application link time.  With this
+ * scheme, the version number is usually part of the file name, like this:
+ *
+ *      libcrypto.so.0.9
+ *
+ * Some unixen also make a softlink with the major verson number only:
+ *
+ *      libcrypto.so.0
+ *
+ * On Tru64 and IRIX 6.x it works a little bit differently.  There, the
+ * shared library version is stored in the file, and is actually a series
+ * of versions, separated by colons.  The rightmost version present in the
+ * library when linking an application is stored in the application to be
+ * matched at run time.  When the application is run, a check is done to
+ * see if the library version stored in the application matches any of the
+ * versions in the version string of the library itself.
+ * This version string can be constructed in any way, depending on what
+ * kind of matching is desired.  However, to implement the same scheme as
+ * the one used in the other unixen, all compatible versions, from lowest
+ * to highest, should be part of the string.  Consecutive builds would
+ * give the following versions strings:
+ *
+ *      3.0
+ *      3.0:3.1
+ *      3.0:3.1:3.2
+ *      4.0
+ *      4.0:4.1
+ *
+ * Notice how version 4 is completely incompatible with version, and
+ * therefore give the breach you can see.
+ *
+ * There may be other schemes as well that I haven't yet discovered.
+ *
+ * So, here's the way it works here: first of all, the library version
+ * number doesn't need at all to match the overall OpenSSL version.
+ * However, it's nice and more understandable if it actually does.
+ * The current library version is stored in the macro SHLIB_VERSION_NUMBER,
+ * which is just a piece of text in the format "M.m.e" (Major, minor, edit).
+ * For the sake of Tru64, IRIX, and any other OS that behaves in similar ways,
+ * we need to keep a history of version numbers, which is done in the
+ * macro SHLIB_VERSION_HISTORY.  The numbers are separated by colons and
+ * should only keep the versions that are binary compatible with the current.
+ */
+# define SHLIB_VERSION_HISTORY ""
+# define SHLIB_VERSION_NUMBER "1.0.0"
+
+
+#ifdef  __cplusplus
+}
+#endif
+#endif                          /* HEADER_OPENSSLV_H */

+ 213 - 0
libssh2/openssl/include/openssl/ossl_typ.h

@@ -0,0 +1,213 @@
+/* ====================================================================
+ * Copyright (c) 1998-2001 The OpenSSL 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. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    openssl-core@openssl.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED 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 OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS 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.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com).  This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+
+#ifndef HEADER_OPENSSL_TYPES_H
+# define HEADER_OPENSSL_TYPES_H
+
+#ifdef  __cplusplus
+extern "C" {
+#endif
+
+# include <openssl/e_os2.h>
+
+# ifdef NO_ASN1_TYPEDEFS
+#  define ASN1_INTEGER            ASN1_STRING
+#  define ASN1_ENUMERATED         ASN1_STRING
+#  define ASN1_BIT_STRING         ASN1_STRING
+#  define ASN1_OCTET_STRING       ASN1_STRING
+#  define ASN1_PRINTABLESTRING    ASN1_STRING
+#  define ASN1_T61STRING          ASN1_STRING
+#  define ASN1_IA5STRING          ASN1_STRING
+#  define ASN1_UTCTIME            ASN1_STRING
+#  define ASN1_GENERALIZEDTIME    ASN1_STRING
+#  define ASN1_TIME               ASN1_STRING
+#  define ASN1_GENERALSTRING      ASN1_STRING
+#  define ASN1_UNIVERSALSTRING    ASN1_STRING
+#  define ASN1_BMPSTRING          ASN1_STRING
+#  define ASN1_VISIBLESTRING      ASN1_STRING
+#  define ASN1_UTF8STRING         ASN1_STRING
+#  define ASN1_BOOLEAN            int
+#  define ASN1_NULL               int
+# else
+typedef struct asn1_string_st ASN1_INTEGER;
+typedef struct asn1_string_st ASN1_ENUMERATED;
+typedef struct asn1_string_st ASN1_BIT_STRING;
+typedef struct asn1_string_st ASN1_OCTET_STRING;
+typedef struct asn1_string_st ASN1_PRINTABLESTRING;
+typedef struct asn1_string_st ASN1_T61STRING;
+typedef struct asn1_string_st ASN1_IA5STRING;
+typedef struct asn1_string_st ASN1_GENERALSTRING;
+typedef struct asn1_string_st ASN1_UNIVERSALSTRING;
+typedef struct asn1_string_st ASN1_BMPSTRING;
+typedef struct asn1_string_st ASN1_UTCTIME;
+typedef struct asn1_string_st ASN1_TIME;
+typedef struct asn1_string_st ASN1_GENERALIZEDTIME;
+typedef struct asn1_string_st ASN1_VISIBLESTRING;
+typedef struct asn1_string_st ASN1_UTF8STRING;
+typedef struct asn1_string_st ASN1_STRING;
+typedef int ASN1_BOOLEAN;
+typedef int ASN1_NULL;
+# endif
+
+typedef struct asn1_object_st ASN1_OBJECT;
+
+typedef struct ASN1_ITEM_st ASN1_ITEM;
+typedef struct asn1_pctx_st ASN1_PCTX;
+
+# ifdef OPENSSL_SYS_WIN32
+#  undef X509_NAME
+#  undef X509_EXTENSIONS
+#  undef X509_CERT_PAIR
+#  undef PKCS7_ISSUER_AND_SERIAL
+#  undef OCSP_REQUEST
+#  undef OCSP_RESPONSE
+# endif
+
+# ifdef BIGNUM
+#  undef BIGNUM
+# endif
+typedef struct bignum_st BIGNUM;
+typedef struct bignum_ctx BN_CTX;
+typedef struct bn_blinding_st BN_BLINDING;
+typedef struct bn_mont_ctx_st BN_MONT_CTX;
+typedef struct bn_recp_ctx_st BN_RECP_CTX;
+typedef struct bn_gencb_st BN_GENCB;
+
+typedef struct buf_mem_st BUF_MEM;
+
+typedef struct evp_cipher_st EVP_CIPHER;
+typedef struct evp_cipher_ctx_st EVP_CIPHER_CTX;
+typedef struct env_md_st EVP_MD;
+typedef struct env_md_ctx_st EVP_MD_CTX;
+typedef struct evp_pkey_st EVP_PKEY;
+
+typedef struct evp_pkey_asn1_method_st EVP_PKEY_ASN1_METHOD;
+
+typedef struct evp_pkey_method_st EVP_PKEY_METHOD;
+typedef struct evp_pkey_ctx_st EVP_PKEY_CTX;
+
+typedef struct dh_st DH;
+typedef struct dh_method DH_METHOD;
+
+typedef struct dsa_st DSA;
+typedef struct dsa_method DSA_METHOD;
+
+typedef struct rsa_st RSA;
+typedef struct rsa_meth_st RSA_METHOD;
+
+typedef struct rand_meth_st RAND_METHOD;
+
+typedef struct ecdh_method ECDH_METHOD;
+typedef struct ecdsa_method ECDSA_METHOD;
+
+typedef struct x509_st X509;
+typedef struct X509_algor_st X509_ALGOR;
+typedef struct X509_crl_st X509_CRL;
+typedef struct x509_crl_method_st X509_CRL_METHOD;
+typedef struct x509_revoked_st X509_REVOKED;
+typedef struct X509_name_st X509_NAME;
+typedef struct X509_pubkey_st X509_PUBKEY;
+typedef struct x509_store_st X509_STORE;
+typedef struct x509_store_ctx_st X509_STORE_CTX;
+
+typedef struct pkcs8_priv_key_info_st PKCS8_PRIV_KEY_INFO;
+
+typedef struct v3_ext_ctx X509V3_CTX;
+typedef struct conf_st CONF;
+
+typedef struct store_st STORE;
+typedef struct store_method_st STORE_METHOD;
+
+typedef struct ui_st UI;
+typedef struct ui_method_st UI_METHOD;
+
+typedef struct st_ERR_FNS ERR_FNS;
+
+typedef struct engine_st ENGINE;
+typedef struct ssl_st SSL;
+typedef struct ssl_ctx_st SSL_CTX;
+
+typedef struct comp_method_st COMP_METHOD;
+
+typedef struct X509_POLICY_NODE_st X509_POLICY_NODE;
+typedef struct X509_POLICY_LEVEL_st X509_POLICY_LEVEL;
+typedef struct X509_POLICY_TREE_st X509_POLICY_TREE;
+typedef struct X509_POLICY_CACHE_st X509_POLICY_CACHE;
+
+typedef struct AUTHORITY_KEYID_st AUTHORITY_KEYID;
+typedef struct DIST_POINT_st DIST_POINT;
+typedef struct ISSUING_DIST_POINT_st ISSUING_DIST_POINT;
+typedef struct NAME_CONSTRAINTS_st NAME_CONSTRAINTS;
+
+  /* If placed in pkcs12.h, we end up with a circular depency with pkcs7.h */
+# define DECLARE_PKCS12_STACK_OF(type)/* Nothing */
+# define IMPLEMENT_PKCS12_STACK_OF(type)/* Nothing */
+
+typedef struct crypto_ex_data_st CRYPTO_EX_DATA;
+/* Callback types for crypto.h */
+typedef int CRYPTO_EX_new (void *parent, void *ptr, CRYPTO_EX_DATA *ad,
+                           int idx, long argl, void *argp);
+typedef void CRYPTO_EX_free (void *parent, void *ptr, CRYPTO_EX_DATA *ad,
+                             int idx, long argl, void *argp);
+typedef int CRYPTO_EX_dup (CRYPTO_EX_DATA *to, CRYPTO_EX_DATA *from,
+                           void *from_d, int idx, long argl, void *argp);
+
+typedef struct ocsp_req_ctx_st OCSP_REQ_CTX;
+typedef struct ocsp_response_st OCSP_RESPONSE;
+typedef struct ocsp_responder_id_st OCSP_RESPID;
+
+#ifdef  __cplusplus
+}
+#endif
+#endif                          /* def HEADER_OPENSSL_TYPES_H */

Beberapa file tidak ditampilkan karena terlalu banyak file yang berubah dalam diff ini