diff options
author | George Hazan <george.hazan@gmail.com> | 2024-01-31 19:13:48 +0300 |
---|---|---|
committer | George Hazan <george.hazan@gmail.com> | 2024-01-31 19:13:48 +0300 |
commit | a5b576429205ffa3c9397614ea31363b31944e79 (patch) | |
tree | f5b92958748d66556f0f6af0b313ce42d8ad8903 /libs/libssh2/src | |
parent | 4ce9ed24b5fabd39d82aaf81147377f3906dec3b (diff) |
libssh2: update to 1.11
Diffstat (limited to 'libs/libssh2/src')
40 files changed, 2682 insertions, 1109 deletions
diff --git a/libs/libssh2/src/CMakeLists.txt b/libs/libssh2/src/CMakeLists.txt index 3a2077d06b..bca1b23d5b 100644 --- a/libs/libssh2/src/CMakeLists.txt +++ b/libs/libssh2/src/CMakeLists.txt @@ -36,9 +36,13 @@ # # SPDX-License-Identifier: BSD-3-Clause +set(LIBSSH2_SOVERSION 1) +set(LIBSSH2_LIBVERSION 1.0.1) + if(CRYPTO_BACKEND) list(APPEND PRIVATE_COMPILE_DEFINITIONS ${CRYPTO_BACKEND_DEFINE}) list(APPEND PRIVATE_INCLUDE_DIRECTORIES ${CRYPTO_BACKEND_INCLUDE_DIR}) + add_feature_info("Crypto backend" ON "${CRYPTO_BACKEND}") else() message(FATAL_ERROR "No suitable cryptography backend found.") endif() @@ -47,10 +51,10 @@ endif() option(CLEAR_MEMORY "Enable clearing of memory before being freed" ON) if(NOT CLEAR_MEMORY) - list(APPEND libssh2_DEFINITIONS LIBSSH2_NO_CLEAR_MEMORY) + list(APPEND libssh2_DEFINITIONS "LIBSSH2_NO_CLEAR_MEMORY") endif() -option(ENABLE_ZLIB_COMPRESSION "Use zlib for compression") +option(ENABLE_ZLIB_COMPRESSION "Use zlib for compression" OFF) add_feature_info(Compression ENABLE_ZLIB_COMPRESSION "using zlib for compression") if(ENABLE_ZLIB_COMPRESSION) @@ -58,16 +62,17 @@ if(ENABLE_ZLIB_COMPRESSION) list(APPEND libssh2_INCLUDE_DIRS ${ZLIB_INCLUDE_DIRS}) list(APPEND LIBRARIES ${ZLIB_LIBRARIES}) - list(APPEND PC_REQUIRES_PRIVATE zlib) + list(APPEND LIBSSH2_PC_LIBS_PRIVATE "-lz") + list(APPEND LIBSSH2_PC_REQUIRES_PRIVATE "zlib") if(ZLIB_FOUND) - list(APPEND libssh2_DEFINITIONS LIBSSH2_HAVE_ZLIB) + list(APPEND libssh2_DEFINITIONS "LIBSSH2_HAVE_ZLIB") endif() endif() list(APPEND LIBRARIES ${SOCKET_LIBRARIES}) if(WIN32) - list(APPEND PC_LIBS -lws2_32) + list(APPEND LIBSSH2_PC_LIBS_PRIVATE "-lws2_32") endif() # to find generated header @@ -83,7 +88,7 @@ endif() include(GNUInstallDirs) transform_makefile_inc("Makefile.inc" "${CMAKE_CURRENT_BINARY_DIR}/Makefile.inc.cmake") # Get 'CSOURCES' and 'HHEADERS' variables -include(${CMAKE_CURRENT_BINARY_DIR}/Makefile.inc.cmake) +include("${CMAKE_CURRENT_BINARY_DIR}/Makefile.inc.cmake") set(SOURCES ${CSOURCES} ${HHEADERS}) ## Library definition @@ -102,55 +107,62 @@ endif() if(BUILD_STATIC_LIBS) list(APPEND libssh2_export ${LIB_STATIC}) add_library(${LIB_STATIC} STATIC ${SOURCES}) + add_library(${PROJECT_NAME}::${LIB_STATIC} ALIAS ${LIB_STATIC}) target_compile_definitions(${LIB_STATIC} PRIVATE ${PRIVATE_COMPILE_DEFINITIONS} ${libssh2_DEFINITIONS}) target_link_libraries(${LIB_STATIC} PRIVATE ${LIBRARIES}) - set_target_properties(${LIB_STATIC} PROPERTIES PREFIX "" OUTPUT_NAME "libssh2") - set_target_properties(${LIB_STATIC} PROPERTIES SUFFIX "${STATIC_LIB_SUFFIX}${CMAKE_STATIC_LIBRARY_SUFFIX}") + set_target_properties(${LIB_STATIC} PROPERTIES + PREFIX "" OUTPUT_NAME "libssh2" SOVERSION "${LIBSSH2_SOVERSION}" VERSION "${LIBSSH2_LIBVERSION}" + SUFFIX "${STATIC_LIB_SUFFIX}${CMAKE_STATIC_LIBRARY_SUFFIX}") target_include_directories(${LIB_STATIC} PRIVATE "${PROJECT_SOURCE_DIR}/include/" ${libssh2_INCLUDE_DIRS} ${PRIVATE_INCLUDE_DIRECTORIES} PUBLIC - $<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}/include> - $<INSTALL_INTERFACE:$<INSTALL_PREFIX>/${CMAKE_INSTALL_INCLUDEDIR}>) + "$<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}/include>" + "$<INSTALL_INTERFACE:$<INSTALL_PREFIX>/${CMAKE_INSTALL_INCLUDEDIR}>") endif() if(BUILD_SHARED_LIBS) list(APPEND libssh2_export ${LIB_SHARED}) add_library(${LIB_SHARED} SHARED ${SOURCES}) + add_library(${PROJECT_NAME}::${LIB_SHARED} ALIAS ${LIB_SHARED}) if(WIN32) - set_property(TARGET ${LIB_SHARED} APPEND PROPERTY SOURCES libssh2.rc) + set_property(TARGET ${LIB_SHARED} APPEND PROPERTY SOURCES "libssh2.rc") endif() target_compile_definitions(${LIB_SHARED} PRIVATE ${PRIVATE_COMPILE_DEFINITIONS} ${libssh2_DEFINITIONS} ${LIB_SHARED_DEFINITIONS}) target_compile_options(${LIB_SHARED} PRIVATE ${LIB_SHARED_C_FLAGS}) target_link_libraries(${LIB_SHARED} PRIVATE ${LIBRARIES}) - set_target_properties(${LIB_SHARED} PROPERTIES PREFIX "" IMPORT_PREFIX "" OUTPUT_NAME "libssh2") - set_target_properties(${LIB_SHARED} PROPERTIES IMPORT_SUFFIX "${IMPORT_LIB_SUFFIX}${CMAKE_IMPORT_LIBRARY_SUFFIX}") - set_target_properties(${LIB_SHARED} PROPERTIES POSITION_INDEPENDENT_CODE ON) + set_target_properties(${LIB_SHARED} PROPERTIES + PREFIX "" OUTPUT_NAME "libssh2" SOVERSION "${LIBSSH2_SOVERSION}" VERSION "${LIBSSH2_LIBVERSION}" + IMPORT_PREFIX "" IMPORT_SUFFIX "${IMPORT_LIB_SUFFIX}${CMAKE_IMPORT_LIBRARY_SUFFIX}" + POSITION_INDEPENDENT_CODE ON) target_include_directories(${LIB_SHARED} PRIVATE "${PROJECT_SOURCE_DIR}/include/" ${libssh2_INCLUDE_DIRS} ${PRIVATE_INCLUDE_DIRECTORIES} PUBLIC - $<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}/include> - $<INSTALL_INTERFACE:$<INSTALL_PREFIX>/${CMAKE_INSTALL_INCLUDEDIR}>) + "$<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}/include>" + "$<INSTALL_INTERFACE:$<INSTALL_PREFIX>/${CMAKE_INSTALL_INCLUDEDIR}>") endif() +add_library(${PROJECT_NAME}::${LIB_NAME} ALIAS ${LIB_SELECTED}) +add_library(${LIB_NAME} ALIAS ${LIB_SELECTED}) + ## Installation install(FILES - ${PROJECT_SOURCE_DIR}/include/libssh2.h - ${PROJECT_SOURCE_DIR}/include/libssh2_publickey.h - ${PROJECT_SOURCE_DIR}/include/libssh2_sftp.h + "${PROJECT_SOURCE_DIR}/include/libssh2.h" + "${PROJECT_SOURCE_DIR}/include/libssh2_publickey.h" + "${PROJECT_SOURCE_DIR}/include/libssh2_sftp.h" DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}) if(BUILD_STATIC_LIBS) install(TARGETS ${LIB_STATIC} - EXPORT Libssh2Config + EXPORT "${PROJECT_NAME}-targets" RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}) endif() if(BUILD_SHARED_LIBS) install(TARGETS ${LIB_SHARED} - EXPORT Libssh2Config + EXPORT "${PROJECT_NAME}-targets" RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}) @@ -163,55 +175,54 @@ set(RUNTIME_DEPENDENCIES ${_RUNTIME_DEPENDENCIES} CACHE INTERNAL # Package config -## During package installation, install Libssh2Config.cmake -install(EXPORT Libssh2Config - NAMESPACE Libssh2:: - DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/libssh2) +## During package installation, install libssh2-targets.cmake +install(EXPORT "${PROJECT_NAME}-targets" + NAMESPACE "${PROJECT_NAME}::" + DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME}") ## During build, register directly from build tree -# create Libssh2Config.cmake -export(TARGETS ${libssh2_export} NAMESPACE Libssh2:: FILE Libssh2Config.cmake) -export(PACKAGE Libssh2) # register it +# create libssh2-targets.cmake +export(TARGETS ${libssh2_export} NAMESPACE "${PROJECT_NAME}::" FILE "${PROJECT_NAME}-targets.cmake") +export(PACKAGE ${PROJECT_NAME}) # register it + +# Generate libssh2-config.cmake into build tree and install it +configure_file("${PROJECT_SOURCE_DIR}/cmake/libssh2-config.cmake.in" "${PROJECT_NAME}-config.cmake" @ONLY) +install( + FILES "${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}-config.cmake" + DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME}") ## Export a .pc file for client projects not using CMaek -if(PC_REQUIRES_PRIVATE) - string(REPLACE ";" "," PC_REQUIRES_PRIVATE "${PC_REQUIRES_PRIVATE}") +if(LIBSSH2_PC_REQUIRES_PRIVATE) + string(REPLACE ";" "," LIBSSH2_PC_REQUIRES_PRIVATE "${LIBSSH2_PC_REQUIRES_PRIVATE}") +endif() +if(LIBSSH2_PC_LIBS_PRIVATE) + list(REMOVE_DUPLICATES LIBSSH2_PC_LIBS_PRIVATE) + string(REPLACE ";" " " LIBSSH2_PC_LIBS_PRIVATE "${LIBSSH2_PC_LIBS_PRIVATE}") endif() -if(PC_LIBS) - string(REPLACE ";" " " PC_LIBS "${PC_LIBS}") +# merge the pkg-config private fields into public ones when static-only +if(BUILD_SHARED_LIBS) + set(LIBSSH2_PC_REQUIRES "") + set(LIBSSH2_PC_LIBS "") +else() + set(LIBSSH2_PC_REQUIRES "${LIBSSH2_PC_REQUIRES_PRIVATE}") + set(LIBSSH2_PC_LIBS "${LIBSSH2_PC_LIBS_PRIVATE}") endif() -set(LIBSSH2VER ${LIBSSH2_VERSION}) -set(LIBSREQUIRED ${PC_REQUIRES_PRIVATE}) -set(LIBS ${PC_LIBS}) set(prefix ${CMAKE_INSTALL_PREFIX}) set(exec_prefix "\${prefix}") set(libdir "\${prefix}/${CMAKE_INSTALL_LIBDIR}") set(includedir "\${prefix}/${CMAKE_INSTALL_INCLUDEDIR}") -configure_file(${CMAKE_SOURCE_DIR}/libssh2.pc.in libssh2.pc @ONLY) +configure_file("${PROJECT_SOURCE_DIR}/libssh2.pc.in" "libssh2.pc" @ONLY) install( - FILES ${CMAKE_CURRENT_BINARY_DIR}/libssh2.pc - DESTINATION ${CMAKE_INSTALL_LIBDIR}/pkgconfig) + FILES "${CMAKE_CURRENT_BINARY_DIR}/libssh2.pc" + DESTINATION "${CMAKE_INSTALL_LIBDIR}/pkgconfig") -## Versioning - -set(LIBSSH2_SOVERSION 1) -set(LIBSSH2_VERSION 1.0.1) -if(BUILD_STATIC_LIBS) - set_target_properties(${LIB_STATIC} PROPERTIES - SOVERSION ${LIBSSH2_SOVERSION} - VERSION ${LIBSSH2_VERSION}) -endif() -if(BUILD_SHARED_LIBS) - set_target_properties(${LIB_SHARED} PROPERTIES - SOVERSION ${LIBSSH2_SOVERSION} - VERSION ${LIBSSH2_VERSION}) -endif() +# include(CMakePackageConfigHelpers) write_basic_package_version_file( - ${CMAKE_CURRENT_BINARY_DIR}/Libssh2ConfigVersion.cmake + "${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}-config-version.cmake" VERSION "${LIBSSH2_VERSION_MAJOR}.${LIBSSH2_VERSION_MINOR}.${LIBSSH2_VERSION_PATCH}" COMPATIBILITY SameMajorVersion) install( - FILES ${CMAKE_CURRENT_BINARY_DIR}/Libssh2ConfigVersion.cmake - DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/libssh2) + FILES "${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}-config-version.cmake" + DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME}") diff --git a/libs/libssh2/src/Makefile.am b/libs/libssh2/src/Makefile.am index bd7b8de8ea..45b7a17275 100644 --- a/libs/libssh2/src/Makefile.am +++ b/libs/libssh2/src/Makefile.am @@ -19,6 +19,9 @@ lib_LTLIBRARIES = libssh2.la # tree AM_CPPFLAGS = -I$(top_builddir)/src -I$(top_srcdir)/include +# This might hold -Werror +CFLAGS += @LIBSSH2_CFLAG_EXTRAS@ + VERSION=-version-info 1:1:0 # This flag accepts an argument of the form current[:revision[:age]]. So, diff --git a/libs/libssh2/src/Makefile.inc b/libs/libssh2/src/Makefile.inc index a1876daceb..9133819a62 100644 --- a/libs/libssh2/src/Makefile.inc +++ b/libs/libssh2/src/Makefile.inc @@ -29,6 +29,7 @@ HHEADERS = \ channel.h \ comp.h \ crypto.h \ + crypto_config.h \ libgcrypt.h \ libssh2_priv.h \ libssh2_setup.h \ diff --git a/libs/libssh2/src/agent.c b/libs/libssh2/src/agent.c index d99a319550..dd709eb1fc 100644 --- a/libs/libssh2/src/agent.c +++ b/libs/libssh2/src/agent.c @@ -53,13 +53,14 @@ #undef PF_UNIX #endif -#if defined(WIN32) && !defined(LIBSSH2_WINDOWS_UWP) +#if defined(_WIN32) && !defined(LIBSSH2_WINDOWS_UWP) #define HAVE_WIN32_AGENTS #endif #include "userauth.h" #include "session.h" +#if 0 /* Requests from client to agent for protocol 1 key operations */ #define SSH_AGENTC_REQUEST_RSA_IDENTITIES 1 #define SSH_AGENTC_RSA_CHALLENGE 3 @@ -67,10 +68,12 @@ #define SSH_AGENTC_REMOVE_RSA_IDENTITY 8 #define SSH_AGENTC_REMOVE_ALL_RSA_IDENTITIES 9 #define SSH_AGENTC_ADD_RSA_ID_CONSTRAINED 24 +#endif /* Requests from client to agent for protocol 2 key operations */ #define SSH2_AGENTC_REQUEST_IDENTITIES 11 #define SSH2_AGENTC_SIGN_REQUEST 13 +#if 0 #define SSH2_AGENTC_ADD_IDENTITY 17 #define SSH2_AGENTC_REMOVE_IDENTITY 18 #define SSH2_AGENTC_REMOVE_ALL_IDENTITIES 19 @@ -91,13 +94,14 @@ #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 +#endif + +/* Replies from agent to client for protocol 2 key operations */ +#define SSH2_AGENT_IDENTITIES_ANSWER 12 +#define SSH2_AGENT_SIGN_RESPONSE 14 /* Signature request methods */ #define SSH_AGENT_RSA_SHA2_256 2 @@ -559,7 +563,7 @@ agent_sign(LIBSSH2_SESSION *session, unsigned char **sig, size_t *sig_len, _libssh2_debug((session, LIBSSH2_TRACE_KEX, "Agent sign method %.*s", - method_len, method_name)); + (int)method_len, method_name)); rc = LIBSSH2_ERROR_ALGO_UNSUPPORTED; goto error; diff --git a/libs/libssh2/src/bcrypt_pbkdf.c b/libs/libssh2/src/bcrypt_pbkdf.c index d088587873..414c5e4e36 100644 --- a/libs/libssh2/src/bcrypt_pbkdf.c +++ b/libs/libssh2/src/bcrypt_pbkdf.c @@ -127,9 +127,12 @@ bcrypt_pbkdf(const char *pass, size_t passlen, const uint8_t *salt, memcpy(countsalt, salt, saltlen); /* collapse password */ - (void)libssh2_sha512_init(&ctx); - libssh2_sha512_update(ctx, pass, passlen); - libssh2_sha512_final(ctx, sha2pass); + if(!libssh2_sha512_init(&ctx) || + !libssh2_sha512_update(ctx, pass, passlen) || + !libssh2_sha512_final(ctx, sha2pass)) { + free(countsalt); + return -1; + } /* generate key, sizeof(out) at a time */ for(count = 1; keylen > 0; count++) { @@ -139,18 +142,26 @@ bcrypt_pbkdf(const char *pass, size_t passlen, const uint8_t *salt, countsalt[saltlen + 3] = count & 0xff; /* first round, salt is salt */ - (void)libssh2_sha512_init(&ctx); - libssh2_sha512_update(ctx, countsalt, saltlen + 4); - libssh2_sha512_final(ctx, sha2salt); + if(!libssh2_sha512_init(&ctx) || + !libssh2_sha512_update(ctx, countsalt, saltlen + 4) || + !libssh2_sha512_final(ctx, sha2salt)) { + _libssh2_explicit_zero(out, sizeof(out)); + free(countsalt); + return -1; + } bcrypt_hash(sha2pass, sha2salt, tmpout); memcpy(out, tmpout, sizeof(out)); for(i = 1; i < rounds; i++) { /* subsequent rounds, salt is previous output */ - (void)libssh2_sha512_init(&ctx); - libssh2_sha512_update(ctx, tmpout, sizeof(tmpout)); - libssh2_sha512_final(ctx, sha2salt); + if(!libssh2_sha512_init(&ctx) || + !libssh2_sha512_update(ctx, tmpout, sizeof(tmpout)) || + !libssh2_sha512_final(ctx, sha2salt)) { + _libssh2_explicit_zero(out, sizeof(out)); + free(countsalt); + return -1; + } bcrypt_hash(sha2pass, sha2salt, tmpout); for(j = 0; j < sizeof(out); j++) diff --git a/libs/libssh2/src/channel.c b/libs/libssh2/src/channel.c index c35658a04e..2f7d162c72 100644 --- a/libs/libssh2/src/channel.c +++ b/libs/libssh2/src/channel.c @@ -84,7 +84,7 @@ _libssh2_channel_nextid(LIBSSH2_SESSION * session) */ session->next_channel = id + 1; _libssh2_debug((session, LIBSSH2_TRACE_CONN, - "Allocated new channel ID#%lu", id)); + "Allocated new channel ID#%u", id)); return id; } @@ -265,8 +265,8 @@ _libssh2_channel_open(LIBSSH2_SESSION * session, const char *channel_type, 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", + "Connection Established - ID: %u/%u win: %u/%u" + " pack: %u/%u", session->open_channel->local.id, session->open_channel->remote.id, session->open_channel->local.window_size, @@ -902,7 +902,7 @@ static int channel_setenv(LIBSSH2_CHANNEL *channel, _libssh2_debug((session, LIBSSH2_TRACE_CONN, "Setting remote environment variable: %s=%s on " - "channel %lu/%lu", + "channel %u/%u", varname, value, channel->local.id, channel->remote.id)); s = channel->setenv_packet = @@ -1036,7 +1036,7 @@ static int channel_request_pty(LIBSSH2_CHANNEL *channel, sizeof(channel->reqPTY_packet_requirev_state)); _libssh2_debug((session, LIBSSH2_TRACE_CONN, - "Allocating tty on channel %lu/%lu", channel->local.id, + "Allocating tty on channel %u/%u", channel->local.id, channel->remote.id)); s = channel->reqPTY_packet; @@ -1139,7 +1139,7 @@ static int channel_request_auth_agent(LIBSSH2_CHANNEL *channel, sizeof(channel->req_auth_agent_requirev_state)); _libssh2_debug((session, LIBSSH2_TRACE_CONN, - "Requesting auth agent on channel %lu/%lu", + "Requesting auth agent on channel %u/%u", channel->local.id, channel->remote.id)); /* @@ -1303,7 +1303,7 @@ channel_request_pty_size(LIBSSH2_CHANNEL * channel, int width, sizeof(channel->reqPTY_packet_requirev_state)); _libssh2_debug((session, LIBSSH2_TRACE_CONN, - "changing tty size on channel %lu/%lu", + "changing tty size on channel %u/%u", channel->local.id, channel->remote.id)); @@ -1392,7 +1392,7 @@ channel_x11_req(LIBSSH2_CHANNEL *channel, int single_connection, sizeof(channel->reqX11_packet_requirev_state)); _libssh2_debug((session, LIBSSH2_TRACE_CONN, - "Requesting x11-req for channel %lu/%lu: single=%d " + "Requesting x11-req for channel %u/%u: single=%d " "proto=%s cookie=%s screen=%d", channel->local.id, channel->remote.id, single_connection, @@ -1550,7 +1550,7 @@ _libssh2_channel_process_startup(LIBSSH2_CHANNEL *channel, channel->process_packet_len += + 4; _libssh2_debug((session, LIBSSH2_TRACE_CONN, - "starting request(%s) on channel %lu/%lu, message=%s", + "starting request(%s) on channel %u/%u, message=%s", request, channel->local.id, channel->remote.id, message ? message : "<null>")); s = channel->process_packet = @@ -1719,9 +1719,9 @@ _libssh2_channel_flush(LIBSSH2_CHANNEL *channel, int streamid) 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, + "Flushing %ld bytes of data from stream " + "%d on channel %u/%u", + (long)bytes_to_flush, packet_stream_id, channel->local.id, channel->remote.id)); /* It's one of the streams we wanted to flush */ @@ -1882,8 +1882,8 @@ _libssh2_channel_receive_window_adjust(LIBSSH2_CHANNEL * channel, && (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", + "Queueing %u bytes for receive window adjustment " + "for channel %u/%u", adjustment, channel->local.id, channel->remote.id)); channel->adjust_queue += adjustment; return 0; @@ -1901,8 +1901,8 @@ _libssh2_channel_receive_window_adjust(LIBSSH2_CHANNEL * channel, _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", + "Adjusting window %u bytes for data on " + "channel %u/%u", adjustment, channel->local.id, channel->remote.id)); channel->adjust_state = libssh2_NB_state_created; @@ -1930,10 +1930,9 @@ _libssh2_channel_receive_window_adjust(LIBSSH2_CHANNEL * channel, return 0; } +#ifndef LIBSSH2_NO_DEPRECATED /* - * libssh2_channel_receive_window_adjust - * - * DEPRECATED + * libssh2_channel_receive_window_adjust (DEPRECATED, DO NOT USE!) * * 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 @@ -1963,6 +1962,7 @@ libssh2_channel_receive_window_adjust(LIBSSH2_CHANNEL *channel, kept for backwards compatibility */ return rc ? (unsigned long)rc : window; } +#endif /* * libssh2_channel_receive_window_adjust2 @@ -1998,7 +1998,7 @@ _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" + "Setting channel %u/%u handle_extended_data" " mode to %d", channel->local.id, channel->remote.id, ignore_mode)); channel->remote.extended_data_ignore_mode = (char)ignore_mode; @@ -2038,10 +2038,9 @@ libssh2_channel_handle_extended_data2(LIBSSH2_CHANNEL *channel, return rc; } +#ifndef LIBSSH2_NO_DEPRECATED /* - * libssh2_channel_handle_extended_data - * - * DEPRECATED DO NOTE USE! + * libssh2_channel_handle_extended_data (DEPRECATED, DO NOT 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 @@ -2054,7 +2053,7 @@ libssh2_channel_handle_extended_data(LIBSSH2_CHANNEL *channel, { (void)libssh2_channel_handle_extended_data2(channel, ignore_mode); } - +#endif /* @@ -2081,9 +2080,9 @@ ssize_t _libssh2_channel_read(LIBSSH2_CHANNEL *channel, int stream_id, LIBSSH2_PACKET *read_next; _libssh2_debug((session, LIBSSH2_TRACE_CONN, - "channel_read() wants %d bytes from channel %lu/%lu " + "channel_read() wants %ld bytes from channel %u/%u " "stream #%d", - (int) buflen, channel->local.id, channel->remote.id, + (long)buflen, channel->local.id, channel->remote.id, stream_id)); /* expand the receiving window first if it has become too narrow */ @@ -2178,8 +2177,8 @@ ssize_t _libssh2_channel_read(LIBSSH2_CHANNEL *channel, int stream_id, } _libssh2_debug((session, LIBSSH2_TRACE_CONN, - "channel_read() got %d of data from %lu/%lu/%d%s", - bytes_want, channel->local.id, + "channel_read() got %ld of data from %u/%u/%d%s", + (long)bytes_want, channel->local.id, channel->remote.id, stream_id, unlink_packet?" [ul]":"")); @@ -2356,8 +2355,8 @@ _libssh2_channel_write(LIBSSH2_CHANNEL *channel, int stream_id, 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, + "Writing %ld bytes on channel %u/%u, stream #%d", + (long)buflen, channel->local.id, channel->remote.id, stream_id)); if(channel->local.close) @@ -2405,16 +2404,16 @@ _libssh2_channel_write(LIBSSH2_CHANNEL *channel, int stream_id, /* 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", + "Splitting write block due to %u byte " + "window_size on %u/%u/%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", + "Splitting write block due to %u byte " + "packet_size on %u/%u/%d", channel->local.packet_size, channel->local.id, channel->remote.id, stream_id)); channel->write_bufwrite = channel->local.packet_size; @@ -2425,8 +2424,8 @@ _libssh2_channel_write(LIBSSH2_CHANNEL *channel, int stream_id, 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, + "Sending %ld bytes on channel %u/%u, stream_id=%d", + (long)channel->write_bufwrite, channel->local.id, channel->remote.id, stream_id)); channel->write_state = libssh2_NB_state_created; @@ -2500,7 +2499,7 @@ static int channel_send_eof(LIBSSH2_CHANNEL *channel) int rc; _libssh2_debug((session, LIBSSH2_TRACE_CONN, - "Sending EOF on channel %lu/%lu", + "Sending EOF on channel %u/%u", channel->local.id, channel->remote.id)); packet[0] = SSH_MSG_CHANNEL_EOF; _libssh2_htonu32(packet + 1, channel->remote.id); @@ -2590,7 +2589,7 @@ static int channel_wait_eof(LIBSSH2_CHANNEL *channel) if(channel->wait_eof_state == libssh2_NB_state_idle) { _libssh2_debug((session, LIBSSH2_TRACE_CONN, - "Awaiting EOF for channel %lu/%lu", channel->local.id, + "Awaiting EOF for channel %u/%u", channel->local.id, channel->remote.id)); channel->wait_eof_state = libssh2_NB_state_created; @@ -2671,7 +2670,7 @@ int _libssh2_channel_close(LIBSSH2_CHANNEL * channel) 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", + _libssh2_debug((session, LIBSSH2_TRACE_CONN, "Closing channel %u/%u", channel->local.id, channel->remote.id)); channel->close_packet[0] = SSH_MSG_CHANNEL_CLOSE; @@ -2762,7 +2761,7 @@ static int channel_wait_closed(LIBSSH2_CHANNEL *channel) if(channel->wait_closed_state == libssh2_NB_state_idle) { _libssh2_debug((session, LIBSSH2_TRACE_CONN, - "Awaiting close of channel %lu/%lu", channel->local.id, + "Awaiting close of channel %u/%u", channel->local.id, channel->remote.id)); channel->wait_closed_state = libssh2_NB_state_created; @@ -2825,7 +2824,7 @@ int _libssh2_channel_free(LIBSSH2_CHANNEL *channel) if(channel->free_state == libssh2_NB_state_idle) { _libssh2_debug((session, LIBSSH2_TRACE_CONN, - "Freeing channel %lu/%lu resources", channel->local.id, + "Freeing channel %u/%u resources", channel->local.id, channel->remote.id)); channel->free_state = libssh2_NB_state_created; diff --git a/libs/libssh2/src/channel.h b/libs/libssh2/src/channel.h index 6d03550164..709ec0615f 100644 --- a/libs/libssh2/src/channel.h +++ b/libs/libssh2/src/channel.h @@ -1,5 +1,5 @@ -#ifndef __LIBSSH2_CHANNEL_H -#define __LIBSSH2_CHANNEL_H +#ifndef LIBSSH2_CHANNEL_H +#define LIBSSH2_CHANNEL_H /* Copyright (C) Daniel Stenberg * * All rights reserved. @@ -139,4 +139,4 @@ int _libssh2_channel_close(LIBSSH2_CHANNEL * channel); */ int _libssh2_channel_forward_cancel(LIBSSH2_LISTENER *listener); -#endif /* __LIBSSH2_CHANNEL_H */ +#endif /* LIBSSH2_CHANNEL_H */ diff --git a/libs/libssh2/src/comp.c b/libs/libssh2/src/comp.c index 55ddb85a48..ecfb28a315 100644 --- a/libs/libssh2/src/comp.c +++ b/libs/libssh2/src/comp.c @@ -208,7 +208,7 @@ comp_method_zlib_comp(LIBSSH2_SESSION *session, } _libssh2_debug((session, LIBSSH2_TRACE_TRANS, - "unhandled zlib compression error %d, avail_out", + "unhandled zlib compression error %d, avail_out %u", status, strm->avail_out)); return _libssh2_error(session, LIBSSH2_ERROR_ZLIB, "compression failure"); } diff --git a/libs/libssh2/src/comp.h b/libs/libssh2/src/comp.h index cce113b2bc..6a35d69494 100644 --- a/libs/libssh2/src/comp.h +++ b/libs/libssh2/src/comp.h @@ -1,5 +1,5 @@ -#ifndef __LIBSSH2_COMP_H -#define __LIBSSH2_COMP_H +#ifndef LIBSSH2_COMP_H +#define LIBSSH2_COMP_H /* Copyright (C) Daniel Stenberg * * Redistribution and use in source and binary forms, @@ -42,4 +42,4 @@ const LIBSSH2_COMP_METHOD **_libssh2_comp_methods(LIBSSH2_SESSION *session); -#endif /* __LIBSSH2_COMP_H */ +#endif /* LIBSSH2_COMP_H */ diff --git a/libs/libssh2/src/crypto.h b/libs/libssh2/src/crypto.h index 561cd96e2b..487444145d 100644 --- a/libs/libssh2/src/crypto.h +++ b/libs/libssh2/src/crypto.h @@ -1,5 +1,5 @@ -#ifndef __LIBSSH2_CRYPTO_H -#define __LIBSSH2_CRYPTO_H +#ifndef LIBSSH2_CRYPTO_H +#define LIBSSH2_CRYPTO_H /* Copyright (C) Simon Josefsson * Copyright (C) The Written Word, Inc. * Copyright (C) Daniel Stenberg @@ -55,70 +55,26 @@ #error "no cryptography backend selected" #endif -#ifdef LIBSSH2_NO_MD5 -#undef LIBSSH2_MD5 -#define LIBSSH2_MD5 0 +/* return: success = 1, error = 0 */ +int _libssh2_hmac_ctx_init(libssh2_hmac_ctx *ctx); +#if LIBSSH2_MD5 +int _libssh2_hmac_md5_init(libssh2_hmac_ctx *ctx, + void *key, size_t keylen); #endif - -#ifdef LIBSSH2_NO_HMAC_RIPEMD -#undef LIBSSH2_HMAC_RIPEMD -#define LIBSSH2_HMAC_RIPEMD 0 -#endif - -#ifdef LIBSSH2_NO_DSA -#undef LIBSSH2_DSA -#define LIBSSH2_DSA 0 -#endif - -#ifdef LIBSSH2_NO_RSA -#undef LIBSSH2_RSA -#define LIBSSH2_RSA 0 -#endif - -#ifdef LIBSSH2_NO_RSA_SHA1 -#undef LIBSSH2_RSA_SHA1 -#define LIBSSH2_RSA_SHA1 0 -#endif - -#ifdef LIBSSH2_NO_ECDSA -#undef LIBSSH2_ECDSA -#define LIBSSH2_ECDSA 0 -#endif - -#ifdef LIBSSH2_NO_ED25519 -#undef LIBSSH2_ED25519 -#define LIBSSH2_ED25519 0 -#endif - -#ifdef LIBSSH2_NO_AES_CTR -#undef LIBSSH2_AES_CTR -#define LIBSSH2_AES_CTR 0 -#endif - -#ifdef LIBSSH2_NO_AES_CBC -#undef LIBSSH2_AES_CBC -#define LIBSSH2_AES_CBC 0 -#endif - -#ifdef LIBSSH2_NO_BLOWFISH -#undef LIBSSH2_BLOWFISH -#define LIBSSH2_BLOWFISH 0 -#endif - -#ifdef LIBSSH2_NO_RC4 -#undef LIBSSH2_RC4 -#define LIBSSH2_RC4 0 -#endif - -#ifdef LIBSSH2_NO_CAST -#undef LIBSSH2_CAST -#define LIBSSH2_CAST 0 -#endif - -#ifdef LIBSSH2_NO_3DES -#undef LIBSSH2_3DES -#define LIBSSH2_3DES 0 +#if LIBSSH2_HMAC_RIPEMD +int _libssh2_hmac_ripemd160_init(libssh2_hmac_ctx *ctx, + void *key, size_t keylen); #endif +int _libssh2_hmac_sha1_init(libssh2_hmac_ctx *ctx, + void *key, size_t keylen); +int _libssh2_hmac_sha256_init(libssh2_hmac_ctx *ctx, + void *key, size_t keylen); +int _libssh2_hmac_sha512_init(libssh2_hmac_ctx *ctx, + void *key, size_t keylen); +int _libssh2_hmac_update(libssh2_hmac_ctx *ctx, + const void *data, size_t datalen); +int _libssh2_hmac_final(libssh2_hmac_ctx *ctx, void *data); +void _libssh2_hmac_cleanup(libssh2_hmac_ctx *ctx); #define LIBSSH2_ED25519_KEY_LEN 32 #define LIBSSH2_ED25519_PRIVATE_KEY_LEN 64 @@ -146,16 +102,16 @@ int _libssh2_rsa_new_private(libssh2_rsa_ctx ** rsa, const char *filename, unsigned const char *passphrase); #if LIBSSH2_RSA_SHA1 -int _libssh2_rsa_sha1_verify(libssh2_rsa_ctx * rsa, - const unsigned char *sig, - size_t sig_len, - const unsigned char *m, size_t 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_sha1_verify(libssh2_rsa_ctx * rsa, + const unsigned char *sig, + size_t sig_len, + const unsigned char *m, size_t m_len); #endif #if LIBSSH2_RSA_SHA2 int _libssh2_rsa_sha2_sign(LIBSSH2_SESSION * session, @@ -398,4 +354,4 @@ _libssh2_supported_key_sign_algorithms(LIBSSH2_SESSION *session, unsigned char *key_method, size_t key_method_len); -#endif /* __LIBSSH2_CRYPTO_H */ +#endif /* LIBSSH2_CRYPTO_H */ diff --git a/libs/libssh2/src/crypto_config.h b/libs/libssh2/src/crypto_config.h new file mode 100644 index 0000000000..5934e140b6 --- /dev/null +++ b/libs/libssh2/src/crypto_config.h @@ -0,0 +1,76 @@ +/* Copyright (C) Viktor Szakats + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#define LIBSSH2_MD5_PEM LIBSSH2_MD5 + +#ifdef LIBSSH2_NO_MD5 +#undef LIBSSH2_MD5 +#define LIBSSH2_MD5 0 +#endif + +#ifdef LIBSSH2_NO_MD5_PEM +#undef LIBSSH2_MD5_PEM +#define LIBSSH2_MD5_PEM 0 +#endif + +#ifdef LIBSSH2_NO_HMAC_RIPEMD +#undef LIBSSH2_HMAC_RIPEMD +#define LIBSSH2_HMAC_RIPEMD 0 +#endif + +#ifdef LIBSSH2_NO_DSA +#undef LIBSSH2_DSA +#define LIBSSH2_DSA 0 +#endif + +#ifdef LIBSSH2_NO_RSA +#undef LIBSSH2_RSA +#define LIBSSH2_RSA 0 +#endif + +#ifdef LIBSSH2_NO_RSA_SHA1 +#undef LIBSSH2_RSA_SHA1 +#define LIBSSH2_RSA_SHA1 0 +#endif + +#ifdef LIBSSH2_NO_ECDSA +#undef LIBSSH2_ECDSA +#define LIBSSH2_ECDSA 0 +#endif + +#ifdef LIBSSH2_NO_ED25519 +#undef LIBSSH2_ED25519 +#define LIBSSH2_ED25519 0 +#endif + +#ifdef LIBSSH2_NO_AES_CTR +#undef LIBSSH2_AES_CTR +#define LIBSSH2_AES_CTR 0 +#endif + +#ifdef LIBSSH2_NO_AES_CBC +#undef LIBSSH2_AES_CBC +#define LIBSSH2_AES_CBC 0 +#endif + +#ifdef LIBSSH2_NO_BLOWFISH +#undef LIBSSH2_BLOWFISH +#define LIBSSH2_BLOWFISH 0 +#endif + +#ifdef LIBSSH2_NO_RC4 +#undef LIBSSH2_RC4 +#define LIBSSH2_RC4 0 +#endif + +#ifdef LIBSSH2_NO_CAST +#undef LIBSSH2_CAST +#define LIBSSH2_CAST 0 +#endif + +#ifdef LIBSSH2_NO_3DES +#undef LIBSSH2_3DES +#define LIBSSH2_3DES 0 +#endif diff --git a/libs/libssh2/src/hostkey.c b/libs/libssh2/src/hostkey.c index 56eee369f5..b28b4e6995 100644 --- a/libs/libssh2/src/hostkey.c +++ b/libs/libssh2/src/hostkey.c @@ -106,7 +106,7 @@ hostkey_method_ssh_rsa_init(LIBSSH2_SESSION * session, #endif { _libssh2_debug((session, LIBSSH2_TRACE_ERROR, - "unexpected rsa type: %.*s", type_len, type)); + "unexpected rsa type: %.*s", (int)type_len, type)); return -1; } @@ -242,11 +242,18 @@ hostkey_method_ssh_rsa_signv(LIBSSH2_SESSION * session, unsigned char hash[SHA_DIGEST_LENGTH]; libssh2_sha1_ctx ctx; - (void)libssh2_sha1_init(&ctx); + if(!libssh2_sha1_init(&ctx)) { + return -1; + } for(i = 0; i < veccount; i++) { - libssh2_sha1_update(ctx, datavec[i].iov_base, datavec[i].iov_len); + if(!libssh2_sha1_update(ctx, + datavec[i].iov_base, datavec[i].iov_len)) { + return -1; + } + } + if(!libssh2_sha1_final(ctx, hash)) { + return -1; } - libssh2_sha1_final(ctx, hash); ret = _libssh2_rsa_sha1_sign(session, rsactx, hash, SHA_DIGEST_LENGTH, signature, signature_len); @@ -316,9 +323,14 @@ hostkey_method_ssh_rsa_sha2_256_signv(LIBSSH2_SESSION * session, return -1; } for(i = 0; i < veccount; i++) { - libssh2_sha256_update(ctx, datavec[i].iov_base, datavec[i].iov_len); + if(!libssh2_sha256_update(ctx, + datavec[i].iov_base, datavec[i].iov_len)) { + return -1; + } + } + if(!libssh2_sha256_final(ctx, hash)) { + return -1; } - libssh2_sha256_final(ctx, hash); ret = _libssh2_rsa_sha2_sign(session, rsactx, hash, SHA256_DIGEST_LENGTH, signature, signature_len); @@ -386,9 +398,14 @@ hostkey_method_ssh_rsa_sha2_512_signv(LIBSSH2_SESSION * session, return -1; } for(i = 0; i < veccount; i++) { - libssh2_sha512_update(ctx, datavec[i].iov_base, datavec[i].iov_len); + if(!libssh2_sha512_update(ctx, + datavec[i].iov_base, datavec[i].iov_len)) { + return -1; + } + } + if(!libssh2_sha512_final(ctx, hash)) { + return -1; } - libssh2_sha512_final(ctx, hash); ret = _libssh2_rsa_sha2_sign(session, rsactx, hash, SHA512_DIGEST_LENGTH, signature, signature_len); @@ -659,6 +676,12 @@ hostkey_method_ssh_dss_signv(LIBSSH2_SESSION * session, libssh2_sha1_ctx ctx; int i; + if(!libssh2_sha1_init(&ctx)) { + *signature = NULL; + *signature_len = 0; + return -1; + } + *signature = LIBSSH2_CALLOC(session, 2 * SHA_DIGEST_LENGTH); if(!*signature) { return -1; @@ -666,11 +689,15 @@ hostkey_method_ssh_dss_signv(LIBSSH2_SESSION * session, *signature_len = 2 * SHA_DIGEST_LENGTH; - (void)libssh2_sha1_init(&ctx); for(i = 0; i < veccount; i++) { - libssh2_sha1_update(ctx, datavec[i].iov_base, datavec[i].iov_len); + if(!libssh2_sha1_update(ctx, + datavec[i].iov_base, datavec[i].iov_len)) { + return -1; + } + } + if(!libssh2_sha1_final(ctx, hash)) { + return -1; } - libssh2_sha1_final(ctx, hash); if(_libssh2_dsa_sha1_sign(dsactx, hash, SHA_DIGEST_LENGTH, *signature)) { LIBSSH2_FREE(session, *signature); @@ -909,20 +936,33 @@ hostkey_method_ssh_ecdsa_sig_verify(LIBSSH2_SESSION * session, } -#define LIBSSH2_HOSTKEY_METHOD_EC_SIGNV_HASH(digest_type) \ - do { \ - unsigned char hash[SHA##digest_type##_DIGEST_LENGTH]; \ - libssh2_sha##digest_type##_ctx ctx; \ - int i; \ - (void)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); \ +#define LIBSSH2_HOSTKEY_METHOD_EC_SIGNV_HASH(digest_type) \ + do { \ + unsigned char hash[SHA##digest_type##_DIGEST_LENGTH]; \ + libssh2_sha##digest_type##_ctx ctx; \ + int i; \ + if(!libssh2_sha##digest_type##_init(&ctx)) { \ + ret = -1; \ + break; \ + } \ + for(i = 0; i < veccount; i++) { \ + if(!libssh2_sha##digest_type##_update(ctx, \ + datavec[i].iov_base, \ + datavec[i].iov_len)) { \ + ret = -1; \ + break; \ + } \ + } \ + if(ret == -1) { \ + break; \ + } \ + if(!libssh2_sha##digest_type##_final(ctx, hash)) { \ + ret = -1; \ + break; \ + } \ + ret = _libssh2_ecdsa_sign(session, ec_ctx, hash, \ + SHA##digest_type##_DIGEST_LENGTH, \ + signature, signature_len); \ } while(0) @@ -1224,7 +1264,8 @@ hostkey_method_ssh_ed25519_signv(LIBSSH2_SESSION * session, } return _libssh2_ed25519_sign(ctx, session, signature, signature_len, - datavec[0].iov_base, datavec[0].iov_len); + (const uint8_t *)datavec[0].iov_base, + datavec[0].iov_len); } @@ -1326,18 +1367,15 @@ libssh2_hostkey_hash(LIBSSH2_SESSION * session, int hash_type) 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; } diff --git a/libs/libssh2/src/keepalive.c b/libs/libssh2/src/keepalive.c index 54fddb060f..489a1daaa9 100644 --- a/libs/libssh2/src/keepalive.c +++ b/libs/libssh2/src/keepalive.c @@ -45,7 +45,7 @@ LIBSSH2_API void libssh2_keepalive_config(LIBSSH2_SESSION *session, int want_reply, - unsigned interval) + unsigned int interval) { if(interval == 1) session->keepalive_interval = 2; diff --git a/libs/libssh2/src/kex.c b/libs/libssh2/src/kex.c index 8972d44bb3..8c65a0fee6 100644 --- a/libs/libssh2/src/kex.c +++ b/libs/libssh2/src/kex.c @@ -55,6 +55,7 @@ /* Helper macro called from kex_method_diffie_hellman_group1_sha1_key_exchange */ +#if LIBSSH2_ECDSA #define LIBSSH2_KEX_METHOD_EC_SHA_VALUE_HASH(value, reqlen, version) \ do { \ if(type == LIBSSH2_EC_CURVE_NISTP256) { \ @@ -67,6 +68,7 @@ LIBSSH2_KEX_METHOD_SHA_VALUE_HASH(512, value, reqlen, version); \ } \ } while(0) +#endif #define LIBSSH2_KEX_METHOD_SHA_VALUE_HASH(digest_type, value, \ reqlen, version) \ @@ -79,22 +81,40 @@ do { \ } \ if(value) \ while(len < (size_t)reqlen) { \ - (void)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(!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)) { \ + LIBSSH2_FREE(session, value); \ + value = NULL; \ + break; \ + } \ if(len > 0) { \ - libssh2_sha##digest_type##_update(hash, value, len); \ + if(!libssh2_sha##digest_type##_update(hash, value, len)) { \ + LIBSSH2_FREE(session, value); \ + value = NULL; \ + break; \ + } \ } \ else { \ - libssh2_sha##digest_type##_update(hash, (version), 1); \ - libssh2_sha##digest_type##_update(hash, session->session_id,\ - session->session_id_len); \ + if(!libssh2_sha##digest_type##_update(hash, \ + (version), 1) || \ + !libssh2_sha##digest_type##_update(hash, \ + session->session_id, \ + session->session_id_len)) { \ + LIBSSH2_FREE(session, value); \ + value = NULL; \ + break; \ + } \ + } \ + if(!libssh2_sha##digest_type##_final(hash, (value) + len)) { \ + LIBSSH2_FREE(session, value); \ + value = NULL; \ + break; \ } \ - libssh2_sha##digest_type##_final(hash, (value) + len); \ len += SHA##digest_type##_DIGEST_LENGTH; \ } \ } while(0) @@ -106,75 +126,80 @@ do { \ * don't allow it so we have to wrap them up in helper functions */ -static void _libssh2_sha_algo_ctx_init(int sha_algo, void *ctx) +static int _libssh2_sha_algo_ctx_init(int sha_algo, void *ctx) { if(sha_algo == 512) { - (void)libssh2_sha512_init((libssh2_sha512_ctx*)ctx); + return libssh2_sha512_init((libssh2_sha512_ctx*)ctx); } else if(sha_algo == 384) { - (void)libssh2_sha384_init((libssh2_sha384_ctx*)ctx); + return libssh2_sha384_init((libssh2_sha384_ctx*)ctx); } else if(sha_algo == 256) { - (void)libssh2_sha256_init((libssh2_sha256_ctx*)ctx); + return libssh2_sha256_init((libssh2_sha256_ctx*)ctx); } else if(sha_algo == 1) { - (void)libssh2_sha1_init((libssh2_sha1_ctx*)ctx); + return libssh2_sha1_init((libssh2_sha1_ctx*)ctx); } else { +#ifdef LIBSSH2DEBUG assert(0); +#endif } + return 0; } -static void _libssh2_sha_algo_ctx_update(int sha_algo, void *ctx, - void *data, size_t len) +static int _libssh2_sha_algo_ctx_update(int sha_algo, void *ctx, + void *data, size_t len) { if(sha_algo == 512) { libssh2_sha512_ctx *_ctx = (libssh2_sha512_ctx*)ctx; - libssh2_sha512_update(*_ctx, data, len); + return libssh2_sha512_update(*_ctx, data, len); } else if(sha_algo == 384) { libssh2_sha384_ctx *_ctx = (libssh2_sha384_ctx*)ctx; - libssh2_sha384_update(*_ctx, data, len); + return libssh2_sha384_update(*_ctx, data, len); } else if(sha_algo == 256) { libssh2_sha256_ctx *_ctx = (libssh2_sha256_ctx*)ctx; - libssh2_sha256_update(*_ctx, data, len); + return libssh2_sha256_update(*_ctx, data, len); } else if(sha_algo == 1) { libssh2_sha1_ctx *_ctx = (libssh2_sha1_ctx*)ctx; - libssh2_sha1_update(*_ctx, data, len); + return libssh2_sha1_update(*_ctx, data, len); } else { #ifdef LIBSSH2DEBUG assert(0); #endif } + return 0; } -static void _libssh2_sha_algo_ctx_final(int sha_algo, void *ctx, - void *hash) +static int _libssh2_sha_algo_ctx_final(int sha_algo, void *ctx, + void *hash) { if(sha_algo == 512) { libssh2_sha512_ctx *_ctx = (libssh2_sha512_ctx*)ctx; - libssh2_sha512_final(*_ctx, hash); + return libssh2_sha512_final(*_ctx, hash); } else if(sha_algo == 384) { libssh2_sha384_ctx *_ctx = (libssh2_sha384_ctx*)ctx; - libssh2_sha384_final(*_ctx, hash); + return libssh2_sha384_final(*_ctx, hash); } else if(sha_algo == 256) { libssh2_sha256_ctx *_ctx = (libssh2_sha256_ctx*)ctx; - libssh2_sha256_final(*_ctx, hash); + return libssh2_sha256_final(*_ctx, hash); } else if(sha_algo == 1) { libssh2_sha1_ctx *_ctx = (libssh2_sha1_ctx*)ctx; - libssh2_sha1_final(*_ctx, hash); + return libssh2_sha1_final(*_ctx, hash); } else { #ifdef LIBSSH2DEBUG assert(0); #endif } + return 0; } static void _libssh2_sha_algo_value_hash(int sha_algo, @@ -300,8 +325,8 @@ static int diffie_hellman_sha_algo(LIBSSH2_SESSION *session, exchange_state->e_packet + 6); } - _libssh2_debug((session, LIBSSH2_TRACE_KEX, "Sending KEX packet %d", - (int) packet_type_init)); + _libssh2_debug((session, LIBSSH2_TRACE_KEX, "Sending KEX packet %u", + (unsigned int) packet_type_init)); exchange_state->state = libssh2_NB_state_created; } @@ -355,6 +380,7 @@ static int diffie_hellman_sha_algo(LIBSSH2_SESSION *session, struct string_buf buf; size_t host_key_len; int err; + int hok; rc = _libssh2_packet_require(session, packet_type_reply, &exchange_state->s_packet, @@ -397,11 +423,11 @@ static int diffie_hellman_sha_algo(LIBSSH2_SESSION *session, { 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); + 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 { @@ -425,11 +451,11 @@ static int diffie_hellman_sha_algo(LIBSSH2_SESSION *session, { 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); + 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 { @@ -452,11 +478,11 @@ static int diffie_hellman_sha_algo(LIBSSH2_SESSION *session, { 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); + 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 { @@ -532,59 +558,66 @@ static int diffie_hellman_sha_algo(LIBSSH2_SESSION *session, } exchange_state->exchange_hash = (void *)&exchange_hash_ctx; - _libssh2_sha_algo_ctx_init(sha_algo_value, exchange_hash_ctx); - + if(!_libssh2_sha_algo_ctx_init(sha_algo_value, exchange_hash_ctx)) { + ret = _libssh2_error(session, LIBSSH2_ERROR_HASH_INIT, + "Unable to initialize hash context"); + goto clean_exit; + } + hok = 1; if(session->local.banner) { _libssh2_htonu32(exchange_state->h_sig_comp, (uint32_t)(strlen((char *) session->local.banner) - 2)); - _libssh2_sha_algo_ctx_update(sha_algo_value, exchange_hash_ctx, - exchange_state->h_sig_comp, 4); - _libssh2_sha_algo_ctx_update(sha_algo_value, exchange_hash_ctx, - session->local.banner, + hok &= _libssh2_sha_algo_ctx_update(sha_algo_value, + exchange_hash_ctx, + exchange_state->h_sig_comp, 4); + hok &= _libssh2_sha_algo_ctx_update(sha_algo_value, + 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_sha_algo_ctx_update(sha_algo_value, exchange_hash_ctx, - exchange_state->h_sig_comp, 4); - _libssh2_sha_algo_ctx_update(sha_algo_value, exchange_hash_ctx, - (unsigned char *) - LIBSSH2_SSH_DEFAULT_BANNER, + hok &= _libssh2_sha_algo_ctx_update(sha_algo_value, + exchange_hash_ctx, + exchange_state->h_sig_comp, 4); + hok &= _libssh2_sha_algo_ctx_update(sha_algo_value, + exchange_hash_ctx, + (unsigned char *)LIBSSH2_SSH_DEFAULT_BANNER, sizeof(LIBSSH2_SSH_DEFAULT_BANNER) - 1); } _libssh2_htonu32(exchange_state->h_sig_comp, (uint32_t)strlen((char *) session->remote.banner)); - _libssh2_sha_algo_ctx_update(sha_algo_value, exchange_hash_ctx, - exchange_state->h_sig_comp, 4); - _libssh2_sha_algo_ctx_update(sha_algo_value, exchange_hash_ctx, - session->remote.banner, - strlen((char *) session->remote.banner)); + hok &= _libssh2_sha_algo_ctx_update(sha_algo_value, exchange_hash_ctx, + exchange_state->h_sig_comp, 4); + hok &= _libssh2_sha_algo_ctx_update(sha_algo_value, exchange_hash_ctx, + session->remote.banner, + strlen((char *)session->remote.banner)); _libssh2_htonu32(exchange_state->h_sig_comp, (uint32_t)session->local.kexinit_len); - _libssh2_sha_algo_ctx_update(sha_algo_value, exchange_hash_ctx, - exchange_state->h_sig_comp, 4); - _libssh2_sha_algo_ctx_update(sha_algo_value, exchange_hash_ctx, - session->local.kexinit, - session->local.kexinit_len); + hok &= _libssh2_sha_algo_ctx_update(sha_algo_value, exchange_hash_ctx, + exchange_state->h_sig_comp, 4); + hok &= _libssh2_sha_algo_ctx_update(sha_algo_value, exchange_hash_ctx, + session->local.kexinit, + session->local.kexinit_len); _libssh2_htonu32(exchange_state->h_sig_comp, (uint32_t)session->remote.kexinit_len); - _libssh2_sha_algo_ctx_update(sha_algo_value, exchange_hash_ctx, - exchange_state->h_sig_comp, 4); - _libssh2_sha_algo_ctx_update(sha_algo_value, exchange_hash_ctx, - session->remote.kexinit, - session->remote.kexinit_len); + hok &= _libssh2_sha_algo_ctx_update(sha_algo_value, exchange_hash_ctx, + exchange_state->h_sig_comp, 4); + hok &= _libssh2_sha_algo_ctx_update(sha_algo_value, exchange_hash_ctx, + session->remote.kexinit, + session->remote.kexinit_len); _libssh2_htonu32(exchange_state->h_sig_comp, session->server_hostkey_len); - _libssh2_sha_algo_ctx_update(sha_algo_value, exchange_hash_ctx, - exchange_state->h_sig_comp, 4); - _libssh2_sha_algo_ctx_update(sha_algo_value, exchange_hash_ctx, - session->server_hostkey, - session->server_hostkey_len); + hok &= _libssh2_sha_algo_ctx_update(sha_algo_value, exchange_hash_ctx, + exchange_state->h_sig_comp, 4); + hok &= _libssh2_sha_algo_ctx_update(sha_algo_value, 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 */ @@ -594,33 +627,41 @@ static int diffie_hellman_sha_algo(LIBSSH2_SESSION *session, LIBSSH2_DH_GEX_OPTGROUP); _libssh2_htonu32(exchange_state->h_sig_comp + 8, LIBSSH2_DH_GEX_MAXGROUP); - _libssh2_sha_algo_ctx_update(sha_algo_value, exchange_hash_ctx, - exchange_state->h_sig_comp, 12); + hok &= _libssh2_sha_algo_ctx_update(sha_algo_value, + exchange_hash_ctx, + exchange_state->h_sig_comp, + 12); } if(midhash) { - _libssh2_sha_algo_ctx_update(sha_algo_value, exchange_hash_ctx, - midhash, midhash_len); + hok &= _libssh2_sha_algo_ctx_update(sha_algo_value, + exchange_hash_ctx, + midhash, midhash_len); } - _libssh2_sha_algo_ctx_update(sha_algo_value, exchange_hash_ctx, - exchange_state->e_packet + 1, - exchange_state->e_packet_len - 1); + hok &= _libssh2_sha_algo_ctx_update(sha_algo_value, exchange_hash_ctx, + exchange_state->e_packet + 1, + exchange_state->e_packet_len - 1); _libssh2_htonu32(exchange_state->h_sig_comp, (uint32_t)exchange_state->f_value_len); - _libssh2_sha_algo_ctx_update(sha_algo_value, exchange_hash_ctx, - exchange_state->h_sig_comp, 4); - _libssh2_sha_algo_ctx_update(sha_algo_value, exchange_hash_ctx, - exchange_state->f_value, - exchange_state->f_value_len); - - _libssh2_sha_algo_ctx_update(sha_algo_value, exchange_hash_ctx, - exchange_state->k_value, - exchange_state->k_value_len); - - _libssh2_sha_algo_ctx_final(sha_algo_value, exchange_hash_ctx, - exchange_state->h_sig_comp); + hok &= _libssh2_sha_algo_ctx_update(sha_algo_value, exchange_hash_ctx, + exchange_state->h_sig_comp, 4); + hok &= _libssh2_sha_algo_ctx_update(sha_algo_value, exchange_hash_ctx, + exchange_state->f_value, + exchange_state->f_value_len); + + hok &= _libssh2_sha_algo_ctx_update(sha_algo_value, exchange_hash_ctx, + exchange_state->k_value, + exchange_state->k_value_len); + + if(!hok || + !_libssh2_sha_algo_ctx_final(sha_algo_value, exchange_hash_ctx, + exchange_state->h_sig_comp)) { + ret = _libssh2_error(session, LIBSSH2_ERROR_HASH_CALC, + "kex: failed to calculate hash"); + goto clean_exit; + } err = session->hostkey->sig_verify(session, exchange_state->h_sig, @@ -1568,6 +1609,7 @@ dh_gex_clean_exit: return ret; } +#if LIBSSH2_ECDSA /* LIBSSH2_KEX_METHOD_EC_SHA_HASH_CREATE_VERIFY * @@ -1585,101 +1627,104 @@ dh_gex_clean_exit: * mpint K, shared secret * */ - #define LIBSSH2_KEX_METHOD_EC_SHA_HASH_CREATE_VERIFY(digest_type) \ do { \ libssh2_sha##digest_type##_ctx ctx; \ + int hok; \ + if(!libssh2_sha##digest_type##_init(&ctx)) { \ + rc = -1; \ + break; \ + } \ exchange_state->exchange_hash = (void *)&ctx; \ - (void)libssh2_sha##digest_type##_init(&ctx); \ + hok = 1; \ if(session->local.banner) { \ _libssh2_htonu32(exchange_state->h_sig_comp, \ (uint32_t)(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); \ + hok &= libssh2_sha##digest_type##_update(ctx, \ + exchange_state->h_sig_comp, \ + 4); \ + hok &= 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, \ + hok &= libssh2_sha##digest_type##_update(ctx, \ exchange_state->h_sig_comp, 4); \ - libssh2_sha##digest_type##_update(ctx, \ - LIBSSH2_SSH_DEFAULT_BANNER, \ + hok &= libssh2_sha##digest_type##_update(ctx, \ + LIBSSH2_SSH_DEFAULT_BANNER, \ sizeof(LIBSSH2_SSH_DEFAULT_BANNER) \ - 1); \ } \ \ _libssh2_htonu32(exchange_state->h_sig_comp, \ (uint32_t)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)); \ + hok &= libssh2_sha##digest_type##_update(ctx, \ + exchange_state->h_sig_comp, 4); \ + hok &= libssh2_sha##digest_type##_update(ctx, session->remote.banner, \ + strlen((char *)session->remote.banner)); \ \ _libssh2_htonu32(exchange_state->h_sig_comp, \ (uint32_t)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); \ + hok &= libssh2_sha##digest_type##_update(ctx, \ + exchange_state->h_sig_comp, 4); \ + hok &= libssh2_sha##digest_type##_update(ctx, \ + session->local.kexinit, \ + session->local.kexinit_len); \ \ _libssh2_htonu32(exchange_state->h_sig_comp, \ (uint32_t)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); \ + hok &= libssh2_sha##digest_type##_update(ctx, \ + exchange_state->h_sig_comp, 4); \ + hok &= 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); \ + hok &= libssh2_sha##digest_type##_update(ctx, \ + exchange_state->h_sig_comp, 4); \ + hok &= libssh2_sha##digest_type##_update(ctx, \ + session->server_hostkey, \ + session->server_hostkey_len); \ \ _libssh2_htonu32(exchange_state->h_sig_comp, \ (uint32_t)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); \ + hok &= libssh2_sha##digest_type##_update(ctx, \ + exchange_state->h_sig_comp, 4); \ + hok &= libssh2_sha##digest_type##_update(ctx, \ + public_key, \ + public_key_len); \ \ _libssh2_htonu32(exchange_state->h_sig_comp, \ (uint32_t)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); \ + hok &= libssh2_sha##digest_type##_update(ctx, \ + exchange_state->h_sig_comp, 4); \ + hok &= 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); \ + hok &= 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(!hok || \ + !libssh2_sha##digest_type##_final(ctx, exchange_state->h_sig_comp)) { \ + rc = -1; \ + break; \ + } \ \ 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)) { \ + 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; \ } \ } while(0) - -#if LIBSSH2_ECDSA - /* kex_session_ecdh_curve_type * returns the EC curve type by name used in key exchange */ @@ -1764,11 +1809,11 @@ static int ecdh_sha2_nistp(LIBSSH2_SESSION *session, libssh2_curve_type type, { 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); + 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 { @@ -1792,11 +1837,11 @@ static int ecdh_sha2_nistp(LIBSSH2_SESSION *session, libssh2_curve_type type, { 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); + 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 { @@ -1820,11 +1865,11 @@ static int ecdh_sha2_nistp(LIBSSH2_SESSION *session, libssh2_curve_type type, { 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); + 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 { @@ -1909,7 +1954,6 @@ static int ecdh_sha2_nistp(LIBSSH2_SESSION *session, libssh2_curve_type 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; @@ -2396,11 +2440,11 @@ curve25519_sha256(LIBSSH2_SESSION *session, unsigned char *data, { 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); + 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 { @@ -2424,11 +2468,11 @@ curve25519_sha256(LIBSSH2_SESSION *session, unsigned char *data, { 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); + 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 { @@ -2452,11 +2496,11 @@ curve25519_sha256(LIBSSH2_SESSION *session, unsigned char *data, { 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); + 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 { @@ -3033,6 +3077,13 @@ kex_method_extension_negotiation = { 0, }; +static const LIBSSH2_KEX_METHOD +kex_method_strict_client_extension = { + "kex-strict-c-v00@openssh.com", + NULL, + 0, +}; + static const LIBSSH2_KEX_METHOD *libssh2_kex_methods[] = { #if LIBSSH2_ED25519 &kex_method_ssh_curve25519_sha256, @@ -3051,6 +3102,7 @@ static const LIBSSH2_KEX_METHOD *libssh2_kex_methods[] = { &kex_method_diffie_helman_group1_sha1, &kex_method_diffie_helman_group_exchange_sha1, &kex_method_extension_negotiation, + &kex_method_strict_client_extension, NULL }; @@ -3303,13 +3355,13 @@ static int kexinit(LIBSSH2_SESSION * session) return 0; } -/* kex_agree_instr +/* _libssh2_kex_agree_instr * Kex specific variant of strstr() * Needle must be preceded by BOL or ',', and followed by ',' or EOL */ -static unsigned char * -kex_agree_instr(unsigned char *haystack, size_t haystack_len, - const unsigned char *needle, size_t needle_len) +unsigned char * +_libssh2_kex_agree_instr(unsigned char *haystack, size_t haystack_len, + const unsigned char *needle, size_t needle_len) { unsigned char *s; unsigned char *end_haystack; @@ -3342,6 +3394,7 @@ kex_agree_instr(unsigned char *haystack, size_t haystack_len, left = end_haystack - s; if((left >= 1) && (left <= haystack_len) && (left > needle_len)) { s++; + left--; } else { return NULL; @@ -3394,7 +3447,7 @@ static int kex_agree_hostkey(LIBSSH2_SESSION * session, 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)) { + if(_libssh2_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, @@ -3428,9 +3481,9 @@ static int kex_agree_hostkey(LIBSSH2_SESSION * session, } while(hostkeyp && (*hostkeyp) && (*hostkeyp)->name) { - s = kex_agree_instr(hostkey, hostkey_len, - (unsigned char *) (*hostkeyp)->name, - strlen((*hostkeyp)->name)); + s = _libssh2_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) */ @@ -3464,6 +3517,12 @@ static int kex_agree_kex_hostkey(LIBSSH2_SESSION * session, unsigned char *kex, { const LIBSSH2_KEX_METHOD **kexp = libssh2_kex_methods; unsigned char *s; + const unsigned char *strict = + (unsigned char *)"kex-strict-s-v00@openssh.com"; + + if(_libssh2_kex_agree_instr(kex, kex_len, strict, 28)) { + session->kex_strict = 1; + } if(session->kex_prefs) { s = (unsigned char *) session->kex_prefs; @@ -3471,7 +3530,7 @@ static int kex_agree_kex_hostkey(LIBSSH2_SESSION * session, unsigned char *kex, 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); + q = _libssh2_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, @@ -3505,9 +3564,9 @@ static int kex_agree_kex_hostkey(LIBSSH2_SESSION * session, unsigned char *kex, } while(*kexp && (*kexp)->name) { - s = kex_agree_instr(kex, kex_len, - (unsigned char *) (*kexp)->name, - strlen((*kexp)->name)); + s = _libssh2_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? @@ -3551,7 +3610,7 @@ static int kex_agree_crypt(LIBSSH2_SESSION * session, 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)) { + if(_libssh2_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, @@ -3573,9 +3632,9 @@ static int kex_agree_crypt(LIBSSH2_SESSION * session, } while(*cryptp && (*cryptp)->name) { - s = kex_agree_instr(crypt, crypt_len, - (unsigned char *) (*cryptp)->name, - strlen((*cryptp)->name)); + s = _libssh2_kex_agree_instr(crypt, crypt_len, + (unsigned char *) (*cryptp)->name, + strlen((*cryptp)->name)); if(s) { endpoint->crypt = *cryptp; return 0; @@ -3615,7 +3674,7 @@ static int kex_agree_mac(LIBSSH2_SESSION * session, 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)) { + if(_libssh2_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 **) @@ -3636,8 +3695,9 @@ static int kex_agree_mac(LIBSSH2_SESSION * session, } while(*macp && (*macp)->name) { - s = kex_agree_instr(mac, mac_len, (unsigned char *) (*macp)->name, - strlen((*macp)->name)); + s = _libssh2_kex_agree_instr(mac, mac_len, + (unsigned char *) (*macp)->name, + strlen((*macp)->name)); if(s) { endpoint->mac = *macp; return 0; @@ -3668,7 +3728,7 @@ static int kex_agree_comp(LIBSSH2_SESSION *session, 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)) { + if(_libssh2_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, @@ -3690,8 +3750,9 @@ static int kex_agree_comp(LIBSSH2_SESSION *session, } while(*compp && (*compp)->name) { - s = kex_agree_instr(comp, comp_len, (unsigned char *) (*compp)->name, - strlen((*compp)->name)); + s = _libssh2_kex_agree_instr(comp, comp_len, + (unsigned char *) (*compp)->name, + strlen((*compp)->name)); if(s) { endpoint->comp = *compp; return 0; @@ -3872,6 +3933,7 @@ _libssh2_kex_exchange(LIBSSH2_SESSION * session, int reexchange, 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_INITIAL_KEX; session->state &= ~LIBSSH2_STATE_KEX_ACTIVE; session->state &= ~LIBSSH2_STATE_EXCHANGING_KEYS; return -1; @@ -3897,6 +3959,7 @@ _libssh2_kex_exchange(LIBSSH2_SESSION * session, int reexchange, 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_INITIAL_KEX; session->state &= ~LIBSSH2_STATE_KEX_ACTIVE; session->state &= ~LIBSSH2_STATE_EXCHANGING_KEYS; return -1; @@ -3945,6 +4008,7 @@ _libssh2_kex_exchange(LIBSSH2_SESSION * session, int reexchange, session->remote.kexinit = NULL; } + session->state &= ~LIBSSH2_STATE_INITIAL_KEX; session->state &= ~LIBSSH2_STATE_KEX_ACTIVE; session->state &= ~LIBSSH2_STATE_EXCHANGING_KEYS; diff --git a/libs/libssh2/src/knownhost.c b/libs/libssh2/src/knownhost.c index 1caab14789..5eba6a108c 100644 --- a/libs/libssh2/src/knownhost.c +++ b/libs/libssh2/src/knownhost.c @@ -421,19 +421,23 @@ knownhost_check(LIBSSH2_KNOWNHOSTS *hosts, */ unsigned char hash[SHA_DIGEST_LENGTH]; libssh2_hmac_ctx ctx; - libssh2_hmac_ctx_init(ctx); + if(!_libssh2_hmac_ctx_init(&ctx)) + break; 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(!_libssh2_hmac_sha1_init(&ctx, + node->salt, node->salt_len)) + break; + if(!_libssh2_hmac_update(&ctx, host, strlen(host)) || + !_libssh2_hmac_final(&ctx, hash)) { + _libssh2_hmac_cleanup(&ctx); + break; + } + _libssh2_hmac_cleanup(&ctx); if(!memcmp(hash, node->name, SHA_DIGEST_LENGTH)) /* this is a node we're interested in */ @@ -1049,7 +1053,7 @@ knownhost_writeline(LIBSSH2_KNOWNHOSTS *hosts, break; } /* otherwise fallback to default and error */ - /* FALL-THROUGH */ + LIBSSH2_FALLTHROUGH(); default: return _libssh2_error(hosts->session, LIBSSH2_ERROR_METHOD_NOT_SUPPORTED, diff --git a/libs/libssh2/src/libgcrypt.c b/libs/libssh2/src/libgcrypt.c index e463d9e347..b92ec7c97d 100644 --- a/libs/libssh2/src/libgcrypt.c +++ b/libs/libssh2/src/libgcrypt.c @@ -40,6 +40,105 @@ #ifdef LIBSSH2_CRYPTO_C /* Compile this via crypto.c */ +int _libssh2_hmac_ctx_init(libssh2_hmac_ctx *ctx) +{ + *ctx = NULL; + return 1; +} + +#if LIBSSH2_MD5 +int _libssh2_hmac_md5_init(libssh2_hmac_ctx *ctx, + void *key, size_t keylen) +{ + gcry_error_t err; + err = gcry_md_open(ctx, GCRY_MD_MD5, GCRY_MD_FLAG_HMAC); + if(gcry_err_code(err) != GPG_ERR_NO_ERROR) + return 0; + err = gcry_md_setkey(*ctx, key, keylen); + if(gcry_err_code(err) != GPG_ERR_NO_ERROR) + return 0; + return 1; +} +#endif + +#if LIBSSH2_HMAC_RIPEMD +int _libssh2_hmac_ripemd160_init(libssh2_hmac_ctx *ctx, + void *key, size_t keylen) +{ + gcry_error_t err; + err = gcry_md_open(ctx, GCRY_MD_RMD160, GCRY_MD_FLAG_HMAC); + if(gcry_err_code(err) != GPG_ERR_NO_ERROR) + return 0; + err = gcry_md_setkey(*ctx, key, keylen); + if(gcry_err_code(err) != GPG_ERR_NO_ERROR) + return 0; + return 1; +} +#endif + +int _libssh2_hmac_sha1_init(libssh2_hmac_ctx *ctx, + void *key, size_t keylen) +{ + gcry_error_t err; + err = gcry_md_open(ctx, GCRY_MD_SHA1, GCRY_MD_FLAG_HMAC); + if(gcry_err_code(err) != GPG_ERR_NO_ERROR) + return 0; + err = gcry_md_setkey(*ctx, key, keylen); + if(gcry_err_code(err) != GPG_ERR_NO_ERROR) + return 0; + return 1; +} + +int _libssh2_hmac_sha256_init(libssh2_hmac_ctx *ctx, + void *key, size_t keylen) +{ + gcry_error_t err; + err = gcry_md_open(ctx, GCRY_MD_SHA256, GCRY_MD_FLAG_HMAC); + if(gcry_err_code(err) != GPG_ERR_NO_ERROR) + return 0; + err = gcry_md_setkey(*ctx, key, keylen); + if(gcry_err_code(err) != GPG_ERR_NO_ERROR) + return 0; + return 1; +} + +int _libssh2_hmac_sha512_init(libssh2_hmac_ctx *ctx, + void *key, size_t keylen) +{ + gcry_error_t err; + err = gcry_md_open(ctx, GCRY_MD_SHA512, GCRY_MD_FLAG_HMAC); + if(gcry_err_code(err) != GPG_ERR_NO_ERROR) + return 0; + err = gcry_md_setkey(*ctx, key, keylen); + if(gcry_err_code(err) != GPG_ERR_NO_ERROR) + return 0; + return 1; +} + +int _libssh2_hmac_update(libssh2_hmac_ctx *ctx, + const void *data, size_t datalen) +{ + gcry_md_write(*ctx, data, datalen); + return 1; +} + +int _libssh2_hmac_final(libssh2_hmac_ctx *ctx, void *data) +{ + unsigned char *res = gcry_md_read(*ctx, 0); + + if(!res) + return 0; + + memcpy(data, res, gcry_md_get_algo_dlen(gcry_md_get_algo(*ctx))); + + return 1; +} + +void _libssh2_hmac_cleanup(libssh2_hmac_ctx *ctx) +{ + gcry_md_close(*ctx); +} + #if LIBSSH2_RSA int _libssh2_rsa_new(libssh2_rsa_ctx ** rsa, @@ -95,7 +194,9 @@ _libssh2_rsa_sha1_verify(libssh2_rsa_ctx * rsa, gcry_sexp_t s_sig, s_hash; int rc = -1; - libssh2_sha1(m, m_len, hash); + if(libssh2_sha1(m, m_len, hash)) { + return -1; + } rc = gcry_sexp_build(&s_hash, NULL, "(data (flags pkcs1) (hash sha1 %b))", @@ -544,7 +645,9 @@ _libssh2_dsa_sha1_verify(libssh2_dsa_ctx * dsactx, gcry_sexp_t s_sig, s_hash; int rc = -1; - libssh2_sha1(m, m_len, hash + 1); + if(libssh2_sha1(m, m_len, hash + 1)) { + return -1; + } hash[0] = 0; if(gcry_sexp_build(&s_hash, NULL, "(data(flags raw)(value %b))", diff --git a/libs/libssh2/src/libgcrypt.h b/libs/libssh2/src/libgcrypt.h index 77a1b8aba3..7fc8148720 100644 --- a/libs/libssh2/src/libgcrypt.h +++ b/libs/libssh2/src/libgcrypt.h @@ -1,5 +1,5 @@ -#ifndef __LIBSSH2_LIBGCRYPT_H -#define __LIBSSH2_LIBGCRYPT_H +#ifndef LIBSSH2_LIBGCRYPT_H +#define LIBSSH2_LIBGCRYPT_H /* * Copyright (C) Simon Josefsson * Copyright (C) The Written Word, Inc. @@ -53,7 +53,7 @@ #define LIBSSH2_AES_CBC 1 #define LIBSSH2_AES_CTR 1 -#define LIBSSH2_AES_GCM 1 +#define LIBSSH2_AES_GCM 0 #define LIBSSH2_BLOWFISH 1 #define LIBSSH2_RC4 1 #define LIBSSH2_CAST 1 @@ -61,12 +61,16 @@ #define LIBSSH2_RSA 1 #define LIBSSH2_RSA_SHA1 1 -#define LIBSSH2_RSA_SHA2 1 +#define LIBSSH2_RSA_SHA2 0 #define LIBSSH2_DSA 1 -#define LIBSSH2_ECDSA 1 -#define LIBSSH2_ED25519 1 +#define LIBSSH2_ECDSA 0 +#define LIBSSH2_ED25519 0 +#include "crypto_config.h" + +#if LIBSSH2_MD5 || LIBSSH2_MD5_PEM #define MD5_DIGEST_LENGTH 16 +#endif #define SHA_DIGEST_LENGTH 20 #define SHA256_DIGEST_LENGTH 32 #define SHA384_DIGEST_LENGTH 48 @@ -80,86 +84,62 @@ #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) + (gcry_md_write(ctx, (unsigned char *) data, len), 1) #define libssh2_sha1_final(ctx, out) \ - memcpy(out, gcry_md_read(ctx, 0), SHA_DIGEST_LENGTH), gcry_md_close(ctx) + (memcpy(out, gcry_md_read(ctx, 0), SHA_DIGEST_LENGTH), \ + gcry_md_close(ctx), 1) #define libssh2_sha1(message, len, out) \ - gcry_md_hash_buffer(GCRY_MD_SHA1, out, message, len) + (gcry_md_hash_buffer(GCRY_MD_SHA1, out, message, len), 0) #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) + (gcry_md_write(ctx, (unsigned char *) data, len), 1) #define libssh2_sha256_final(ctx, out) \ - memcpy(out, gcry_md_read(ctx, 0), SHA256_DIGEST_LENGTH), gcry_md_close(ctx) + (memcpy(out, gcry_md_read(ctx, 0), SHA256_DIGEST_LENGTH), \ + gcry_md_close(ctx), 1) #define libssh2_sha256(message, len, out) \ - gcry_md_hash_buffer(GCRY_MD_SHA256, out, message, len) + (gcry_md_hash_buffer(GCRY_MD_SHA256, out, message, len), 0) #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) + (gcry_md_write(ctx, (unsigned char *) data, len), 1) #define libssh2_sha384_final(ctx, out) \ - memcpy(out, gcry_md_read(ctx, 0), SHA384_DIGEST_LENGTH), gcry_md_close(ctx) + (memcpy(out, gcry_md_read(ctx, 0), SHA384_DIGEST_LENGTH), \ + gcry_md_close(ctx), 1) #define libssh2_sha384(message, len, out) \ - gcry_md_hash_buffer(GCRY_MD_SHA384, out, message, len) + (gcry_md_hash_buffer(GCRY_MD_SHA384, out, message, len), 0) #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) + (gcry_md_write(ctx, (unsigned char *) data, len), 1) #define libssh2_sha512_final(ctx, out) \ - memcpy(out, gcry_md_read(ctx, 0), SHA512_DIGEST_LENGTH), gcry_md_close(ctx) + (memcpy(out, gcry_md_read(ctx, 0), SHA512_DIGEST_LENGTH), \ + gcry_md_close(ctx), 1) #define libssh2_sha512(message, len, out) \ - gcry_md_hash_buffer(GCRY_MD_SHA512, out, message, len) + (gcry_md_hash_buffer(GCRY_MD_SHA512, out, message, len), 0) +#if LIBSSH2_MD5 || LIBSSH2_MD5_PEM #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) + (gcry_md_write(ctx, (unsigned char *) data, len), 1) #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) + (memcpy(out, gcry_md_read(ctx, 0), MD5_DIGEST_LENGTH), \ + gcry_md_close(ctx), 1) +#endif #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() @@ -250,4 +230,4 @@ 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); -#endif /* __LIBSSH2_LIBGCRYPT_H */ +#endif /* LIBSSH2_LIBGCRYPT_H */ diff --git a/libs/libssh2/src/libssh2.rc b/libs/libssh2/src/libssh2.rc index 4862d78eef..3021d8e69c 100644 --- a/libs/libssh2/src/libssh2.rc +++ b/libs/libssh2/src/libssh2.rc @@ -1,7 +1,7 @@ /*************************************************************************** * libssh2 Windows resource file * Copyright (C) The libssh2 project and its contributors. -* +* * SPDX-License-Identifier: BSD-3-Clause ***************************************************************************/ #include <winver.h> @@ -29,7 +29,7 @@ BEGIN BEGIN BLOCK "040904b0" /* 0x0409: en-US, 1200/0x04b0: UTF-16LE */ BEGIN - VALUE "CompanyName", "The libssh2 library, https://www.libssh2.org/\0" + VALUE "CompanyName", "The libssh2 library, https://libssh2.org/\0" VALUE "FileDescription", "libssh2 Shared Library\0" VALUE "FileVersion", LIBSSH2_VERSION "\0" VALUE "InternalName", "libssh2\0" @@ -37,7 +37,7 @@ BEGIN VALUE "ProductName", "The libssh2 library\0" VALUE "ProductVersion", LIBSSH2_VERSION "\0" VALUE "LegalCopyright", "Copyright (C) " LIBSSH2_COPYRIGHT "\0" - VALUE "License", "https://www.libssh2.org/license.html\0" + VALUE "License", "https://libssh2.org/license.html\0" END END diff --git a/libs/libssh2/src/libssh2_priv.h b/libs/libssh2/src/libssh2_priv.h index 96af134279..18d9ab2130 100644 --- a/libs/libssh2/src/libssh2_priv.h +++ b/libs/libssh2/src/libssh2_priv.h @@ -1,5 +1,5 @@ -#ifndef __LIBSSH2_PRIV_H -#define __LIBSSH2_PRIV_H +#ifndef LIBSSH2_PRIV_H +#define LIBSSH2_PRIV_H /* Copyright (C) Sara Golemon <sarag@libssh2.org> * Copyright (C) Daniel Stenberg * Copyright (C) Simon Josefsson @@ -41,7 +41,14 @@ * SPDX-License-Identifier: BSD-3-Clause */ -/* Header used by 'src' */ +/* Header used by 'src' and 'tests' */ + +/* FIXME: Disable warnings for 'src' */ +#if !defined(LIBSSH2_TESTS) && !defined(LIBSSH2_WARN_SIGN_CONVERSION) +#ifdef __GNUC__ +#pragma GCC diagnostic ignored "-Wsign-conversion" +#endif +#endif #define LIBSSH2_LIBRARY @@ -86,6 +93,19 @@ #include "libssh2_sftp.h" #include "misc.h" +#ifdef _WIN32 +/* Detect Windows App environment which has a restricted access + to the Win32 APIs. */ +# if (defined(_WIN32_WINNT) && (_WIN32_WINNT >= 0x0602)) || \ + defined(WINAPI_FAMILY) +# include <winapifamily.h> +# if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP) && \ + !WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) +# define LIBSSH2_WINDOWS_UWP +# endif +# endif +#endif + #ifndef FALSE #define FALSE 0 #endif @@ -93,12 +113,28 @@ #define TRUE 1 #endif +#if (defined(__GNUC__) || defined(__clang__)) && \ + defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) && \ + !defined(LIBSSH2_NO_FMT_CHECKS) +#ifdef __MINGW_PRINTF_FORMAT +#define LIBSSH2_PRINTF(fmt, arg) \ + __attribute__((format(__MINGW_PRINTF_FORMAT, fmt, arg))) +#elif !defined(__MINGW32__) +#define LIBSSH2_PRINTF(fmt, arg) \ + __attribute__((format(printf, fmt, arg))) +#endif +#endif +#ifndef LIBSSH2_PRINTF +#define LIBSSH2_PRINTF(fmt, arg) +#endif + /* Use local implementation when not available */ #if !defined(HAVE_SNPRINTF) #undef snprintf #define snprintf _libssh2_snprintf #define LIBSSH2_SNPRINTF -int _libssh2_snprintf(char *cp, size_t cp_max_len, const char *fmt, ...); +int _libssh2_snprintf(char *cp, size_t cp_max_len, const char *fmt, ...) + LIBSSH2_PRINTF(3, 4); #endif #if !defined(HAVE_GETTIMEOFDAY) @@ -111,6 +147,15 @@ int _libssh2_gettimeofday(struct timeval *tp, void *tzp); #include <sys/time.h> #endif +#if !defined(LIBSSH2_FALLTHROUGH) +#if (defined(__GNUC__) && __GNUC__ >= 7) || \ + (defined(__clang__) && __clang_major__ >= 10) +# define LIBSSH2_FALLTHROUGH() __attribute__((fallthrough)) +#else +# define LIBSSH2_FALLTHROUGH() do {} while (0) +#endif +#endif + /* "inline" keyword is valid only with C++ engine! */ #ifdef __GNUC__ #undef inline @@ -121,7 +166,7 @@ int _libssh2_gettimeofday(struct timeval *tp, void *tzp); #endif /* 3DS doesn't seem to have iovec */ -#if defined(WIN32) || defined(_3DS) +#if defined(_WIN32) || defined(_3DS) struct iovec { size_t iov_len; @@ -152,6 +197,9 @@ struct iovec { #define LIBSSH2_MAX(x, y) ((x) > (y) ? (x) : (y)) #define LIBSSH2_MIN(x, y) ((x) < (y) ? (x) : (y)) +#define MAX_BLOCKSIZE 32 /* MUST fit biggest crypto block size we use/get */ +#define MAX_MACSIZE 64 /* MUST fit biggest MAC length we support */ + /* RFC4253 section 6.1 Maximum Packet Length says: * * "All implementations MUST be able to process packets with @@ -402,7 +450,7 @@ struct _LIBSSH2_CHANNEL struct list_node node; unsigned char *channel_type; - unsigned channel_type_len; + size_t channel_type_len; /* channel's program exit status */ int exit_status; @@ -455,7 +503,7 @@ struct _LIBSSH2_CHANNEL size_t flush_refund_bytes; size_t flush_flush_bytes; - /* State variables used in libssh2_channel_receive_window_adjust() */ + /* State variables used in libssh2_channel_receive_window_adjust2() */ libssh2_nonblocking_states adjust_state; unsigned char adjust_adjust[9]; /* packet_type(1) + channel(4) + adjustment(4) */ @@ -688,6 +736,9 @@ struct _LIBSSH2_SESSION /* key signing algorithm preferences -- NULL yields server order */ char *sign_algo_prefs; + /* Whether to use the OpenSSH Strict KEX extension */ + int kex_strict; + /* (remote as source of data -- packet_read ) */ libssh2_endpoint_data remote; @@ -710,7 +761,8 @@ struct _LIBSSH2_SESSION int socket_state; int socket_block_directions; int socket_prev_blockstate; /* stores the state of the socket blockiness - when libssh2_session_startup() is called */ + when libssh2_session_handshake() + is called */ /* Error tracking */ const char *err_msg; @@ -736,7 +788,7 @@ struct _LIBSSH2_SESSION unsigned char *kexinit_data; size_t kexinit_data_len; - /* State variables used in libssh2_session_startup() */ + /* State variables used in libssh2_session_handshake() */ libssh2_nonblocking_states startup_state; unsigned char *startup_data; size_t startup_data_len; @@ -859,6 +911,7 @@ struct _LIBSSH2_SESSION int fullpacket_macstate; size_t fullpacket_payload_len; int fullpacket_packet_type; + uint32_t fullpacket_required_type; /* State variables used in libssh2_sftp_init() */ libssh2_nonblocking_states sftpInit_state; @@ -869,7 +922,7 @@ struct _LIBSSH2_SESSION size_t sftpInit_sent; /* number of bytes from the buffer that have been sent */ - /* State variables used in libssh2_scp_recv() / libssh_scp_recv2() */ + /* State variables used in libssh2_scp_recv2() */ libssh2_nonblocking_states scpRecv_state; unsigned char *scpRecv_command; size_t scpRecv_command_len; @@ -899,10 +952,11 @@ struct _LIBSSH2_SESSION }; /* 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 +#define LIBSSH2_STATE_INITIAL_KEX 0x00000001 +#define LIBSSH2_STATE_EXCHANGING_KEYS 0x00000002 +#define LIBSSH2_STATE_NEWKEYS 0x00000004 +#define LIBSSH2_STATE_AUTHENTICATED 0x00000008 +#define LIBSSH2_STATE_KEX_ACTIVE 0x00000010 /* session.flag helpers */ #ifdef MSG_NOSIGNAL @@ -1032,7 +1086,7 @@ struct _LIBSSH2_COMP_METHOD #ifdef LIBSSH2DEBUG void _libssh2_debug_low(LIBSSH2_SESSION * session, int context, const char *format, - ...); + ...) LIBSSH2_PRINTF(3, 4); #define _libssh2_debug(x) _libssh2_debug_low x #else #define _libssh2_debug(x) do {} while(0) @@ -1133,6 +1187,11 @@ ssize_t _libssh2_send(libssh2_socket_t socket, const void *buffer, int _libssh2_kex_exchange(LIBSSH2_SESSION * session, int reexchange, key_exchange_state_t * state); +unsigned char *_libssh2_kex_agree_instr(unsigned char *haystack, + size_t haystack_len, + const unsigned char *needle, + size_t needle_len); + /* 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); @@ -1182,6 +1241,8 @@ size_t plain_method(char *method, size_t method_len); /* define to output the libssh2_int64_t type in a *printf() */ #if defined(__BORLANDC__) || defined(_MSC_VER) #define LIBSSH2_INT64_T_FORMAT "I64d" +#elif defined(__MINGW32__) +#define LIBSSH2_INT64_T_FORMAT PRId64 #else #define LIBSSH2_INT64_T_FORMAT "lld" #endif @@ -1189,12 +1250,12 @@ size_t plain_method(char *method, size_t method_len); /* 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) +#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. +/* 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 @@ -1209,4 +1270,4 @@ size_t plain_method(char *method, size_t method_len); #define FOPEN_APPENDTEXT "a" #endif -#endif /* __LIBSSH2_PRIV_H */ +#endif /* LIBSSH2_PRIV_H */ diff --git a/libs/libssh2/src/libssh2_setup.h b/libs/libssh2/src/libssh2_setup.h index 8e56a06042..7e084f993a 100644 --- a/libs/libssh2/src/libssh2_setup.h +++ b/libs/libssh2/src/libssh2_setup.h @@ -9,10 +9,6 @@ /* Header for platform/compiler-specific initialization. Used by 'src', 'example', 'tests' */ -#if defined(_WIN32) && !defined(WIN32) -#define WIN32 -#endif - /* Define mingw-w64 version macros, eg __MINGW{32,64}_{MINOR,MAJOR}_VERSION */ #ifdef __MINGW32__ #include <_mingw.h> @@ -26,7 +22,7 @@ /* Hand-crafted configuration for platforms which lack config tool. Keep this synced with root CMakeLists.txt */ -#elif defined(WIN32) +#elif defined(_WIN32) #define HAVE_SELECT #define HAVE_SNPRINTF @@ -54,7 +50,7 @@ /* Below applies to both auto-detected and hand-crafted configs */ -#ifdef WIN32 +#ifdef _WIN32 #ifndef WIN32_LEAN_AND_MEAN #define WIN32_LEAN_AND_MEAN @@ -103,6 +99,6 @@ # endif #endif -#endif /* WIN32 */ +#endif /* _WIN32 */ #endif /* LIBSSH2_SETUP_H */ diff --git a/libs/libssh2/src/mac.c b/libs/libssh2/src/mac.c index db6f57a44e..03ecd329ee 100644 --- a/libs/libssh2/src/mac.c +++ b/libs/libssh2/src/mac.c @@ -124,23 +124,27 @@ mac_method_hmac_sha2_512_hash(LIBSSH2_SESSION * session, { libssh2_hmac_ctx ctx; unsigned char seqno_buf[4]; + int res; (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; + if(!_libssh2_hmac_ctx_init(&ctx)) + return 1; + res = _libssh2_hmac_sha512_init(&ctx, *abstract, 64) && + _libssh2_hmac_update(&ctx, seqno_buf, 4) && + _libssh2_hmac_update(&ctx, packet, packet_len); + if(res && addtl && addtl_len) + res = _libssh2_hmac_update(&ctx, addtl, addtl_len); + if(res) + res = _libssh2_hmac_final(&ctx, buf); + _libssh2_hmac_cleanup(&ctx); + + return !res; } + + static const LIBSSH2_MAC_METHOD mac_method_hmac_sha2_512 = { "hmac-sha2-512", 64, @@ -179,21 +183,23 @@ mac_method_hmac_sha2_256_hash(LIBSSH2_SESSION * session, { libssh2_hmac_ctx ctx; unsigned char seqno_buf[4]; + int res; (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; + if(!_libssh2_hmac_ctx_init(&ctx)) + return 1; + res = _libssh2_hmac_sha256_init(&ctx, *abstract, 32) && + _libssh2_hmac_update(&ctx, seqno_buf, 4) && + _libssh2_hmac_update(&ctx, packet, packet_len); + if(res && addtl && addtl_len) + res = _libssh2_hmac_update(&ctx, addtl, addtl_len); + if(res) + res = _libssh2_hmac_final(&ctx, buf); + _libssh2_hmac_cleanup(&ctx); + + return !res; } @@ -236,21 +242,23 @@ mac_method_hmac_sha1_hash(LIBSSH2_SESSION * session, { libssh2_hmac_ctx ctx; unsigned char seqno_buf[4]; + int res; (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; + if(!_libssh2_hmac_ctx_init(&ctx)) + return 1; + res = _libssh2_hmac_sha1_init(&ctx, *abstract, 20) && + _libssh2_hmac_update(&ctx, seqno_buf, 4) && + _libssh2_hmac_update(&ctx, packet, packet_len); + if(res && addtl && addtl_len) + res = _libssh2_hmac_update(&ctx, addtl, addtl_len); + if(res) + res = _libssh2_hmac_final(&ctx, buf); + _libssh2_hmac_cleanup(&ctx); + + return !res; } @@ -288,10 +296,11 @@ mac_method_hmac_sha1_96_hash(LIBSSH2_SESSION * session, { 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); + if(mac_method_hmac_sha1_hash(session, temp, seqno, packet, packet_len, + addtl, addtl_len, abstract)) + return 1; + memcpy(buf, (char *) temp, 96 / 8); return 0; } @@ -321,21 +330,23 @@ mac_method_hmac_md5_hash(LIBSSH2_SESSION * session, unsigned char *buf, { libssh2_hmac_ctx ctx; unsigned char seqno_buf[4]; + int res; (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; + if(!_libssh2_hmac_ctx_init(&ctx)) + return 1; + res = _libssh2_hmac_md5_init(&ctx, *abstract, 16) && + _libssh2_hmac_update(&ctx, seqno_buf, 4) && + _libssh2_hmac_update(&ctx, packet, packet_len); + if(res && addtl && addtl_len) + res = _libssh2_hmac_update(&ctx, addtl, addtl_len); + if(res) + res = _libssh2_hmac_final(&ctx, buf); + _libssh2_hmac_cleanup(&ctx); + + return !res; } @@ -362,8 +373,11 @@ mac_method_hmac_md5_96_hash(LIBSSH2_SESSION * session, size_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); + + if(mac_method_hmac_md5_hash(session, temp, seqno, packet, packet_len, + addtl, addtl_len, abstract)) + return 1; + memcpy(buf, (char *) temp, 96 / 8); return 0; } @@ -396,21 +410,23 @@ mac_method_hmac_ripemd160_hash(LIBSSH2_SESSION * session, { libssh2_hmac_ctx ctx; unsigned char seqno_buf[4]; + int res; (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; + if(!_libssh2_hmac_ctx_init(&ctx)) + return 1; + res = _libssh2_hmac_ripemd160_init(&ctx, *abstract, 20) && + _libssh2_hmac_update(&ctx, seqno_buf, 4) && + _libssh2_hmac_update(&ctx, packet, packet_len); + if(res && addtl && addtl_len) + res = _libssh2_hmac_update(&ctx, addtl, addtl_len); + if(res) + res = _libssh2_hmac_final(&ctx, buf); + _libssh2_hmac_cleanup(&ctx); + + return !res; } diff --git a/libs/libssh2/src/mac.h b/libs/libssh2/src/mac.h index 696f835aa6..8e5b8c280f 100644 --- a/libs/libssh2/src/mac.h +++ b/libs/libssh2/src/mac.h @@ -1,5 +1,5 @@ -#ifndef __LIBSSH2_MAC_H -#define __LIBSSH2_MAC_H +#ifndef LIBSSH2_MAC_H +#define LIBSSH2_MAC_H /* Copyright (C) Daniel Stenberg * All rights reserved. * @@ -69,4 +69,4 @@ const LIBSSH2_MAC_METHOD **_libssh2_mac_methods(void); const LIBSSH2_MAC_METHOD *_libssh2_mac_override( const LIBSSH2_CRYPT_METHOD *crypt); -#endif /* __LIBSSH2_MAC_H */ +#endif /* LIBSSH2_MAC_H */ diff --git a/libs/libssh2/src/misc.c b/libs/libssh2/src/misc.c index b386e3d667..0dee48f5f5 100644 --- a/libs/libssh2/src/misc.c +++ b/libs/libssh2/src/misc.c @@ -40,7 +40,6 @@ */ #include "libssh2_priv.h" -#include "misc.h" #ifdef HAVE_UNISTD_H #include <unistd.h> @@ -49,7 +48,7 @@ #include <errno.h> #include <assert.h> -#ifdef WIN32 +#ifdef _WIN32 /* Force parameter type. */ #define recv(s, b, l, f) recv((s), (b), (int)(l), (f)) #define send(s, b, l, f) send((s), (b), (int)(l), (f)) @@ -73,7 +72,14 @@ int _libssh2_snprintf(char *cp, size_t cp_max_len, const char *fmt, ...) if(cp_max_len < 2) return 0; va_start(args, fmt); +#ifdef __clang__ +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wformat-nonliteral" +#endif n = vsnprintf(cp, cp_max_len, fmt, args); +#ifdef __clang__ +#pragma clang diagnostic pop +#endif va_end(args); return (n < (int)cp_max_len) ? n : (int)(cp_max_len - 1); } @@ -126,8 +132,8 @@ 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) +#ifdef _WIN32 +int _libssh2_wsa2errno(void) { switch(WSAGetLastError()) { case WSAEWOULDBLOCK: @@ -161,23 +167,29 @@ _libssh2_recv(libssh2_socket_t sock, void *buffer, size_t length, (void)abstract; rc = recv(sock, buffer, length, flags); -#ifdef WIN32 - if(rc < 0) - return -wsa2errno(); -#else if(rc < 0) { + int err; +#ifdef _WIN32 + err = _libssh2_wsa2errno(); +#else + err = errno; +#endif + /* Profiling tools that use SIGPROF can cause EINTR responses. + recv() does not modify its arguments when it returns EINTR, + but there may be data waiting, so the caller should try again */ + if(err == EINTR) + return -EAGAIN; /* Sometimes the first recv() function call sets errno to ENOENT on Solaris and HP-UX */ - if(errno == ENOENT) + if(err == ENOENT) return -EAGAIN; #ifdef EWOULDBLOCK /* For VMS and other special unixes */ - else if(errno == EWOULDBLOCK) - return -EAGAIN; + else if(err == EWOULDBLOCK) + return -EAGAIN; #endif else - return -errno; + return -err; } -#endif return rc; } @@ -194,18 +206,24 @@ _libssh2_send(libssh2_socket_t sock, const void *buffer, size_t length, (void)abstract; rc = send(sock, buffer, length, flags); -#ifdef WIN32 - if(rc < 0) - return -wsa2errno(); -#else if(rc < 0) { + int err; +#ifdef _WIN32 + err = _libssh2_wsa2errno(); +#else + err = errno; +#endif + /* Profiling tools that use SIGPROF can cause EINTR responses. + send() is defined as not yet sending any data when it returns EINTR, + so the caller should try again */ + if(err == EINTR) + return -EAGAIN; #ifdef EWOULDBLOCK /* For VMS and other special unixes */ - if(errno == EWOULDBLOCK) + if(err == EWOULDBLOCK) return -EAGAIN; #endif - return -errno; + return -err; } -#endif return rc; } @@ -557,7 +575,14 @@ _libssh2_debug_low(LIBSSH2_SESSION * session, int context, const char *format, buflen -= len; msglen = len; va_start(vargs, format); +#ifdef __clang__ +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wformat-nonliteral" +#endif len = vsnprintf(buffer + msglen, buflen, format, vargs); +#ifdef __clang__ +#pragma clang diagnostic pop +#endif va_end(vargs); msglen += len < buflen ? len : buflen - 1; } @@ -709,7 +734,7 @@ int _libssh2_gettimeofday(struct timeval *tp, void *tzp) { (void)tzp; if(tp) { -#ifdef WIN32 +#ifdef _WIN32 /* Offset between 1601-01-01 and 1970-01-01 in 100 nanosec units */ #define _WIN32_FT_OFFSET (116444736000000000) @@ -901,7 +926,6 @@ int _libssh2_copy_string(LIBSSH2_SESSION *session, struct string_buf *buf, } } else { - *outlen = 0; *outbuf = NULL; } diff --git a/libs/libssh2/src/misc.h b/libs/libssh2/src/misc.h index bf3e3c3623..c7b090f1b8 100644 --- a/libs/libssh2/src/misc.h +++ b/libs/libssh2/src/misc.h @@ -1,5 +1,5 @@ -#ifndef __LIBSSH2_MISC_H -#define __LIBSSH2_MISC_H +#ifndef LIBSSH2_MISC_H +#define LIBSSH2_MISC_H /* Copyright (C) Daniel Stenberg * All rights reserved. * @@ -44,8 +44,7 @@ (void)(buf); \ (void)(size); \ } while(0) -#else -#ifdef WIN32 +#elif defined(_WIN32) #define _libssh2_explicit_zero(buf, size) SecureZeroMemory(buf, size) #elif defined(HAVE_EXPLICIT_BZERO) #define _libssh2_explicit_zero(buf, size) explicit_bzero(buf, size) @@ -58,7 +57,6 @@ void _libssh2_memzero(void *buf, size_t size); #define _libssh2_explicit_zero(buf, size) _libssh2_memzero(buf, size) #endif -#endif struct list_head { struct list_node *last; @@ -81,6 +79,11 @@ 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); +#ifdef _WIN32 +/* Convert Win32 WSAGetLastError to errno equivalent */ +int _libssh2_wsa2errno(void); +#endif + void _libssh2_list_init(struct list_head *head); /* add a node last in the list */ @@ -139,4 +142,4 @@ void _libssh2_xor_data(unsigned char *output, void _libssh2_aes_ctr_increment(unsigned char *ctr, size_t length); -#endif /* _LIBSSH2_MISC_H */ +#endif /* LIBSSH2_MISC_H */ diff --git a/libs/libssh2/src/openssl.c b/libs/libssh2/src/openssl.c index 2dc2340c3b..31220f9cc8 100644 --- a/libs/libssh2/src/openssl.c +++ b/libs/libssh2/src/openssl.c @@ -44,16 +44,161 @@ #include <stdlib.h> #include <assert.h> -#ifndef EVP_MAX_BLOCK_LENGTH -#define EVP_MAX_BLOCK_LENGTH 32 +int _libssh2_hmac_ctx_init(libssh2_hmac_ctx *ctx) +{ +#ifdef USE_OPENSSL_3 + *ctx = NULL; + return 1; +#elif defined(HAVE_OPAQUE_STRUCTS) + *ctx = HMAC_CTX_new(); + return *ctx ? 1 : 0; +#else + HMAC_CTX_init(ctx); + return 1; #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); +#ifdef USE_OPENSSL_3 +static int _libssh2_hmac_init(libssh2_hmac_ctx *ctx, + void *key, size_t keylen, + const char *digest_name) +{ + EVP_MAC* mac; + OSSL_PARAM params[3]; + + mac = EVP_MAC_fetch(NULL, OSSL_MAC_NAME_HMAC, NULL); + if(!mac) + return 0; + + *ctx = EVP_MAC_CTX_new(mac); + EVP_MAC_free(mac); + if(!*ctx) + return 0; + + params[0] = OSSL_PARAM_construct_octet_string( + OSSL_MAC_PARAM_KEY, (void *)key, keylen); + params[1] = OSSL_PARAM_construct_utf8_string( + OSSL_MAC_PARAM_DIGEST, (char *)digest_name, 0); + params[2] = OSSL_PARAM_construct_end(); + + return EVP_MAC_init(*ctx, NULL, 0, params); +} +#endif + +#if LIBSSH2_MD5 +int _libssh2_hmac_md5_init(libssh2_hmac_ctx *ctx, + void *key, size_t keylen) +{ +#ifdef USE_OPENSSL_3 + return _libssh2_hmac_init(ctx, key, keylen, OSSL_DIGEST_NAME_MD5); +#elif defined(HAVE_OPAQUE_STRUCTS) + return HMAC_Init_ex(*ctx, key, (int)keylen, EVP_md5(), NULL); +#else + return HMAC_Init_ex(ctx, key, (int)keylen, EVP_md5(), NULL); +#endif +} +#endif + +#if LIBSSH2_HMAC_RIPEMD +int _libssh2_hmac_ripemd160_init(libssh2_hmac_ctx *ctx, + void *key, size_t keylen) +{ +#ifdef USE_OPENSSL_3 + return _libssh2_hmac_init(ctx, key, keylen, OSSL_DIGEST_NAME_RIPEMD160); +#elif defined(HAVE_OPAQUE_STRUCTS) + return HMAC_Init_ex(*ctx, key, (int)keylen, EVP_ripemd160(), NULL); +#else + return HMAC_Init_ex(ctx, key, (int)keylen, EVP_ripemd160(), NULL); +#endif +} +#endif + +int _libssh2_hmac_sha1_init(libssh2_hmac_ctx *ctx, + void *key, size_t keylen) +{ +#ifdef USE_OPENSSL_3 + return _libssh2_hmac_init(ctx, key, keylen, OSSL_DIGEST_NAME_SHA1); +#elif defined(HAVE_OPAQUE_STRUCTS) + return HMAC_Init_ex(*ctx, key, (int)keylen, EVP_sha1(), NULL); +#else + return HMAC_Init_ex(ctx, key, (int)keylen, EVP_sha1(), NULL); +#endif +} + +int _libssh2_hmac_sha256_init(libssh2_hmac_ctx *ctx, + void *key, size_t keylen) +{ +#ifdef USE_OPENSSL_3 + return _libssh2_hmac_init(ctx, key, keylen, OSSL_DIGEST_NAME_SHA2_256); +#elif defined(HAVE_OPAQUE_STRUCTS) + return HMAC_Init_ex(*ctx, key, (int)keylen, EVP_sha256(), NULL); +#else + return HMAC_Init_ex(ctx, key, (int)keylen, EVP_sha256(), NULL); +#endif +} + +int _libssh2_hmac_sha512_init(libssh2_hmac_ctx *ctx, + void *key, size_t keylen) +{ +#ifdef USE_OPENSSL_3 + return _libssh2_hmac_init(ctx, key, keylen, OSSL_DIGEST_NAME_SHA2_512); +#elif defined(HAVE_OPAQUE_STRUCTS) + return HMAC_Init_ex(*ctx, key, (int)keylen, EVP_sha512(), NULL); +#else + return HMAC_Init_ex(ctx, key, (int)keylen, EVP_sha512(), NULL); +#endif +} + +int _libssh2_hmac_update(libssh2_hmac_ctx *ctx, + const void *data, size_t datalen) +{ +#ifdef USE_OPENSSL_3 + return EVP_MAC_update(*ctx, data, datalen); +#elif defined(HAVE_OPAQUE_STRUCTS) +/* FIXME: upstream bug as of v5.6.0: datalen is int instead of size_t */ +#if defined(LIBSSH2_WOLFSSL) + return HMAC_Update(*ctx, data, (int)datalen); +#else /* !LIBSSH2_WOLFSSL */ + return HMAC_Update(*ctx, data, datalen); +#endif /* LIBSSH2_WOLFSSL */ +#else + return HMAC_Update(ctx, data, datalen); +#endif +} + +int _libssh2_hmac_final(libssh2_hmac_ctx *ctx, void *data) +{ +#ifdef USE_OPENSSL_3 + return EVP_MAC_final(*ctx, data, NULL, MAX_MACSIZE); +#elif defined(HAVE_OPAQUE_STRUCTS) + return HMAC_Final(*ctx, data, NULL); +#else + return HMAC_Final(ctx, data, NULL); +#endif +} + +void _libssh2_hmac_cleanup(libssh2_hmac_ctx *ctx) +{ +#ifdef USE_OPENSSL_3 + EVP_MAC_CTX_free(*ctx); +#elif defined(HAVE_OPAQUE_STRUCTS) + HMAC_CTX_free(*ctx); +#else + HMAC_cleanup(ctx); +#endif +} + +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); static int _libssh2_sk_pub_openssh_keyfilememory(LIBSSH2_SESSION *session, @@ -92,6 +237,20 @@ write_bn(unsigned char *buf, const BIGNUM *bn, int bn_bytes) } #endif +static inline void +_libssh2_swap_bytes(unsigned char *buf, unsigned long len) +{ +#if !defined(WORDS_BIGENDIAN) || !WORDS_BIGENDIAN + unsigned long i, j; + unsigned char temp; + for(i = 0, j = len - 1; i < j; i++, j--) { + temp = buf[i]; + buf[i] = buf[j]; + buf[j] = temp; + } +#endif +} + int _libssh2_openssl_random(void *buf, size_t len) { @@ -121,6 +280,76 @@ _libssh2_rsa_new(libssh2_rsa_ctx ** rsa, unsigned long e2len, const unsigned char *coeffdata, unsigned long coefflen) { +#ifdef USE_OPENSSL_3 + int ret = 0; + EVP_PKEY_CTX *ctx; + OSSL_PARAM params[4]; + int param_num = 0; + unsigned char *nbuf = NULL; + unsigned char *ebuf = NULL; + unsigned char *dbuf = NULL; + + (void)pdata; + (void)plen; + (void)qdata; + (void)qlen; + (void)e1data; + (void)e1len; + (void)e2data; + (void)e2len; + (void)coeffdata; + (void)coefflen; + + if(ndata && nlen > 0) { + nbuf = OPENSSL_malloc(nlen); + + if(nbuf) { + memcpy(nbuf, ndata, nlen); + _libssh2_swap_bytes(nbuf, nlen); + params[param_num++] = + OSSL_PARAM_construct_BN(OSSL_PKEY_PARAM_RSA_N, nbuf, nlen); + } + } + + if(edata && elen > 0) { + ebuf = OPENSSL_malloc(elen); + if(ebuf) { + memcpy(ebuf, edata, elen); + _libssh2_swap_bytes(ebuf, elen); + params[param_num++] = + OSSL_PARAM_construct_BN(OSSL_PKEY_PARAM_RSA_E, ebuf, elen); + } + } + + if(ddata && dlen > 0) { + dbuf = OPENSSL_malloc(dlen); + if(dbuf) { + memcpy(dbuf, ddata, dlen); + _libssh2_swap_bytes(dbuf, dlen); + params[param_num++] = + OSSL_PARAM_construct_BN(OSSL_PKEY_PARAM_RSA_D, dbuf, dlen); + } + } + + params[param_num] = OSSL_PARAM_construct_end(); + + *rsa = NULL; + ctx = EVP_PKEY_CTX_new_id(EVP_PKEY_RSA, NULL); + + if(EVP_PKEY_fromdata_init(ctx) > 0) { + ret = EVP_PKEY_fromdata(ctx, rsa, EVP_PKEY_KEYPAIR, params); + } + if(nbuf) + OPENSSL_clear_free(nbuf, nlen); + + if(ebuf) + OPENSSL_clear_free(ebuf, elen); + + if(dbuf) + OPENSSL_clear_free(dbuf, dlen); + + return (ret == 1) ? 0 : -1; +#else BIGNUM * e; BIGNUM * n; BIGNUM * d = 0; @@ -180,6 +409,8 @@ _libssh2_rsa_new(libssh2_rsa_ctx ** rsa, (*rsa)->iqmp = iqmp; #endif return 0; + +#endif /* USE_OPENSSL_3 */ } int @@ -189,6 +420,11 @@ _libssh2_rsa_sha2_verify(libssh2_rsa_ctx * rsactx, size_t sig_len, const unsigned char *m, size_t m_len) { +#ifdef USE_OPENSSL_3 + EVP_PKEY_CTX *ctx = NULL; + const EVP_MD *md = NULL; +#endif + int ret; int nid_type; unsigned char *hash = malloc(hash_len); @@ -202,7 +438,6 @@ _libssh2_rsa_sha2_verify(libssh2_rsa_ctx * rsactx, else if(hash_len == SHA256_DIGEST_LENGTH) { nid_type = NID_sha256; ret = _libssh2_sha256(m, m_len, hash); - } else if(hash_len == SHA512_DIGEST_LENGTH) { nid_type = NID_sha512; @@ -222,9 +457,37 @@ _libssh2_rsa_sha2_verify(libssh2_rsa_ctx * rsactx, return -1; /* failure */ } +#ifdef USE_OPENSSL_3 + ctx = EVP_PKEY_CTX_new(rsactx, NULL); + + if(nid_type == NID_sha1) { + md = EVP_sha1(); + } + else if(nid_type == NID_sha256) { + md = EVP_sha256(); + } + else if(nid_type == NID_sha512) { + md = EVP_sha512(); + } + + if(ctx && md) { + if(EVP_PKEY_verify_init(ctx) > 0 && + EVP_PKEY_CTX_set_rsa_padding(ctx, RSA_PKCS1_PADDING) > 0 && + EVP_PKEY_CTX_set_signature_md(ctx, md) > 0) { + ret = EVP_PKEY_verify(ctx, sig, sig_len, hash, hash_len); + } + } + + if(ctx) { + EVP_PKEY_CTX_free(ctx); + } + +#else + ret = RSA_verify(nid_type, hash, (unsigned int) hash_len, (unsigned char *) sig, (unsigned int) sig_len, rsactx); +#endif free(hash); @@ -257,6 +520,97 @@ _libssh2_dsa_new(libssh2_dsa_ctx ** dsactx, unsigned long y_len, const unsigned char *x, unsigned long x_len) { +#ifdef USE_OPENSSL_3 + int ret = 0; + EVP_PKEY_CTX *ctx = NULL; + OSSL_PARAM params[6]; + int param_num = 0; + unsigned char *p_buf = NULL; + unsigned char *q_buf = NULL; + unsigned char *g_buf = NULL; + unsigned char *y_buf = NULL; + unsigned char *x_buf = NULL; + + if(p && p_len > 0) { + p_buf = OPENSSL_malloc(p_len); + + if(p_buf) { + memcpy(p_buf, p, p_len); + _libssh2_swap_bytes(p_buf, p_len); + params[param_num++] = + OSSL_PARAM_construct_BN(OSSL_PKEY_PARAM_FFC_P, p_buf, p_len); + } + } + + if(q && q_len > 0) { + q_buf = OPENSSL_malloc(q_len); + + if(q_buf) { + memcpy(q_buf, q, q_len); + _libssh2_swap_bytes(q_buf, q_len); + params[param_num++] = + OSSL_PARAM_construct_BN(OSSL_PKEY_PARAM_FFC_Q, q_buf, q_len); + } + } + + if(g && g_len > 0) { + g_buf = OPENSSL_malloc(g_len); + + if(g_buf) { + memcpy(g_buf, g, g_len); + _libssh2_swap_bytes(g_buf, g_len); + params[param_num++] = + OSSL_PARAM_construct_BN(OSSL_PKEY_PARAM_FFC_G, g_buf, g_len); + } + } + + if(y && y_len > 0) { + y_buf = OPENSSL_malloc(y_len); + + if(y_buf) { + memcpy(y_buf, y, y_len); + _libssh2_swap_bytes(y_buf, y_len); + params[param_num++] = + OSSL_PARAM_construct_BN(OSSL_PKEY_PARAM_PUB_KEY, y_buf, y_len); + } + } + + if(x && x_len > 0) { + x_buf = OPENSSL_malloc(x_len); + + if(x_buf) { + memcpy(x_buf, x, x_len); + _libssh2_swap_bytes(x_buf, x_len); + params[param_num++] = + OSSL_PARAM_construct_BN(OSSL_PKEY_PARAM_PRIV_KEY, + x_buf, x_len); + } + } + + params[param_num] = OSSL_PARAM_construct_end(); + + *dsactx = NULL; + ctx = EVP_PKEY_CTX_new_id(EVP_PKEY_DSA, NULL); + + if(EVP_PKEY_fromdata_init(ctx) > 0) { + ret = EVP_PKEY_fromdata(ctx, dsactx, EVP_PKEY_KEYPAIR, params); + } + + if(p_buf) + OPENSSL_clear_free(p_buf, p_len); + if(q_buf) + OPENSSL_clear_free(q_buf, q_len); + if(g_buf) + OPENSSL_clear_free(g_buf, g_len); + if(x_buf) + OPENSSL_clear_free(x_buf, x_len); + if(y_buf) + OPENSSL_clear_free(y_buf, y_len); + + return (ret == 1) ? 0 : -1; + +#else + BIGNUM * p_bn; BIGNUM * q_bn; BIGNUM * g_bn; @@ -297,6 +651,8 @@ _libssh2_dsa_new(libssh2_dsa_ctx ** dsactx, (*dsactx)->priv_key = priv_key; #endif return 0; + +#endif /* USE_OPENSSL_3 */ } int @@ -304,6 +660,12 @@ _libssh2_dsa_sha1_verify(libssh2_dsa_ctx * dsactx, const unsigned char *sig, const unsigned char *m, size_t m_len) { +#ifdef USE_OPENSSL_3 + EVP_PKEY_CTX *ctx = NULL; + unsigned char *der = NULL; + int der_len = 0; +#endif + unsigned char hash[SHA_DIGEST_LENGTH]; DSA_SIG * dsasig; BIGNUM * r; @@ -322,9 +684,30 @@ _libssh2_dsa_sha1_verify(libssh2_dsa_ctx * dsactx, dsasig->r = r; dsasig->s = s; #endif + +#ifdef USE_OPENSSL_3 + ctx = EVP_PKEY_CTX_new(dsactx, NULL); + der_len = i2d_DSA_SIG(dsasig, &der); + + if(ctx && !_libssh2_sha1(m, m_len, hash)) { + /* _libssh2_sha1() succeeded */ + if(EVP_PKEY_verify_init(ctx) > 0) { + ret = EVP_PKEY_verify(ctx, der, der_len, hash, SHA_DIGEST_LENGTH); + } + } + + if(ctx) { + EVP_PKEY_CTX_free(ctx); + } + + if(der) { + OPENSSL_clear_free(der, der_len); + } +#else if(!_libssh2_sha1(m, m_len, hash)) /* _libssh2_sha1() succeeded */ ret = DSA_do_verify(hash, SHA_DIGEST_LENGTH, dsasig, dsactx); +#endif DSA_SIG_free(dsasig); @@ -343,8 +726,25 @@ _libssh2_dsa_sha1_verify(libssh2_dsa_ctx * dsactx, libssh2_curve_type _libssh2_ecdsa_get_curve_type(libssh2_ecdsa_ctx *ec_ctx) { +#ifdef USE_OPENSSL_3 + int bits = 0; + EVP_PKEY_get_int_param(ec_ctx, OSSL_PKEY_PARAM_BITS, &bits); + + if(bits == 256) { + return LIBSSH2_EC_CURVE_NISTP256; + } + else if(bits == 384) { + return LIBSSH2_EC_CURVE_NISTP384; + } + else if(bits == 521) { + return LIBSSH2_EC_CURVE_NISTP521; + } + + return LIBSSH2_EC_CURVE_NISTP256; +#else const EC_GROUP *group = EC_KEY_get0_group(ec_ctx); return EC_GROUP_get_curve_name(group); +#endif } /* _libssh2_ecdsa_curve_type_from_name @@ -390,13 +790,56 @@ _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; + +#ifdef USE_OPENSSL_3 + EVP_PKEY_CTX *ctx = EVP_PKEY_CTX_new_id(EVP_PKEY_EC, NULL); + const char *n = EC_curve_nid2nist(curve); + char *group_name = NULL; + unsigned char *data = NULL; + + if(n) { + group_name = OPENSSL_zalloc(strlen(n) + 1); + } + + if(k_len > 0) { + data = OPENSSL_malloc(k_len); + } + + if(group_name && data) { + OSSL_PARAM params[3] = { 0 }; + + memcpy(group_name, n, strlen(n)); + memcpy(data, k, k_len); + + params[0] = + OSSL_PARAM_construct_utf8_string(OSSL_PKEY_PARAM_GROUP_NAME, + group_name, 0); + + params[1] = + OSSL_PARAM_construct_octet_string(OSSL_PKEY_PARAM_PUB_KEY, + data, k_len); + + params[2] = OSSL_PARAM_construct_end(); + + if(EVP_PKEY_fromdata_init(ctx) > 0) { + ret = EVP_PKEY_fromdata(ctx, ec_ctx, EVP_PKEY_PUBLIC_KEY, + params); + } + + if(group_name) + OPENSSL_clear_free(group_name, strlen(n)); + + if(data) + OPENSSL_clear_free(data, k_len); + } +#else EC_KEY *ec_key = EC_KEY_new_by_curve_name(curve); - EC_POINT *point = NULL; if(ec_key) { + const EC_GROUP *ec_group = NULL; + EC_POINT *point = NULL; + 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); @@ -408,27 +851,51 @@ _libssh2_ecdsa_curve_name_with_octal_new(libssh2_ecdsa_ctx ** ec_ctx, if(ec_ctx) *ec_ctx = ec_key; } +#endif return (ret == 1) ? 0 : -1; } +#ifdef USE_OPENSSL_3 #define LIBSSH2_ECDSA_VERIFY(digest_type) \ do { \ 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); \ + if(libssh2_sha##digest_type(m, m_len, hash) == 0) { \ + ret = EVP_PKEY_verify_init(ctx); \ + if(ret > 0) { \ + ret = EVP_PKEY_verify(ctx, der, der_len, hash, \ + SHA##digest_type##_DIGEST_LENGTH); \ + } \ + } \ } while(0) +#else +#define LIBSSH2_ECDSA_VERIFY(digest_type) \ + do { \ + unsigned char hash[SHA##digest_type##_DIGEST_LENGTH]; \ + if(libssh2_sha##digest_type(m, m_len, hash) == 0) { \ + ret = ECDSA_do_verify(hash, \ + SHA##digest_type##_DIGEST_LENGTH, \ + ecdsa_sig, ec_key); \ + } \ + } while(0) +#endif int -_libssh2_ecdsa_verify(libssh2_ecdsa_ctx * ctx, +_libssh2_ecdsa_verify(libssh2_ecdsa_ctx * ecdsa_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_get_curve_type(ec_key); + libssh2_curve_type type = _libssh2_ecdsa_get_curve_type(ecdsa_ctx); + +#ifdef USE_OPENSSL_3 + EVP_PKEY_CTX *ctx = NULL; + unsigned char *der = NULL; + int der_len = 0; +#else + EC_KEY *ec_key = (EC_KEY*)ecdsa_ctx; +#endif #ifdef HAVE_OPAQUE_STRUCTS ECDSA_SIG *ecdsa_sig = ECDSA_SIG_new(); @@ -438,7 +905,6 @@ _libssh2_ecdsa_verify(libssh2_ecdsa_ctx * ctx, BN_bin2bn(r, (int) r_len, pr); BN_bin2bn(s, (int) s_len, ps); ECDSA_SIG_set0(ecdsa_sig, pr, ps); - #else ECDSA_SIG ecdsa_sig_; ECDSA_SIG *ecdsa_sig = &ecdsa_sig_; @@ -448,6 +914,11 @@ _libssh2_ecdsa_verify(libssh2_ecdsa_ctx * ctx, BN_bin2bn(s, (int) s_len, ecdsa_sig_.s); #endif +#ifdef USE_OPENSSL_3 + ctx = EVP_PKEY_CTX_new(ecdsa_ctx, NULL); + der_len = i2d_ECDSA_SIG(ecdsa_sig, &der); +#endif + if(type == LIBSSH2_EC_CURVE_NISTP256) { LIBSSH2_ECDSA_VERIFY(256); } @@ -502,6 +973,10 @@ _libssh2_cipher_init(_libssh2_cipher_ctx * h, #endif } +#ifndef EVP_MAX_BLOCK_LENGTH +#define EVP_MAX_BLOCK_LENGTH 32 +#endif + int _libssh2_cipher_crypt(_libssh2_cipher_ctx * ctx, _libssh2_cipher_type(algo), @@ -568,8 +1043,7 @@ _libssh2_cipher_crypt(_libssh2_cipher_ctx * ctx, #endif } -#if (defined(OPENSSL_VERSION_MAJOR) && OPENSSL_VERSION_MAJOR >= 3) || \ - defined(LIBSSH2_WOLFSSL) +#if defined(USE_OPENSSL_3) || defined(LIBSSH2_WOLFSSL) if(ret != -1) #else if(ret >= 1) @@ -617,13 +1091,8 @@ _libssh2_cipher_crypt(_libssh2_cipher_ctx * ctx, 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 +#if OPENSSL_VERSION_NUMBER < 0x10100000L || \ + (defined(LIBRESSL_VERSION_NUMBER) && LIBRESSL_VERSION_NUMBER < 0x2070000fL) OpenSSL_add_all_algorithms(); OpenSSL_add_all_ciphers(); OpenSSL_add_all_digests(); @@ -632,6 +1101,9 @@ void _libssh2_openssl_crypto_init(void) ENGINE_register_all_complete(); #endif #endif +#if defined(LIBSSH2_WOLFSSL) && defined(DEBUG_WOLFSSL) + wolfSSL_Debugging_ON(); +#endif } void _libssh2_openssl_crypto_exit(void) @@ -717,43 +1189,69 @@ read_private_key_from_file(void **key_ctx, int _libssh2_rsa_new_private_frommemory(libssh2_rsa_ctx ** rsa, LIBSSH2_SESSION * session, - const char *filedata, size_t filedata_len, + const char *filedata, + size_t filedata_len, unsigned const char *passphrase) { int rc; +#if defined(USE_OPENSSL_3) + pem_read_bio_func read_rsa = + (pem_read_bio_func) &PEM_read_bio_PrivateKey; +#else pem_read_bio_func read_rsa = (pem_read_bio_func) &PEM_read_bio_RSAPrivateKey; +#endif _libssh2_init_if_needed(); - rc = read_private_key_from_memory((void **) rsa, read_rsa, - filedata, filedata_len, passphrase); + 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); + rc = _libssh2_pub_priv_openssh_keyfilememory(session, (void **)rsa, + "ssh-rsa", + NULL, NULL, NULL, NULL, + filedata, filedata_len, + passphrase); } return rc; } static unsigned char * -gen_publickey_from_rsa(LIBSSH2_SESSION *session, RSA *rsa, +gen_publickey_from_rsa(LIBSSH2_SESSION *session, libssh2_rsa_ctx *rsa, size_t *key_len) { int e_bytes, n_bytes; unsigned long len; unsigned char *key; unsigned char *p; + +#ifdef USE_OPENSSL_3 + BIGNUM * e = NULL; + BIGNUM * n = NULL; + + EVP_PKEY_get_bn_param(rsa, OSSL_PKEY_PARAM_RSA_E, &e); + EVP_PKEY_get_bn_param(rsa, OSSL_PKEY_PARAM_RSA_N, &n); +#else const BIGNUM * e; const BIGNUM * n; -#ifdef HAVE_OPAQUE_STRUCTS +#if defined(HAVE_OPAQUE_STRUCTS) + e = NULL; + n = NULL; + RSA_get0_key(rsa, &n, &e, NULL); #else e = rsa->e; n = rsa->n; #endif +#endif + if(!e || !n) { + return NULL; + } + e_bytes = BN_num_bytes(e) + 1; n_bytes = BN_num_bytes(n) + 1; @@ -788,7 +1286,7 @@ gen_publickey_from_rsa_evp(LIBSSH2_SESSION *session, size_t *pubkeydata_len, EVP_PKEY *pk) { - RSA* rsa = NULL; + libssh2_rsa_ctx* rsa = NULL; unsigned char *key; unsigned char *method_buf = NULL; size_t key_len; @@ -797,7 +1295,11 @@ gen_publickey_from_rsa_evp(LIBSSH2_SESSION *session, LIBSSH2_TRACE_AUTH, "Computing public key from RSA private key envelope")); +#ifdef USE_OPENSSL_3 + rsa = pk; +#else rsa = EVP_PKEY_get1_RSA(pk); +#endif if(!rsa) { /* Assume memory allocation error... what else could it be ? */ goto __alloc_error; @@ -812,19 +1314,27 @@ gen_publickey_from_rsa_evp(LIBSSH2_SESSION *session, if(!key) { goto __alloc_error; } +#ifndef USE_OPENSSL_3 RSA_free(rsa); +#endif memcpy(method_buf, "ssh-rsa", 7); - *method = method_buf; - *method_len = 7; - *pubkeydata = key; - *pubkeydata_len = key_len; + *method = method_buf; + if(method_len) { + *method_len = 7; + } + *pubkeydata = key; + if(pubkeydata_len) { + *pubkeydata_len = key_len; + } return 0; __alloc_error: +#ifndef USE_OPENSSL_3 if(rsa) { RSA_free(rsa); } +#endif if(method_buf) { LIBSSH2_FREE(session, method_buf); } @@ -834,7 +1344,8 @@ __alloc_error: "Unable to allocate memory for private key data"); } -static int _libssh2_rsa_new_additional_parameters(RSA *rsa) +#ifndef USE_OPENSSL_3 +static int _libssh2_rsa_new_additional_parameters(libssh2_rsa_ctx *rsa) { BN_CTX *ctx = NULL; BIGNUM *aux = NULL; @@ -905,6 +1416,7 @@ out: return rc; } +#endif /* ndef USE_OPENSSL_3 */ static int gen_publickey_from_rsa_openssh_priv_data(LIBSSH2_SESSION *session, @@ -918,7 +1430,7 @@ gen_publickey_from_rsa_openssh_priv_data(LIBSSH2_SESSION *session, 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_rsa_ctx *rsa = NULL; _libssh2_debug((session, LIBSSH2_TRACE_AUTH, @@ -983,32 +1495,40 @@ gen_publickey_from_rsa_openssh_priv_data(LIBSSH2_SESSION *session, goto fail; } +#ifndef USE_OPENSSL_3 if(rsa) rc = _libssh2_rsa_new_additional_parameters(rsa); +#endif if(rsa && pubkeydata && method) { +#ifdef USE_OPENSSL_3 + EVP_PKEY *pk = rsa; +#else EVP_PKEY *pk = EVP_PKEY_new(); EVP_PKEY_set1_RSA(pk, rsa); +#endif rc = gen_publickey_from_rsa_evp(session, method, method_len, pubkeydata, pubkeydata_len, pk); +#ifndef USE_OPENSSL_3 if(pk) EVP_PKEY_free(pk); +#endif } if(rsa_ctx) *rsa_ctx = rsa; else - RSA_free(rsa); + _libssh2_rsa_free(rsa); return rc; fail: if(rsa) - RSA_free(rsa); + _libssh2_rsa_free(rsa); return _libssh2_error(session, LIBSSH2_ERROR_ALLOC, @@ -1058,8 +1578,8 @@ _libssh2_rsa_new_openssh_private(libssh2_rsa_ctx ** rsa, if(strcmp("ssh-rsa", (const char *)buf) == 0) { rc = gen_publickey_from_rsa_openssh_priv_data(session, decrypted, - NULL, 0, - NULL, 0, rsa); + NULL, NULL, + NULL, NULL, rsa); } else { rc = -1; @@ -1078,8 +1598,13 @@ _libssh2_rsa_new_private(libssh2_rsa_ctx ** rsa, { int rc; +#if defined(USE_OPENSSL_3) + pem_read_bio_func read_rsa = + (pem_read_bio_func) &PEM_read_bio_PrivateKey; +#else pem_read_bio_func read_rsa = (pem_read_bio_func) &PEM_read_bio_RSAPrivateKey; +#endif _libssh2_init_if_needed(); @@ -1099,13 +1624,19 @@ _libssh2_rsa_new_private(libssh2_rsa_ctx ** rsa, int _libssh2_dsa_new_private_frommemory(libssh2_dsa_ctx ** dsa, LIBSSH2_SESSION * session, - const char *filedata, size_t filedata_len, + const char *filedata, + size_t filedata_len, unsigned const char *passphrase) { int rc; +#if defined(USE_OPENSSL_3) + pem_read_bio_func read_dsa = + (pem_read_bio_func) &PEM_read_bio_PrivateKey; +#else pem_read_bio_func read_dsa = (pem_read_bio_func) &PEM_read_bio_DSAPrivateKey; +#endif _libssh2_init_if_needed(); @@ -1114,17 +1645,18 @@ _libssh2_dsa_new_private_frommemory(libssh2_dsa_ctx ** dsa, passphrase); if(rc) { - rc = read_openssh_private_key_from_memory((void **)dsa, session, - "ssh-dsa", - filedata, filedata_len, - passphrase); + rc = _libssh2_pub_priv_openssh_keyfilememory(session, (void **)dsa, + "ssh-dsa", + NULL, NULL, NULL, NULL, + filedata, filedata_len, + passphrase); } return rc; } static unsigned char * -gen_publickey_from_dsa(LIBSSH2_SESSION* session, DSA *dsa, +gen_publickey_from_dsa(LIBSSH2_SESSION* session, libssh2_dsa_ctx *dsa, size_t *key_len) { int p_bytes, q_bytes, g_bytes, k_bytes; @@ -1132,6 +1664,17 @@ gen_publickey_from_dsa(LIBSSH2_SESSION* session, DSA *dsa, unsigned char *key; unsigned char *p; +#ifdef USE_OPENSSL_3 + BIGNUM * p_bn; + BIGNUM * q; + BIGNUM * g; + BIGNUM * pub_key; + + EVP_PKEY_get_bn_param(dsa, OSSL_PKEY_PARAM_FFC_P, &p_bn); + EVP_PKEY_get_bn_param(dsa, OSSL_PKEY_PARAM_FFC_G, &q); + EVP_PKEY_get_bn_param(dsa, OSSL_PKEY_PARAM_FFC_Q, &g); + EVP_PKEY_get_bn_param(dsa, OSSL_PKEY_PARAM_PUB_KEY, &pub_key); +#else const BIGNUM * p_bn; const BIGNUM * q; const BIGNUM * g; @@ -1149,6 +1692,7 @@ gen_publickey_from_dsa(LIBSSH2_SESSION* session, DSA *dsa, #else pub_key = dsa->pub_key; #endif +#endif p_bytes = BN_num_bytes(p_bn) + 1; q_bytes = BN_num_bytes(q) + 1; g_bytes = BN_num_bytes(g) + 1; @@ -1187,7 +1731,7 @@ gen_publickey_from_dsa_evp(LIBSSH2_SESSION *session, size_t *pubkeydata_len, EVP_PKEY *pk) { - DSA* dsa = NULL; + libssh2_dsa_ctx *dsa = NULL; unsigned char *key; unsigned char *method_buf = NULL; size_t key_len; @@ -1196,7 +1740,11 @@ gen_publickey_from_dsa_evp(LIBSSH2_SESSION *session, LIBSSH2_TRACE_AUTH, "Computing public key from DSA private key envelope")); +#ifdef USE_OPENSSL_3 + dsa = pk; +#else dsa = EVP_PKEY_get1_DSA(pk); +#endif if(!dsa) { /* Assume memory allocation error... what else could it be ? */ goto __alloc_error; @@ -1211,19 +1759,27 @@ gen_publickey_from_dsa_evp(LIBSSH2_SESSION *session, if(!key) { goto __alloc_error; } +#ifndef USE_OPENSSL_3 DSA_free(dsa); +#endif memcpy(method_buf, "ssh-dss", 7); - *method = method_buf; - *method_len = 7; - *pubkeydata = key; - *pubkeydata_len = key_len; + *method = method_buf; + if(method_len) { + *method_len = 7; + } + *pubkeydata = key; + if(pubkeydata_len) { + *pubkeydata_len = key_len; + } return 0; __alloc_error: +#ifndef USE_OPENSSL_3 if(dsa) { DSA_free(dsa); } +#endif if(method_buf) { LIBSSH2_FREE(session, method_buf); } @@ -1245,7 +1801,7 @@ gen_publickey_from_dsa_openssh_priv_data(LIBSSH2_SESSION *session, 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_dsa_ctx *dsa = NULL; _libssh2_debug((session, LIBSSH2_TRACE_AUTH, @@ -1295,28 +1851,34 @@ gen_publickey_from_dsa_openssh_priv_data(LIBSSH2_SESSION *session, } if(dsa && pubkeydata && method) { +#ifdef USE_OPENSSL_3 + EVP_PKEY *pk = dsa; +#else EVP_PKEY *pk = EVP_PKEY_new(); EVP_PKEY_set1_DSA(pk, dsa); +#endif rc = gen_publickey_from_dsa_evp(session, method, method_len, pubkeydata, pubkeydata_len, pk); +#ifndef USE_OPENSSL_3 if(pk) EVP_PKEY_free(pk); +#endif } if(dsa_ctx) *dsa_ctx = dsa; else - DSA_free(dsa); + _libssh2_dsa_free(dsa); return rc; fail: if(dsa) - DSA_free(dsa); + _libssh2_dsa_free(dsa); return _libssh2_error(session, LIBSSH2_ERROR_ALLOC, @@ -1366,8 +1928,8 @@ _libssh2_dsa_new_openssh_private(libssh2_dsa_ctx ** dsa, if(strcmp("ssh-dss", (const char *)buf) == 0) { rc = gen_publickey_from_dsa_openssh_priv_data(session, decrypted, - NULL, 0, - NULL, 0, dsa); + NULL, NULL, + NULL, NULL, dsa); } else { rc = -1; @@ -1386,8 +1948,13 @@ _libssh2_dsa_new_private(libssh2_dsa_ctx ** dsa, { int rc; +#if defined(USE_OPENSSL_3) + pem_read_bio_func read_dsa = + (pem_read_bio_func) &PEM_read_bio_PrivateKey; +#else pem_read_bio_func read_dsa = (pem_read_bio_func) &PEM_read_bio_DSAPrivateKey; +#endif _libssh2_init_if_needed(); @@ -1404,7 +1971,6 @@ _libssh2_dsa_new_private(libssh2_dsa_ctx ** dsa, #endif /* LIBSSH_DSA */ #if LIBSSH2_ECDSA - int _libssh2_ecdsa_new_private_frommemory(libssh2_ecdsa_ctx ** ec_ctx, LIBSSH2_SESSION * session, @@ -1414,20 +1980,26 @@ _libssh2_ecdsa_new_private_frommemory(libssh2_ecdsa_ctx ** ec_ctx, { int rc; +#if defined(USE_OPENSSL_3) + pem_read_bio_func read_ec = + (pem_read_bio_func) &PEM_read_bio_PrivateKey; +#else pem_read_bio_func read_ec = (pem_read_bio_func) &PEM_read_bio_ECPrivateKey; +#endif _libssh2_init_if_needed(); - rc = read_private_key_from_memory((void **) ec_ctx, read_ec, + 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); + rc = _libssh2_pub_priv_openssh_keyfilememory(session, (void **)ec_ctx, + "ssh-ecdsa", + NULL, NULL, NULL, NULL, + filedata, filedata_len, + passphrase); } return rc; @@ -1584,10 +2156,14 @@ gen_publickey_from_ed_evp(LIBSSH2_SESSION *session, goto fail; } - *method = methodBuf; - *method_len = sizeof(methodName) - 1; - *pubkeydata = keyBuf; - *pubkeydata_len = bufLen; + *method = methodBuf; + if(method_len) { + *method_len = sizeof(methodName) - 1; + } + *pubkeydata = keyBuf; + if(pubkeydata_len) { + *pubkeydata_len = bufLen; + } return 0; fail: @@ -1896,7 +2472,6 @@ clean_exit: return -1; } - int _libssh2_ed25519_new_private(libssh2_ed25519_ctx ** ed_ctx, LIBSSH2_SESSION * session, @@ -1939,12 +2514,9 @@ _libssh2_ed25519_new_private(libssh2_ed25519_ctx ** ed_ctx, } if(strcmp("ssh-ed25519", (const char *)buf) == 0) { - rc = gen_publickey_from_ed25519_openssh_priv_data(session, - decrypted, - NULL, - NULL, - NULL, - NULL, + rc = gen_publickey_from_ed25519_openssh_priv_data(session, decrypted, + NULL, NULL, + NULL, NULL, &ctx); } else { @@ -2013,10 +2585,8 @@ _libssh2_ed25519_new_private_sk(libssh2_ed25519_ctx **ed_ctx, if(strcmp("sk-ssh-ed25519@openssh.com", (const char *)buf) == 0) { rc = gen_publickey_from_sk_ed25519_openssh_priv_data(session, decrypted, - NULL, - NULL, - NULL, - NULL, + NULL, NULL, + NULL, NULL, flags, application, key_handle, @@ -2066,10 +2636,11 @@ _libssh2_ed25519_new_private_frommemory(libssh2_ed25519_ctx ** ed_ctx, return 0; } - return read_openssh_private_key_from_memory((void **)ed_ctx, session, - "ssh-ed25519", - filedata, filedata_len, - passphrase); + return _libssh2_pub_priv_openssh_keyfilememory(session, (void **)ed_ctx, + "ssh-ed25519", + NULL, NULL, NULL, NULL, + filedata, filedata_len, + passphrase); } int @@ -2136,17 +2707,57 @@ _libssh2_rsa_sha2_sign(LIBSSH2_SESSION * session, size_t hash_len, unsigned char **signature, size_t *signature_len) { - int ret; - unsigned char *sig; - unsigned int sig_len; + int ret = -1; + unsigned char *sig = NULL; + +#ifdef USE_OPENSSL_3 + size_t sig_len = 0; + BIGNUM *n = NULL; + const EVP_MD *md = NULL; + + if(EVP_PKEY_get_bn_param(rsactx, OSSL_PKEY_PARAM_RSA_N, &n) > 0) { + sig_len = BN_num_bytes(n); + } + + if(sig_len > 0) + sig = LIBSSH2_ALLOC(session, sig_len); +#else + unsigned int sig_len = 0; sig_len = RSA_size(rsactx); sig = LIBSSH2_ALLOC(session, sig_len); +#endif if(!sig) { return -1; } +#ifdef USE_OPENSSL_3 + if(hash_len == SHA_DIGEST_LENGTH) + md = EVP_sha1(); + else if(hash_len == SHA256_DIGEST_LENGTH) + md = EVP_sha256(); + else if(hash_len == SHA512_DIGEST_LENGTH) + md = EVP_sha512(); + else { + _libssh2_error(session, LIBSSH2_ERROR_PROTO, + "Unsupported hash digest length"); + } + + if(md) { + EVP_PKEY_CTX *ctx = EVP_PKEY_CTX_new(rsactx, NULL); + if(ctx && + EVP_PKEY_sign_init(ctx) > 0 && + EVP_PKEY_CTX_set_rsa_padding(ctx, RSA_PKCS1_PADDING) > 0 && + EVP_PKEY_CTX_set_signature_md(ctx, md) > 0) { + ret = EVP_PKEY_sign(ctx, sig, &sig_len, hash, hash_len); + } + + if(ctx) { + EVP_PKEY_CTX_free(ctx); + } + } +#else if(hash_len == SHA_DIGEST_LENGTH) ret = RSA_sign(NID_sha1, hash, (unsigned int) hash_len, sig, &sig_len, rsactx); @@ -2161,6 +2772,7 @@ _libssh2_rsa_sha2_sign(LIBSSH2_SESSION * session, "Unsupported hash digest length"); ret = -1; } +#endif if(!ret) { LIBSSH2_FREE(session, sig); @@ -2193,14 +2805,41 @@ _libssh2_dsa_sha1_sign(libssh2_dsa_ctx * dsactx, const unsigned char *hash, size_t hash_len, unsigned char *signature) { - DSA_SIG *sig; + DSA_SIG *sig = NULL; const BIGNUM * r; const BIGNUM * s; int r_len, s_len; +#ifdef USE_OPENSSL_3 + EVP_PKEY_CTX *ctx = EVP_PKEY_CTX_new(dsactx, NULL); + unsigned char *buf = NULL; + size_t sig_len = 0; + int size = 0; + + if(EVP_PKEY_get_int_param(dsactx, OSSL_PKEY_PARAM_MAX_SIZE, &size) > 0) { + sig_len = size; + buf = OPENSSL_malloc(size); + } + + if(buf && ctx && EVP_PKEY_sign_init(ctx) > 0) { + EVP_PKEY_sign(ctx, buf, &sig_len, hash, hash_len); + } + + if(ctx) { + EVP_PKEY_CTX_free(ctx); + } + + if(buf) { + const unsigned char *in = buf; + d2i_DSA_SIG(&sig, &in, (long)sig_len); + OPENSSL_clear_free(buf, size); + } +#else (void)hash_len; sig = DSA_do_sign(hash, SHA_DIGEST_LENGTH, dsactx); +#endif + if(!sig) { return -1; } @@ -2212,20 +2851,20 @@ _libssh2_dsa_sha1_sign(libssh2_dsa_ctx * dsactx, s = sig->s; #endif r_len = BN_num_bytes(r); - if(r_len < 1 || r_len > 20) { + if(r_len < 1 || r_len > SHA_DIGEST_LENGTH) { DSA_SIG_free(sig); return -1; } s_len = BN_num_bytes(s); - if(s_len < 1 || s_len > 20) { + if(s_len < 1 || s_len > SHA_DIGEST_LENGTH) { DSA_SIG_free(sig); return -1; } - memset(signature, 0, 40); + memset(signature, 0, SHA_DIGEST_LENGTH * 2); - BN_bn2bin(r, signature + (20 - r_len)); - BN_bn2bin(s, signature + 20 + (20 - s_len)); + BN_bn2bin(r, signature + (SHA_DIGEST_LENGTH - r_len)); + BN_bn2bin(s, signature + SHA_DIGEST_LENGTH + (SHA_DIGEST_LENGTH - s_len)); DSA_SIG_free(sig); @@ -2247,10 +2886,47 @@ _libssh2_ecdsa_sign(LIBSSH2_SESSION * session, libssh2_ecdsa_ctx * ec_ctx, const BIGNUM *pr = NULL, *ps = NULL; unsigned char *temp_buffer = NULL; unsigned char *out_buffer = NULL; + ECDSA_SIG *sig = NULL; + +#ifdef USE_OPENSSL_3 + EVP_PKEY_CTX *ctx = EVP_PKEY_CTX_new(ec_ctx, NULL); + const unsigned char *p = NULL; + rc = -1; + + if(!ctx) { + return _libssh2_error(session, LIBSSH2_ERROR_ALLOC, + "out of memory"); + } + + out_buffer_len = EVP_PKEY_get_size(ec_ctx); + temp_buffer = LIBSSH2_ALLOC(session, out_buffer_len); + if(!temp_buffer) { + goto clean_exit; + } + + rc = EVP_PKEY_sign_init(ctx); + if(rc <= 0) { + rc = -1; + goto clean_exit; + } + + rc = EVP_PKEY_sign(ctx, temp_buffer, &out_buffer_len, hash, hash_len); + if(rc <= 0) { + rc = -1; + goto clean_exit; + } - ECDSA_SIG *sig = ECDSA_do_sign(hash, (int) hash_len, ec_ctx); + rc = 0; + + p = temp_buffer; + sig = d2i_ECDSA_SIG(NULL, &p, (long)out_buffer_len); + OPENSSL_clear_free(temp_buffer, out_buffer_len); +#else + sig = ECDSA_do_sign(hash, (int)hash_len, ec_ctx); if(!sig) return -1; +#endif + #ifdef HAVE_OPAQUE_STRUCTS ECDSA_SIG_get0(sig, &pr, &ps); #else @@ -2292,6 +2968,11 @@ clean_exit: if(sig) ECDSA_SIG_free(sig); +#ifdef USE_OPENSSL_3 + if(ctx) + EVP_PKEY_CTX_free(ctx); +#endif + return rc; } #endif /* LIBSSH2_ECDSA */ @@ -2319,6 +3000,30 @@ _libssh2_sha1_init(libssh2_sha1_ctx *ctx) } int +_libssh2_sha1_update(libssh2_sha1_ctx *ctx, + const void *data, size_t len) +{ +#ifdef HAVE_OPAQUE_STRUCTS + return EVP_DigestUpdate(*ctx, data, len); +#else + return EVP_DigestUpdate(ctx, data, len); +#endif +} + +int +_libssh2_sha1_final(libssh2_sha1_ctx *ctx, + unsigned char *out) +{ +#ifdef HAVE_OPAQUE_STRUCTS + int ret = EVP_DigestFinal(*ctx, out, NULL); + EVP_MD_CTX_free(*ctx); + return ret; +#else + return EVP_DigestFinal(ctx, out, NULL); +#endif +} + +int _libssh2_sha1(const unsigned char *message, size_t len, unsigned char *out) { @@ -2371,6 +3076,30 @@ _libssh2_sha256_init(libssh2_sha256_ctx *ctx) } int +_libssh2_sha256_update(libssh2_sha256_ctx *ctx, + const void *data, size_t len) +{ +#ifdef HAVE_OPAQUE_STRUCTS + return EVP_DigestUpdate(*ctx, data, len); +#else + return EVP_DigestUpdate(ctx, data, len); +#endif +} + +int +_libssh2_sha256_final(libssh2_sha256_ctx *ctx, + unsigned char *out) +{ +#ifdef HAVE_OPAQUE_STRUCTS + int ret = EVP_DigestFinal(*ctx, out, NULL); + EVP_MD_CTX_free(*ctx); + return ret; +#else + return EVP_DigestFinal(ctx, out, NULL); +#endif +} + +int _libssh2_sha256(const unsigned char *message, size_t len, unsigned char *out) { @@ -2423,6 +3152,30 @@ _libssh2_sha384_init(libssh2_sha384_ctx *ctx) } int +_libssh2_sha384_update(libssh2_sha384_ctx *ctx, + const void *data, size_t len) +{ +#ifdef HAVE_OPAQUE_STRUCTS + return EVP_DigestUpdate(*ctx, data, len); +#else + return EVP_DigestUpdate(ctx, data, len); +#endif +} + +int +_libssh2_sha384_final(libssh2_sha384_ctx *ctx, + unsigned char *out) +{ +#ifdef HAVE_OPAQUE_STRUCTS + int ret = EVP_DigestFinal(*ctx, out, NULL); + EVP_MD_CTX_free(*ctx); + return ret; +#else + return EVP_DigestFinal(ctx, out, NULL); +#endif +} + +int _libssh2_sha384(const unsigned char *message, size_t len, unsigned char *out) { @@ -2475,6 +3228,30 @@ _libssh2_sha512_init(libssh2_sha512_ctx *ctx) } int +_libssh2_sha512_update(libssh2_sha512_ctx *ctx, + const void *data, size_t len) +{ +#ifdef HAVE_OPAQUE_STRUCTS + return EVP_DigestUpdate(*ctx, data, len); +#else + return EVP_DigestUpdate(ctx, data, len); +#endif +} + +int +_libssh2_sha512_final(libssh2_sha512_ctx *ctx, + unsigned char *out) +{ +#ifdef HAVE_OPAQUE_STRUCTS + int ret = EVP_DigestFinal(*ctx, out, NULL); + EVP_MD_CTX_free(*ctx); + return ret; +#else + return EVP_DigestFinal(ctx, out, NULL); +#endif +} + +int _libssh2_sha512(const unsigned char *message, size_t len, unsigned char *out) { @@ -2504,6 +3281,7 @@ _libssh2_sha512(const unsigned char *message, size_t len, return 1; /* error */ } +#if LIBSSH2_MD5 || LIBSSH2_MD5_PEM int _libssh2_md5_init(libssh2_md5_ctx *ctx) { @@ -2513,8 +3291,7 @@ _libssh2_md5_init(libssh2_md5_ctx *ctx) * So, just return 0 in FIPS mode */ #if OPENSSL_VERSION_NUMBER >= 0x000907000L && \ - defined(OPENSSL_VERSION_MAJOR) && \ - OPENSSL_VERSION_MAJOR < 3 && \ + !defined(USE_OPENSSL_3) && \ !defined(LIBRESSL_VERSION_NUMBER) if(FIPS_mode()) @@ -2540,6 +3317,31 @@ _libssh2_md5_init(libssh2_md5_ctx *ctx) #endif } +int +_libssh2_md5_update(libssh2_md5_ctx *ctx, + const void *data, size_t len) +{ +#ifdef HAVE_OPAQUE_STRUCTS + return EVP_DigestUpdate(*ctx, data, len); +#else + return EVP_DigestUpdate(ctx, data, len); +#endif +} + +int +_libssh2_md5_final(libssh2_md5_ctx *ctx, + unsigned char *out) +{ +#ifdef HAVE_OPAQUE_STRUCTS + int ret = EVP_DigestFinal(*ctx, out, NULL); + EVP_MD_CTX_free(*ctx); + return ret; +#else + return EVP_DigestFinal(ctx, out, NULL); +#endif +} +#endif + #if LIBSSH2_ECDSA static int @@ -2552,17 +3354,26 @@ gen_publickey_from_ec_evp(LIBSSH2_SESSION *session, EVP_PKEY *pk) { int rc = 0; - EC_KEY *ec = NULL; unsigned char *p; unsigned char *method_buf = NULL; unsigned char *key; + size_t method_buf_len = 0; size_t key_len = 0; unsigned char *octal_value = NULL; size_t octal_len; + libssh2_curve_type type; + +#ifdef USE_OPENSSL_3 + _libssh2_debug((session, + LIBSSH2_TRACE_AUTH, + "Computing public key from EC private key envelope")); + + type = _libssh2_ecdsa_get_curve_type(pk); +#else + EC_KEY *ec = NULL; const EC_POINT *public_key; const EC_GROUP *group; - BN_CTX *bn_ctx; - libssh2_curve_type type; + BN_CTX *bn_ctx = NULL; _libssh2_debug((session, LIBSSH2_TRACE_AUTH, @@ -2581,26 +3392,32 @@ gen_publickey_from_ec_evp(LIBSSH2_SESSION *session, public_key = EC_KEY_get0_public_key(ec); group = EC_KEY_get0_group(ec); type = _libssh2_ecdsa_get_curve_type(ec); +#endif if(is_sk) - *method_len = 34; + method_buf_len = 34; else - *method_len = 19; + method_buf_len = 19; - method_buf = LIBSSH2_ALLOC(session, *method_len); + method_buf = LIBSSH2_ALLOC(session, method_buf_len); if(!method_buf) { return _libssh2_error(session, LIBSSH2_ERROR_ALLOC, "out of memory"); } - if(is_sk) - memcpy(method_buf, "sk-ecdsa-sha2-nistp256@openssh.com", *method_len); - else if(type == LIBSSH2_EC_CURVE_NISTP256) - memcpy(method_buf, "ecdsa-sha2-nistp256", *method_len); - else if(type == LIBSSH2_EC_CURVE_NISTP384) - memcpy(method_buf, "ecdsa-sha2-nistp384", *method_len); - else if(type == LIBSSH2_EC_CURVE_NISTP521) - memcpy(method_buf, "ecdsa-sha2-nistp521", *method_len); + if(is_sk) { + memcpy(method_buf, "sk-ecdsa-sha2-nistp256@openssh.com", + method_buf_len); + } + else if(type == LIBSSH2_EC_CURVE_NISTP256) { + memcpy(method_buf, "ecdsa-sha2-nistp256", method_buf_len); + } + else if(type == LIBSSH2_EC_CURVE_NISTP384) { + memcpy(method_buf, "ecdsa-sha2-nistp384", method_buf_len); + } + else if(type == LIBSSH2_EC_CURVE_NISTP521) { + memcpy(method_buf, "ecdsa-sha2-nistp521", method_buf_len); + } else { _libssh2_debug((session, LIBSSH2_TRACE_ERROR, @@ -2609,6 +3426,12 @@ gen_publickey_from_ec_evp(LIBSSH2_SESSION *session, goto clean_exit; } +#ifdef USE_OPENSSL_3 + octal_len = EC_MAX_POINT_LEN; + octal_value = LIBSSH2_ALLOC(session, octal_len); + EVP_PKEY_get_octet_string_param(pk, OSSL_PKEY_PARAM_PUB_KEY, + octal_value, octal_len, &octal_len); +#else /* get length */ octal_len = EC_POINT_point2oct(group, public_key, POINT_CONVERSION_UNCOMPRESSED, @@ -2630,10 +3453,11 @@ gen_publickey_from_ec_evp(LIBSSH2_SESSION *session, rc = -1; goto clean_exit; } +#endif - /* Key form is: type_len(4) + type(method_len) + domain_len(4) + domain(8) - + pub_key_len(4) + pub_key(~65). */ - key_len = 4 + *method_len + 4 + 8 + 4 + octal_len; + /* Key form is: type_len(4) + type(method_buf_len) + domain_len(4) + + domain(8) + pub_key_len(4) + pub_key(~65). */ + key_len = 4 + method_buf_len + 4 + 8 + 4 + octal_len; key = LIBSSH2_ALLOC(session, key_len); if(!key) { rc = -1; @@ -2644,7 +3468,7 @@ gen_publickey_from_ec_evp(LIBSSH2_SESSION *session, p = key; /* Key type */ - _libssh2_store_str(&p, (const char *)method_buf, *method_len); + _libssh2_store_str(&p, (const char *)method_buf, method_buf_len); /* Name domain */ if(is_sk) { @@ -2657,18 +3481,25 @@ gen_publickey_from_ec_evp(LIBSSH2_SESSION *session, /* Public key */ _libssh2_store_str(&p, (const char *)octal_value, octal_len); - *method = method_buf; - *pubkeydata = key; - *pubkeydata_len = key_len; + *method = method_buf; + if(method_len) { + *method_len = method_buf_len; + } + *pubkeydata = key; + if(pubkeydata_len) { + *pubkeydata_len = key_len; + } clean_exit: +#ifndef USE_OPENSSL_3 if(ec) EC_KEY_free(ec); if(bn_ctx) { BN_CTX_free(bn_ctx); } +#endif if(octal_value) free(octal_value); @@ -2695,8 +3526,16 @@ gen_publickey_from_ecdsa_openssh_priv_data(LIBSSH2_SESSION *session, int rc = 0; size_t curvelen, exponentlen, pointlen; unsigned char *curve, *exponent, *point_buf; - EC_KEY *ec_key = NULL; + libssh2_ecdsa_ctx *ec_key = NULL; + +#ifdef USE_OPENSSL_3 + EVP_PKEY_CTX *fromdata_ctx = NULL; + OSSL_PARAM params[4]; + const char *n = EC_curve_nid2nist(curve_type); + char *group_name = NULL; +#else BIGNUM *bn_exponent; +#endif _libssh2_debug((session, LIBSSH2_TRACE_AUTH, @@ -2721,6 +3560,43 @@ gen_publickey_from_ecdsa_openssh_priv_data(LIBSSH2_SESSION *session, return -1; } +#ifdef USE_OPENSSL_3 + if(!n) + return -1; + + fromdata_ctx = EVP_PKEY_CTX_new_id(EVP_PKEY_EC, NULL); + + if(!fromdata_ctx) + goto fail; + + group_name = OPENSSL_zalloc(strlen(n) + 1); + + if(!group_name) + goto fail; + + memcpy(group_name, n, strlen(n)); + _libssh2_swap_bytes(exponent, (unsigned long)exponentlen); + + params[0] = OSSL_PARAM_construct_utf8_string(OSSL_PKEY_PARAM_GROUP_NAME, + group_name, 0); + + params[1] = OSSL_PARAM_construct_octet_string(OSSL_PKEY_PARAM_PUB_KEY, + point_buf, pointlen); + + params[2] = OSSL_PARAM_construct_BN(OSSL_PKEY_PARAM_PRIV_KEY, exponent, + exponentlen); + + params[3] = OSSL_PARAM_construct_end(); + + if(EVP_PKEY_fromdata_init(fromdata_ctx) <= 0) + goto fail; + + rc = EVP_PKEY_fromdata(fromdata_ctx, &ec_key, EVP_PKEY_KEYPAIR, params); + rc = rc != 1; + + if(group_name) + OPENSSL_clear_free(group_name, strlen(n)); +#else rc = _libssh2_ecdsa_curve_name_with_octal_new(&ec_key, point_buf, pointlen, curve_type); @@ -2741,29 +3617,46 @@ gen_publickey_from_ecdsa_openssh_priv_data(LIBSSH2_SESSION *session, BN_bin2bn(exponent, (int) exponentlen, bn_exponent); rc = (EC_KEY_set_private_key(ec_key, bn_exponent) != 1); +#endif if(rc == 0 && ec_key && pubkeydata && method) { +#ifdef USE_OPENSSL_3 + EVP_PKEY *pk = ec_key; +#else EVP_PKEY *pk = EVP_PKEY_new(); EVP_PKEY_set1_EC_KEY(pk, ec_key); +#endif rc = gen_publickey_from_ec_evp(session, method, method_len, pubkeydata, pubkeydata_len, 0, pk); +#ifndef USE_OPENSSL_3 if(pk) EVP_PKEY_free(pk); +#endif } +#ifdef USE_OPENSSL_3 + if(fromdata_ctx) + EVP_PKEY_CTX_free(fromdata_ctx); +#endif + if(ec_ctx) *ec_ctx = ec_key; else - EC_KEY_free(ec_key); + _libssh2_ecdsa_free(ec_key); return rc; fail: +#ifdef USE_OPENSSL_3 + if(fromdata_ctx) + EVP_PKEY_CTX_free(fromdata_ctx); +#endif + if(ec_key) - EC_KEY_free(ec_key); + _libssh2_ecdsa_free(ec_key); return rc; } @@ -2784,7 +3677,7 @@ gen_publickey_from_sk_ecdsa_openssh_priv_data(LIBSSH2_SESSION *session, int rc = 0; size_t curvelen, pointlen, key_len, app_len; unsigned char *curve, *point_buf, *p, *key, *app; - EC_KEY *ec_key = NULL; + libssh2_ecdsa_ctx *ec_key = NULL; _libssh2_debug((session, LIBSSH2_TRACE_AUTH, @@ -2843,15 +3736,21 @@ gen_publickey_from_sk_ecdsa_openssh_priv_data(LIBSSH2_SESSION *session, } if(rc == 0 && ec_key && pubkeydata && method) { +#ifdef USE_OPENSSL_3 + EVP_PKEY *pk = ec_key; +#else EVP_PKEY *pk = EVP_PKEY_new(); EVP_PKEY_set1_EC_KEY(pk, ec_key); +#endif rc = gen_publickey_from_ec_evp(session, method, method_len, pubkeydata, pubkeydata_len, 1, pk); +#ifndef USE_OPENSSL_3 if(pk) EVP_PKEY_free(pk); +#endif } if(rc == 0 && pubkeydata) { @@ -2886,13 +3785,13 @@ gen_publickey_from_sk_ecdsa_openssh_priv_data(LIBSSH2_SESSION *session, if(ec_ctx) *ec_ctx = ec_key; else - EC_KEY_free(ec_key); + _libssh2_ecdsa_free(ec_key); return rc; fail: if(ec_key) - EC_KEY_free(ec_key); + _libssh2_ecdsa_free(ec_key); if(application && *application) { LIBSSH2_FREE(session, (void *)application); @@ -2954,8 +3853,9 @@ _libssh2_ecdsa_new_openssh_private(libssh2_ecdsa_ctx ** ec_ctx, if(rc == 0) { rc = gen_publickey_from_ecdsa_openssh_priv_data(session, type, - decrypted, NULL, 0, - NULL, 0, ec_ctx); + decrypted, + NULL, NULL, + NULL, NULL, ec_ctx); } else { rc = -1; @@ -3015,8 +3915,8 @@ _libssh2_ecdsa_new_openssh_private_sk(libssh2_ecdsa_ctx ** ec_ctx, if(strcmp("sk-ecdsa-sha2-nistp256@openssh.com", (const char *)buf) == 0) { rc = gen_publickey_from_sk_ecdsa_openssh_priv_data(session, decrypted, - NULL, 0, - NULL, 0, + NULL, NULL, + NULL, NULL, flags, application, key_handle, @@ -3040,12 +3940,18 @@ _libssh2_ecdsa_new_private(libssh2_ecdsa_ctx ** ec_ctx, { int rc; - pem_read_bio_func read_ec = (pem_read_bio_func) &PEM_read_bio_ECPrivateKey; +#if defined(USE_OPENSSL_3) + pem_read_bio_func read_ec = + (pem_read_bio_func) &PEM_read_bio_PrivateKey; +#else + pem_read_bio_func read_ec = + (pem_read_bio_func) &PEM_read_bio_ECPrivateKey; +#endif _libssh2_init_if_needed(); rc = read_private_key_from_file((void **) ec_ctx, read_ec, - filename, passphrase); + filename, passphrase); if(rc) { return _libssh2_ecdsa_new_openssh_private(ec_ctx, session, @@ -3067,12 +3973,18 @@ _libssh2_ecdsa_new_private_sk(libssh2_ecdsa_ctx ** ec_ctx, { int rc; - pem_read_bio_func read_ec = (pem_read_bio_func) &PEM_read_bio_ECPrivateKey; +#if defined(USE_OPENSSL_3) + pem_read_bio_func read_ec = + (pem_read_bio_func) &PEM_read_bio_PrivateKey; +#else + pem_read_bio_func read_ec = + (pem_read_bio_func) &PEM_read_bio_ECPrivateKey; +#endif _libssh2_init_if_needed(); rc = read_private_key_from_file((void **) ec_ctx, read_ec, - filename, passphrase); + filename, passphrase); if(rc) { return _libssh2_ecdsa_new_openssh_private_sk(ec_ctx, @@ -3107,8 +4019,51 @@ _libssh2_ecdsa_create_key(LIBSSH2_SESSION *session, int ret = 1; size_t octal_len = 0; unsigned char octal_value[EC_MAX_POINT_LEN]; + _libssh2_ec_key *private_key = NULL; + +#ifdef USE_OPENSSL_3 + EVP_PKEY_CTX *ctx = EVP_PKEY_CTX_new_id(EVP_PKEY_EC, NULL); + + if(ctx && + EVP_PKEY_keygen_init(ctx) >0 && + EVP_PKEY_CTX_set_ec_paramgen_curve_nid(ctx, curve_type) > 0) { + ret = EVP_PKEY_keygen(ctx, &private_key); + } + + if(ret <= 0) { + goto clean_exit; + } + + if(out_private_key) + *out_private_key = private_key; + + ret = EVP_PKEY_get_octet_string_param(private_key, OSSL_PKEY_PARAM_PUB_KEY, + NULL, 0, &octal_len); + + if(ret <= 0) { + goto clean_exit; + } + + *out_public_key_octal = LIBSSH2_ALLOC(session, octal_len); + + if(!(*out_public_key_octal)) { + ret = -1; + goto clean_exit; + } + + ret = EVP_PKEY_get_octet_string_param(private_key, OSSL_PKEY_PARAM_PUB_KEY, + octal_value, octal_len, &octal_len); + + if(ret <= 0) { + goto clean_exit; + } + + memcpy(*out_public_key_octal, octal_value, octal_len); + + if(out_public_key_octal_len) + *out_public_key_octal_len = octal_len; +#else const EC_POINT *public_key = NULL; - EC_KEY *private_key = NULL; const EC_GROUP *group = NULL; /* create key */ @@ -3153,11 +4108,16 @@ _libssh2_ecdsa_create_key(LIBSSH2_SESSION *session, if(out_public_key_octal_len) *out_public_key_octal_len = octal_len; +#endif /* USE_OPENSSL_3 */ clean_exit: - +#ifdef USE_OPENSSL_3 + if(ctx) + EVP_PKEY_CTX_free(ctx); +#else if(bn_ctx) BN_CTX_free(bn_ctx); +#endif return (ret == 1) ? 0 : -1; } @@ -3170,16 +4130,120 @@ clean_exit: 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) + const unsigned char *server_public_key, + size_t server_public_key_len) { int ret = 0; - int rc; + BN_CTX *bn_ctx = NULL; + +#ifdef USE_OPENSSL_3 + char *group_name = NULL; + size_t group_name_len = 0; + unsigned char *out_shared_key = NULL; + EVP_PKEY *peer_key = NULL, *server_key = NULL; + EVP_PKEY_CTX *key_fromdata_ctx = NULL; + EVP_PKEY_CTX *server_key_ctx = NULL; + OSSL_PARAM params[3]; + + size_t out_len = 0; + + if(!k || !(*k) || server_public_key_len <= 0) + return -1; + + bn_ctx = BN_CTX_new(); + if(!bn_ctx) + goto clean_exit; + + key_fromdata_ctx = EVP_PKEY_CTX_new_id(EVP_PKEY_EC, NULL); + if(!key_fromdata_ctx) + goto clean_exit; + + ret = EVP_PKEY_get_utf8_string_param(private_key, + OSSL_PKEY_PARAM_GROUP_NAME, + NULL, 0, &group_name_len); + + if(ret <= 0) + goto clean_exit; + + group_name_len += 1; + group_name = OPENSSL_zalloc(group_name_len); + + if(!group_name) + goto clean_exit; + + ret = EVP_PKEY_get_utf8_string_param(private_key, + OSSL_PKEY_PARAM_GROUP_NAME, + group_name, group_name_len, + &group_name_len); + + if(ret <= 0) + goto clean_exit; + + out_shared_key = OPENSSL_malloc(server_public_key_len); + + if(!out_shared_key) + goto clean_exit; + + memcpy(out_shared_key, server_public_key, server_public_key_len); + + params[0] = OSSL_PARAM_construct_utf8_string(OSSL_PKEY_PARAM_GROUP_NAME, + group_name, 0); + + params[1] = OSSL_PARAM_construct_octet_string(OSSL_PKEY_PARAM_PUB_KEY, + out_shared_key, + server_public_key_len); + + params[2] = OSSL_PARAM_construct_end(); + + ret = EVP_PKEY_fromdata_init(key_fromdata_ctx); + if(ret <= 0) + goto clean_exit; + + ret = EVP_PKEY_fromdata(key_fromdata_ctx, &peer_key, + EVP_PKEY_PUBLIC_KEY, params); + + if(ret <= 0) + goto clean_exit; + + server_key = private_key; + + if(!peer_key || !server_key) { + goto clean_exit; + } + + server_key_ctx = EVP_PKEY_CTX_new(server_key, NULL); + if(!server_key_ctx) { + goto clean_exit; + } + + ret = EVP_PKEY_derive_init(server_key_ctx); + if(ret <= 0) + goto clean_exit; + + ret = EVP_PKEY_derive_set_peer(server_key_ctx, peer_key); + if(ret <= 0) + goto clean_exit; + + ret = EVP_PKEY_derive(server_key_ctx, NULL, &out_len); + if(ret <= 0) + goto clean_exit; + + ret = EVP_PKEY_derive(server_key_ctx, out_shared_key, &out_len); + + if(ret == 1) { + BN_bin2bn(out_shared_key, (int)out_len, *k); + } + else { + ret = -1; + } +#else + int rc = -1; 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(); + bn_ctx = BN_CTX_new(); if(!bn_ctx) return -1; @@ -3216,9 +4280,19 @@ _libssh2_ecdh_gen_k(_libssh2_bn **k, _libssh2_ec_key *private_key, } BN_bin2bn(secret, (int) secret_len, *k); +#endif clean_exit: +#ifdef USE_OPENSSL_3 + if(group_name) + OPENSSL_clear_free(group_name, group_name_len); + if(out_shared_key) + OPENSSL_clear_free(out_shared_key, server_public_key_len); + + if(server_key_ctx) + EVP_PKEY_CTX_free(server_key_ctx); +#else if(server_public_key_point) EC_POINT_free(server_public_key_point); @@ -3227,8 +4301,13 @@ clean_exit: if(secret) free(secret); +#endif +#ifdef USE_OPENSSL_3 + return ret == 1 ? 0 : -1; +#else return ret; +#endif } @@ -3522,7 +4601,7 @@ _libssh2_pub_priv_keyfile(LIBSSH2_SESSION *session, "file: Unable to open private key file"); } - BIO_reset(bp); + (void)BIO_reset(bp); pk = PEM_read_bio_PrivateKey(bp, NULL, NULL, (void *)passphrase); BIO_free(bp); @@ -3664,10 +4743,8 @@ _libssh2_pub_priv_openssh_keyfilememory(LIBSSH2_SESSION *session, method_len, pubkeydata, pubkeydata_len, - NULL, - NULL, - NULL, - NULL, + NULL, NULL, + NULL, NULL, (libssh2_ed25519_ctx**)key_ctx); } } @@ -3696,16 +4773,15 @@ _libssh2_pub_priv_openssh_keyfilememory(LIBSSH2_SESSION *session, #endif #if LIBSSH2_ECDSA { - libssh2_curve_type type; + libssh2_curve_type type; if(strcmp("sk-ecdsa-sha2-nistp256@openssh.com", (const char *)buf) == 0) { rc = gen_publickey_from_sk_ecdsa_openssh_priv_data(session, decrypted, method, method_len, pubkeydata, pubkeydata_len, - NULL, NULL, NULL, - NULL, + NULL, NULL, (libssh2_ecdsa_ctx**)key_ctx); } else if(_libssh2_ecdsa_curve_type_from_name((const char *)buf, &type) @@ -3840,19 +4916,6 @@ _libssh2_sk_pub_openssh_keyfilememory(LIBSSH2_SESSION *session, 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); -} - #if OPENSSL_VERSION_NUMBER >= 0x30000000L #define HAVE_SSLERROR_BAD_DECRYPT #endif @@ -3888,7 +4951,7 @@ _libssh2_pub_priv_keyfilememory(LIBSSH2_SESSION *session, return _libssh2_error(session, LIBSSH2_ERROR_ALLOC, "Unable to allocate memory when" "computing public key"); - BIO_reset(bp); + (void)BIO_reset(bp); pk = PEM_read_bio_PrivateKey(bp, NULL, NULL, (void *)passphrase); #ifdef HAVE_SSLERROR_BAD_DECRYPT sslError = ERR_get_error(); @@ -3932,8 +4995,8 @@ _libssh2_pub_priv_keyfilememory(LIBSSH2_SESSION *session, switch(pktype) { #if LIBSSH2_ED25519 case EVP_PKEY_ED25519: - st = gen_publickey_from_ed_evp( - session, method, method_len, pubkeydata, pubkeydata_len, pk); + st = gen_publickey_from_ed_evp(session, method, method_len, + pubkeydata, pubkeydata_len, pk); break; #endif /* LIBSSH2_ED25519 */ #if LIBSSH2_RSA @@ -3951,8 +5014,7 @@ _libssh2_pub_priv_keyfilememory(LIBSSH2_SESSION *session, #if LIBSSH2_ECDSA case EVP_PKEY_EC: st = gen_publickey_from_ec_evp(session, method, method_len, - pubkeydata, pubkeydata_len, - 0, pk); + pubkeydata, pubkeydata_len, 0, pk); break; #endif /* LIBSSH2_ECDSA */ default: @@ -4000,7 +5062,7 @@ _libssh2_sk_pub_keyfilememory(LIBSSH2_SESSION *session, return _libssh2_error(session, LIBSSH2_ERROR_ALLOC, "Unable to allocate memory when" "computing public key"); - BIO_reset(bp); + (void)BIO_reset(bp); pk = PEM_read_bio_PrivateKey(bp, NULL, NULL, (void *)passphrase); BIO_free(bp); @@ -4074,7 +5136,11 @@ _libssh2_supported_key_sign_algorithms(LIBSSH2_SESSION *session, #if LIBSSH2_RSA_SHA2 if(key_method_len == 7 && memcmp(key_method, "ssh-rsa", key_method_len) == 0) { - return "rsa-sha2-512,rsa-sha2-256,ssh-rsa"; + return "rsa-sha2-512,rsa-sha2-256" +#if LIBSSH2_RSA_SHA1 + ",ssh-rsa" +#endif + ; } #endif diff --git a/libs/libssh2/src/openssl.h b/libs/libssh2/src/openssl.h index efd9a007f6..e44c87498c 100644 --- a/libs/libssh2/src/openssl.h +++ b/libs/libssh2/src/openssl.h @@ -1,5 +1,5 @@ -#ifndef __LIBSSH2_OPENSSL_H -#define __LIBSSH2_OPENSSL_H +#ifndef LIBSSH2_OPENSSL_H +#define LIBSSH2_OPENSSL_H /* Copyright (C) Simon Josefsson * Copyright (C) The Written Word, Inc. * All rights reserved. @@ -78,6 +78,7 @@ #endif /* LIBSSH2_WOLFSSL */ +#include <openssl/opensslconf.h> #include <openssl/sha.h> #include <openssl/rsa.h> #ifndef OPENSSL_NO_ENGINE @@ -96,9 +97,15 @@ #include <openssl/pem.h> #include <openssl/rand.h> +#if OPENSSL_VERSION_NUMBER >= 0x30000000L +#define USE_OPENSSL_3 1 +#include <openssl/core_names.h> +#endif + #if (OPENSSL_VERSION_NUMBER >= 0x10100000L && \ !defined(LIBRESSL_VERSION_NUMBER)) || defined(LIBSSH2_WOLFSSL) || \ - LIBRESSL_VERSION_NUMBER >= 0x3050000fL + (defined(LIBRESSL_VERSION_NUMBER) && \ + LIBRESSL_VERSION_NUMBER >= 0x3050000fL) /* For wolfSSL, whether the structs are truly opaque or not, it's best to not * rely on their internal data members being exposed publicly. */ # define HAVE_OPAQUE_STRUCTS 1 @@ -192,6 +199,8 @@ # define LIBSSH2_3DES 1 #endif +#include "crypto_config.h" + #define EC_MAX_POINT_LEN ((528 * 2 / 8) + 1) #define _libssh2_random(buf, len) \ @@ -207,19 +216,15 @@ /* 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_update(libssh2_sha1_ctx *ctx, + const void *data, size_t len); +int _libssh2_sha1_final(libssh2_sha1_ctx *ctx, unsigned char *out); int _libssh2_sha1(const unsigned char *message, size_t len, unsigned char *out); +#define libssh2_sha1_init(x) _libssh2_sha1_init(x) +#define libssh2_sha1_update(ctx, data, len) \ + _libssh2_sha1_update(&(ctx), data, len) +#define libssh2_sha1_final(ctx, out) _libssh2_sha1_final(&(ctx), out) #define libssh2_sha1(x,y,z) _libssh2_sha1(x,y,z) #ifdef HAVE_OPAQUE_STRUCTS @@ -230,20 +235,15 @@ int _libssh2_sha1(const unsigned char *message, size_t len, /* 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_update(libssh2_sha256_ctx *ctx, + const void *data, size_t len); +int _libssh2_sha256_final(libssh2_sha256_ctx *ctx, unsigned char *out); int _libssh2_sha256(const unsigned char *message, size_t len, unsigned char *out); +#define libssh2_sha256_init(x) _libssh2_sha256_init(x) +#define libssh2_sha256_update(ctx, data, len) \ + _libssh2_sha256_update(&(ctx), data, len) +#define libssh2_sha256_final(ctx, out) _libssh2_sha256_final(&(ctx), out) #define libssh2_sha256(x,y,z) _libssh2_sha256(x,y,z) #ifdef HAVE_OPAQUE_STRUCTS @@ -254,20 +254,15 @@ int _libssh2_sha256(const unsigned char *message, size_t len, /* 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_update(libssh2_sha384_ctx *ctx, + const void *data, size_t len); +int _libssh2_sha384_final(libssh2_sha384_ctx *ctx, unsigned char *out); int _libssh2_sha384(const unsigned char *message, size_t len, unsigned char *out); +#define libssh2_sha384_init(x) _libssh2_sha384_init(x) +#define libssh2_sha384_update(ctx, data, len) \ + _libssh2_sha384_update(&(ctx), data, len) +#define libssh2_sha384_final(ctx, out) _libssh2_sha384_final(&(ctx), out) #define libssh2_sha384(x,y,z) _libssh2_sha384(x,y,z) #ifdef HAVE_OPAQUE_STRUCTS @@ -278,22 +273,18 @@ int _libssh2_sha384(const unsigned char *message, size_t len, /* 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_update(libssh2_sha512_ctx *ctx, + const void *data, size_t len); +int _libssh2_sha512_final(libssh2_sha512_ctx *ctx, unsigned char *out); int _libssh2_sha512(const unsigned char *message, size_t len, unsigned char *out); +#define libssh2_sha512_init(x) _libssh2_sha512_init(x) +#define libssh2_sha512_update(ctx, data, len) \ + _libssh2_sha512_update(&(ctx), data, len) +#define libssh2_sha512_final(ctx, out) _libssh2_sha512_final(&(ctx), out) #define libssh2_sha512(x,y,z) _libssh2_sha512(x,y,z) +#if LIBSSH2_MD5 || LIBSSH2_MD5_PEM #ifdef HAVE_OPAQUE_STRUCTS #define libssh2_md5_ctx EVP_MD_CTX * #else @@ -302,62 +293,22 @@ int _libssh2_sha512(const unsigned char *message, size_t len, /* returns 0 in case of failure */ int _libssh2_md5_init(libssh2_md5_ctx *ctx); +int _libssh2_md5_update(libssh2_md5_ctx *ctx, + const void *data, size_t len); +int _libssh2_md5_final(libssh2_md5_ctx *ctx, unsigned char *out); #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_md5_update(ctx, data, len) \ + _libssh2_md5_update(&(ctx), data, len) +#define libssh2_md5_final(ctx, out) _libssh2_md5_final(&(ctx), out) +#endif /* LIBSSH2_MD5 || LIBSSH2_MD5_PEM */ + +#ifdef USE_OPENSSL_3 +#define libssh2_hmac_ctx EVP_MAC_CTX * +#elif defined(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, (int)keylen, EVP_sha1(), NULL) -#define libssh2_hmac_md5_init(ctx, key, keylen) \ - HMAC_Init_ex(*(ctx), key, (int)keylen, EVP_md5(), NULL) -#define libssh2_hmac_ripemd160_init(ctx, key, keylen) \ - HMAC_Init_ex(*(ctx), key, (int)keylen, EVP_ripemd160(), NULL) -#define libssh2_hmac_sha256_init(ctx, key, keylen) \ - HMAC_Init_ex(*(ctx), key, (int)keylen, EVP_sha256(), NULL) -#define libssh2_hmac_sha512_init(ctx, key, keylen) \ - HMAC_Init_ex(*(ctx), key, (int)keylen, EVP_sha512(), NULL) - -#ifdef LIBSSH2_WOLFSSL -/* FIXME: upstream bug as of v5.6.0: datalen is int instead of size_t */ -#define libssh2_hmac_update(ctx, data, datalen) \ - HMAC_Update(ctx, data, (int)datalen) -#else -#define libssh2_hmac_update(ctx, data, datalen) \ - HMAC_Update(ctx, data, datalen) -#endif /* LIBSSH2_WOLFSSL */ -#define libssh2_hmac_final(ctx, data) HMAC_Final(ctx, data, NULL) -#define libssh2_hmac_cleanup(ctx) HMAC_CTX_free(*(ctx)) -#else +#else /* !HAVE_OPAQUE_STRUCTS */ #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, (int)keylen, EVP_sha1(), NULL) -#define libssh2_hmac_md5_init(ctx, key, keylen) \ - HMAC_Init_ex(ctx, key, (int)keylen, EVP_md5(), NULL) -#define libssh2_hmac_ripemd160_init(ctx, key, keylen) \ - HMAC_Init_ex(ctx, key, (int)keylen, EVP_ripemd160(), NULL) -#define libssh2_hmac_sha256_init(ctx, key, keylen) \ - HMAC_Init_ex(ctx, key, (int)keylen, EVP_sha256(), NULL) -#define libssh2_hmac_sha512_init(ctx, key, keylen) \ - HMAC_Init_ex(ctx, key, (int)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 +#endif /* USE_OPENSSL_3 */ extern void _libssh2_openssl_crypto_init(void); extern void _libssh2_openssl_crypto_exit(void); @@ -365,21 +316,40 @@ extern void _libssh2_openssl_crypto_exit(void); #define libssh2_crypto_exit() _libssh2_openssl_crypto_exit() #if LIBSSH2_RSA -#define libssh2_rsa_ctx RSA +#ifdef USE_OPENSSL_3 +#define libssh2_rsa_ctx EVP_PKEY +#define _libssh2_rsa_free(rsactx) EVP_PKEY_free(rsactx) +#else +#define libssh2_rsa_ctx RSA #define _libssh2_rsa_free(rsactx) RSA_free(rsactx) #endif +#endif /* LIBSSH2_RSA */ + #if LIBSSH2_DSA -#define libssh2_dsa_ctx DSA +#ifdef USE_OPENSSL_3 +#define libssh2_dsa_ctx EVP_PKEY +#define _libssh2_dsa_free(rsactx) EVP_PKEY_free(rsactx) +#else +#define libssh2_dsa_ctx DSA #define _libssh2_dsa_free(dsactx) DSA_free(dsactx) #endif +#endif /* LIBSSH2_DSA */ + #if LIBSSH2_ECDSA + +#ifdef USE_OPENSSL_3 +#define libssh2_ecdsa_ctx EVP_PKEY +#define _libssh2_ecdsa_free(ecdsactx) EVP_PKEY_free(ecdsactx) +#define _libssh2_ec_key EVP_PKEY +#else #define libssh2_ecdsa_ctx EC_KEY #define _libssh2_ecdsa_free(ecdsactx) EC_KEY_free(ecdsactx) #define _libssh2_ec_key EC_KEY +#endif typedef enum { LIBSSH2_EC_CURVE_NISTP256 = NID_X9_62_prime256v1, @@ -387,15 +357,14 @@ typedef enum { LIBSSH2_EC_CURVE_NISTP521 = NID_secp521r1 } libssh2_curve_type; -#else +#else /* !LIBSSH2_ECDSA */ #define _libssh2_ec_key void #endif /* LIBSSH2_ECDSA */ #if LIBSSH2_ED25519 #define libssh2_ed25519_ctx EVP_PKEY - #define _libssh2_ed25519_free(ctx) EVP_PKEY_free(ctx) -#endif /* ED25519 */ +#endif /* LIBSSH2_ED25519 */ #define _libssh2_cipher_type(name) const EVP_CIPHER *(*name)(void) #ifdef HAVE_OPAQUE_STRUCTS @@ -468,4 +437,4 @@ 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); -#endif /* __LIBSSH2_OPENSSL_H */ +#endif /* LIBSSH2_OPENSSL_H */ diff --git a/libs/libssh2/src/packet.c b/libs/libssh2/src/packet.c index e3ccf814d4..6da14e9fa1 100644 --- a/libs/libssh2/src/packet.c +++ b/libs/libssh2/src/packet.c @@ -71,14 +71,14 @@ packet_queue_listener(LIBSSH2_SESSION * session, unsigned char *data, * Look for a matching listener */ /* 17 = packet_type(1) + channel(4) + reason(4) + descr(4) + lang(4) */ - size_t packet_len = 17 + (sizeof(FwdNotReq) - 1); + size_t packet_len = 17 + strlen(FwdNotReq); unsigned char *p; LIBSSH2_LISTENER *listn = _libssh2_list_first(&session->listeners); char failure_code = SSH_OPEN_ADMINISTRATIVELY_PROHIBITED; int rc; if(listen_state->state == libssh2_NB_state_idle) { - size_t offset = (sizeof("forwarded-tcpip") - 1) + 5; + size_t offset = strlen("forwarded-tcpip") + 5; size_t temp_len = 0; struct string_buf buf; buf.data = data; @@ -126,7 +126,7 @@ packet_queue_listener(LIBSSH2_SESSION * session, unsigned char *data, } _libssh2_debug((session, LIBSSH2_TRACE_CONN, - "Remote received connection from %s:%ld to %s:%ld", + "Remote received connection from %s:%u to %s:%u", listen_state->shost, listen_state->sport, listen_state->host, listen_state->port)); @@ -137,8 +137,8 @@ packet_queue_listener(LIBSSH2_SESSION * session, unsigned char *data, 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)) { + (memcmp(listn->host, listen_state->host, + listen_state->host_len) == 0)) { /* This is our listener */ LIBSSH2_CHANNEL *channel = NULL; listen_state->channel = NULL; @@ -166,7 +166,7 @@ packet_queue_listener(LIBSSH2_SESSION * session, unsigned char *data, listen_state->channel = channel; channel->session = session; - channel->channel_type_len = sizeof("forwarded-tcpip") - 1; + channel->channel_type_len = strlen("forwarded-tcpip"); channel->channel_type = LIBSSH2_ALLOC(session, channel-> channel_type_len + @@ -199,8 +199,8 @@ packet_queue_listener(LIBSSH2_SESSION * session, unsigned char *data, 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", + "Connection queued: channel %u/%u " + "win %u/%u packet %u/%u", channel->local.id, channel->remote.id, channel->local.window_size, channel->remote.window_size, @@ -253,7 +253,7 @@ packet_queue_listener(LIBSSH2_SESSION * session, unsigned char *data, *(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_store_str(&p, FwdNotReq, strlen(FwdNotReq)); _libssh2_htonu32(p, 0); rc = _libssh2_transport_send(session, listen_state->packet, @@ -282,14 +282,14 @@ packet_x11_open(LIBSSH2_SESSION * session, unsigned char *data, { int failure_code = SSH_OPEN_CONNECT_FAILED; /* 17 = packet_type(1) + channel(4) + reason(4) + descr(4) + lang(4) */ - size_t packet_len = 17 + (sizeof(X11FwdUnAvil) - 1); + size_t packet_len = 17 + strlen(X11FwdUnAvil); unsigned char *p; LIBSSH2_CHANNEL *channel = x11open_state->channel; int rc; if(x11open_state->state == libssh2_NB_state_idle) { - size_t offset = (sizeof("x11") - 1) + 5; + size_t offset = strlen("x11") + 5; size_t temp_len = 0; struct string_buf buf; buf.data = data; @@ -339,7 +339,7 @@ packet_x11_open(LIBSSH2_SESSION * session, unsigned char *data, } _libssh2_debug((session, LIBSSH2_TRACE_CONN, - "X11 Connection Received from %s:%ld on channel %lu", + "X11 Connection Received from %s:%u on channel %u", x11open_state->shost, x11open_state->sport, x11open_state->sender_channel)); @@ -357,7 +357,7 @@ packet_x11_open(LIBSSH2_SESSION * session, unsigned char *data, } channel->session = session; - channel->channel_type_len = sizeof("x11") - 1; + channel->channel_type_len = strlen("x11"); channel->channel_type = LIBSSH2_ALLOC(session, channel->channel_type_len + 1); @@ -384,8 +384,8 @@ packet_x11_open(LIBSSH2_SESSION * session, unsigned char *data, 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", + "X11 Connection established: channel %u/%u " + "win %u/%u packet %u/%u", channel->local.id, channel->remote.id, channel->local.window_size, channel->remote.window_size, @@ -436,7 +436,7 @@ x11_exit: *(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_store_str(&p, X11FwdUnAvil, strlen(X11FwdUnAvil)); _libssh2_htonu32(p, 0); rc = _libssh2_transport_send(session, x11open_state->packet, packet_len, @@ -464,23 +464,40 @@ packet_authagent_open(LIBSSH2_SESSION * session, { int failure_code = SSH_OPEN_CONNECT_FAILED; /* 17 = packet_type(1) + channel(4) + reason(4) + descr(4) + lang(4) */ - size_t packet_len = 17 + (sizeof(X11FwdUnAvil) - 1); + size_t packet_len = 17 + strlen(X11FwdUnAvil); unsigned char *p; LIBSSH2_CHANNEL *channel = authagent_state->channel; int rc; + struct string_buf buf; + size_t offset = strlen("auth-agent@openssh.org") + 5; - (void)datalen; + buf.data = data; + buf.dataptr = buf.data; + buf.len = datalen; + + buf.dataptr += offset; + + if(datalen < offset) { + return _libssh2_error(session, LIBSSH2_ERROR_OUT_OF_BOUNDARY, + "Unexpected packet size"); + } if(authagent_state->state == libssh2_NB_state_idle) { - unsigned char *s = data + (sizeof("auth-agent@openssh.org") - 1) + 5; - authagent_state->sender_channel = _libssh2_ntohu32(s); - s += 4; - authagent_state->initial_window_size = _libssh2_ntohu32(s); - s += 4; - authagent_state->packet_size = _libssh2_ntohu32(s); + if(_libssh2_get_u32(&buf, &(authagent_state->sender_channel))) { + return _libssh2_error(session, LIBSSH2_ERROR_BUFFER_TOO_SMALL, + "Data too short extracting channel"); + } + if(_libssh2_get_u32(&buf, &(authagent_state->initial_window_size))) { + return _libssh2_error(session, LIBSSH2_ERROR_BUFFER_TOO_SMALL, + "Data too short extracting window size"); + } + if(_libssh2_get_u32(&buf, &(authagent_state->packet_size))) { + return _libssh2_error(session, LIBSSH2_ERROR_BUFFER_TOO_SMALL, + "Data too short extracting packet"); + } _libssh2_debug((session, LIBSSH2_TRACE_CONN, - "Auth Agent Connection Received on channel %lu", + "Auth Agent Connection Received on channel %u", authagent_state->sender_channel)); authagent_state->state = libssh2_NB_state_allocated; @@ -500,7 +517,7 @@ packet_authagent_open(LIBSSH2_SESSION * session, memset(channel, 0, sizeof(LIBSSH2_CHANNEL)); channel->session = session; - channel->channel_type_len = sizeof("auth agent") - 1; + channel->channel_type_len = strlen("auth agent"); channel->channel_type = LIBSSH2_ALLOC(session, channel->channel_type_len + 1); @@ -528,7 +545,7 @@ packet_authagent_open(LIBSSH2_SESSION * session, _libssh2_debug((session, LIBSSH2_TRACE_CONN, "Auth Agent Connection established: channel " - "%lu/%lu win %lu/%lu packet %lu/%lu", + "%u/%u win %u/%u packet %u/%u", channel->local.id, channel->remote.id, channel->local.window_size, channel->remote.window_size, @@ -584,7 +601,7 @@ authagent_exit: *(p++) = SSH_MSG_CHANNEL_OPEN_FAILURE; _libssh2_store_u32(&p, authagent_state->sender_channel); _libssh2_store_u32(&p, failure_code); - _libssh2_store_str(&p, AuthAgentUnavail, sizeof(AuthAgentUnavail) - 1); + _libssh2_store_str(&p, AuthAgentUnavail, strlen(AuthAgentUnavail)); _libssh2_htonu32(p, 0); rc = _libssh2_transport_send(session, authagent_state->packet, packet_len, @@ -607,14 +624,13 @@ authagent_exit: * 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. + * will be freed unless return the 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) + size_t datalen, int macstate, uint32_t seq) { int rc = 0; unsigned char *message = NULL; @@ -628,8 +644,8 @@ _libssh2_packet_add(LIBSSH2_SESSION * session, unsigned char *data, 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)); + "Packet type %u received, length=%ld", + (unsigned int) msg, (long) datalen)); if((macstate == LIBSSH2_MAC_INVALID) && (!session->macerror || @@ -659,6 +675,70 @@ _libssh2_packet_add(LIBSSH2_SESSION * session, unsigned char *data, break; } + if(session->state & LIBSSH2_STATE_INITIAL_KEX) { + if(msg == SSH_MSG_KEXINIT) { + if(!session->kex_strict) { + if(datalen < 17) { + LIBSSH2_FREE(session, data); + session->packAdd_state = libssh2_NB_state_idle; + return _libssh2_error(session, + LIBSSH2_ERROR_BUFFER_TOO_SMALL, + "Data too short extracting kex"); + } + else { + const unsigned char *strict = + (unsigned char *)"kex-strict-s-v00@openssh.com"; + struct string_buf buf; + unsigned char *algs = NULL; + size_t algs_len = 0; + + buf.data = (unsigned char *)data; + buf.dataptr = buf.data; + buf.len = datalen; + buf.dataptr += 17; /* advance past type and cookie */ + + if(_libssh2_get_string(&buf, &algs, &algs_len)) { + LIBSSH2_FREE(session, data); + session->packAdd_state = libssh2_NB_state_idle; + return _libssh2_error(session, + LIBSSH2_ERROR_BUFFER_TOO_SMALL, + "Algs too short"); + } + + if(algs_len == 0 || + _libssh2_kex_agree_instr(algs, algs_len, strict, 28)) { + session->kex_strict = 1; + } + } + } + + if(session->kex_strict && seq) { + LIBSSH2_FREE(session, data); + session->socket_state = LIBSSH2_SOCKET_DISCONNECTED; + session->packAdd_state = libssh2_NB_state_idle; + libssh2_session_disconnect(session, "strict KEX violation: " + "KEXINIT was not the first packet"); + + return _libssh2_error(session, LIBSSH2_ERROR_SOCKET_DISCONNECT, + "strict KEX violation: " + "KEXINIT was not the first packet"); + } + } + + if(session->kex_strict && session->fullpacket_required_type && + session->fullpacket_required_type != msg) { + LIBSSH2_FREE(session, data); + session->socket_state = LIBSSH2_SOCKET_DISCONNECTED; + session->packAdd_state = libssh2_NB_state_idle; + libssh2_session_disconnect(session, "strict KEX violation: " + "unexpected packet type"); + + return _libssh2_error(session, LIBSSH2_ERROR_SOCKET_DISCONNECT, + "strict KEX violation: " + "unexpected packet type"); + } + } + if(session->packAdd_state == libssh2_NB_state_allocated) { /* A couple exceptions to the packet adding rule: */ switch(msg) { @@ -795,7 +875,8 @@ _libssh2_packet_add(LIBSSH2_SESSION * session, unsigned char *data, _libssh2_debug((session, LIBSSH2_TRACE_KEX, "Server to Client extension %.*s: %.*s", - name_len, name, value_len, value)); + (int)name_len, name, + (int)value_len, value)); } if(name_len == 15 && @@ -843,7 +924,7 @@ _libssh2_packet_add(LIBSSH2_SESSION * session, unsigned char *data, _libssh2_debug((session, LIBSSH2_TRACE_CONN, "Received global request type %.*s (wr %X)", - len, data + 5, want_reply)); + (int)len, data + 5, want_reply)); } @@ -872,7 +953,7 @@ libssh2_packet_add_jump_point5: /* streamid(4) */ data_head += 4; - /* fall-through */ + LIBSSH2_FALLTHROUGH(); /* byte SSH_MSG_CHANNEL_DATA @@ -903,8 +984,8 @@ libssh2_packet_add_jump_point5: stream_id = _libssh2_ntohu32(data + 5); _libssh2_debug((session, LIBSSH2_TRACE_CONN, - "%d bytes packet_add() for %lu/%lu/%lu", - (int) (datalen - data_head), + "%ld bytes packet_add() for %u/%u/%u", + (long) (datalen - data_head), channelp->local.id, channelp->remote.id, stream_id)); @@ -917,8 +998,8 @@ libssh2_packet_add_jump_point5: LIBSSH2_FREE(session, data); _libssh2_debug((session, LIBSSH2_TRACE_CONN, - "Ignoring extended data and refunding %d bytes", - (int) (datalen - 13))); + "Ignoring extended data and refunding %ld bytes", + (long) (datalen - 13))); if(channelp->read_avail + datalen - data_head >= channelp->remote.window_size) datalen = channelp->remote.window_size - @@ -927,11 +1008,11 @@ libssh2_packet_add_jump_point5: channelp->remote.window_size -= (uint32_t)(datalen - data_head); _libssh2_debug((session, LIBSSH2_TRACE_CONN, - "shrinking window size by %lu bytes to %lu, " - "read_avail %lu", - datalen - data_head, + "shrinking window size by %ld bytes to %u, " + "read_avail %ld", + (long) (datalen - data_head), channelp->remote.window_size, - channelp->read_avail)); + (long) channelp->read_avail)); session->packAdd_channelp = channelp; @@ -993,10 +1074,10 @@ libssh2_packet_add_jump_point1: channelp->read_avail += datalen - data_head; _libssh2_debug((session, LIBSSH2_TRACE_CONN, - "increasing read_avail by %lu bytes to %lu/%lu", + "increasing read_avail by %ld bytes to %ld/%u", (long)(datalen - data_head), (long)channelp->read_avail, - (long)channelp->remote.window_size)); + channelp->remote.window_size)); break; @@ -1016,7 +1097,7 @@ libssh2_packet_add_jump_point1: else { _libssh2_debug((session, LIBSSH2_TRACE_CONN, - "EOF received for channel %lu/%lu", + "EOF received for channel %u/%u", channelp->local.id, channelp->remote.id)); channelp->remote.eof = 1; @@ -1044,43 +1125,45 @@ libssh2_packet_add_jump_point1: _libssh2_debug((session, LIBSSH2_TRACE_CONN, - "Channel %d received request type %.*s (wr %X)", - channel, len, data + 9, want_reply)); + "Channel %u received request type %.*s (wr %X)", + channel, (int)len, data + 9, want_reply)); - if(len == sizeof("exit-status") - 1 - && (sizeof("exit-status") - 1 + 9) <= datalen + if(len == strlen("exit-status") + && (strlen("exit-status") + 9) <= datalen && !memcmp("exit-status", data + 9, - sizeof("exit-status") - 1)) { + strlen("exit-status"))) { /* 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) { + if(channelp && (strlen("exit-status") + 14) <= datalen) { channelp->exit_status = - _libssh2_ntohu32(data + 9 + sizeof("exit-status")); + _libssh2_ntohu32(data + 10 + + strlen("exit-status")); _libssh2_debug((session, LIBSSH2_TRACE_CONN, - "Exit status %lu received for " - "channel %lu/%lu", + "Exit status %d received for " + "channel %u/%u", channelp->exit_status, channelp->local.id, channelp->remote.id)); } } - else if(len == sizeof("exit-signal") - 1 - && (sizeof("exit-signal") - 1 + 9) <= datalen + else if(len == strlen("exit-signal") + && (strlen("exit-signal") + 9) <= datalen && !memcmp("exit-signal", data + 9, - sizeof("exit-signal") - 1)) { + strlen("exit-signal"))) { /* command terminated due to signal */ if(datalen >= 20) channelp = _libssh2_channel_locate(session, channel); - if(channelp && (sizeof("exit-signal") + 13) <= datalen) { + if(channelp && (strlen("exit-signal") + 14) <= datalen) { /* set signal name (without SIG prefix) */ uint32_t namelen = - _libssh2_ntohu32(data + 9 + sizeof("exit-signal")); + _libssh2_ntohu32(data + 10 + + strlen("exit-signal")); if(namelen <= UINT_MAX - 1) { channelp->exit_signal = @@ -1093,15 +1176,15 @@ libssh2_packet_add_jump_point1: if(!channelp->exit_signal) rc = _libssh2_error(session, LIBSSH2_ERROR_ALLOC, "memory for signal name"); - else if((sizeof("exit-signal") + 13 + namelen <= + else if((strlen("exit-signal") + 14 + namelen <= datalen)) { memcpy(channelp->exit_signal, - data + 13 + sizeof("exit-signal"), namelen); + data + 14 + strlen("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", + "channel %u/%u", channelp->exit_signal, channelp->local.id, channelp->remote.id)); @@ -1142,7 +1225,7 @@ libssh2_packet_add_jump_point4: return 0; } _libssh2_debug((session, LIBSSH2_TRACE_CONN, - "Close received for channel %lu/%lu", + "Close received for channel %u/%u", channelp->local.id, channelp->remote.id)); @@ -1164,12 +1247,12 @@ libssh2_packet_add_jump_point4: case SSH_MSG_CHANNEL_OPEN: if(datalen < 17) ; - else if((datalen >= (sizeof("forwarded-tcpip") + 4)) && - ((sizeof("forwarded-tcpip") - 1) == + else if((datalen >= (strlen("forwarded-tcpip") + 5)) && + (strlen("forwarded-tcpip") == _libssh2_ntohu32(data + 1)) && (memcmp(data + 5, "forwarded-tcpip", - sizeof("forwarded-tcpip") - 1) == 0)) { + strlen("forwarded-tcpip")) == 0)) { /* init the state struct */ memset(&session->packAdd_Qlstn_state, 0, @@ -1180,9 +1263,9 @@ libssh2_packet_add_jump_point2: 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)) { + else if((datalen >= (strlen("x11") + 5)) && + ((strlen("x11")) == _libssh2_ntohu32(data + 1)) && + (memcmp(data + 5, "x11", strlen("x11")) == 0)) { /* init the state struct */ memset(&session->packAdd_x11open_state, 0, @@ -1193,11 +1276,11 @@ libssh2_packet_add_jump_point3: rc = packet_x11_open(session, data, datalen, &session->packAdd_x11open_state); } - else if((datalen >= (sizeof("auth-agent@openssh.com") + 4)) && - ((sizeof("auth-agent@openssh.com") - 1) == + else if((datalen >= (strlen("auth-agent@openssh.com") + 5)) && + (strlen("auth-agent@openssh.com") == _libssh2_ntohu32(data + 1)) && (memcmp(data + 5, "auth-agent@openssh.com", - sizeof("auth-agent@openssh.com") - 1) == 0)) { + strlen("auth-agent@openssh.com")) == 0)) { /* init the state struct */ memset(&session->packAdd_authagent_state, 0, @@ -1232,8 +1315,8 @@ libssh2_packet_add_jump_authagent: channelp->local.window_size += bytestoadd; _libssh2_debug((session, LIBSSH2_TRACE_CONN, - "Window adjust for channel %lu/%lu, " - "adding %lu bytes, new window_size=%lu", + "Window adjust for channel %u/%u, " + "adding %u bytes, new window_size=%u", channelp->local.id, channelp->remote.id, bytestoadd, @@ -1325,7 +1408,8 @@ _libssh2_packet_ask(LIBSSH2_SESSION * session, unsigned char packet_type, LIBSSH2_PACKET *packet = _libssh2_list_first(&session->packets); _libssh2_debug((session, LIBSSH2_TRACE_TRANS, - "Looking for packet of type: %d", (int) packet_type)); + "Looking for packet of type: %u", + (unsigned int)packet_type)); while(packet) { if(packet->data[0] == packet_type @@ -1343,6 +1427,15 @@ _libssh2_packet_ask(LIBSSH2_SESSION * session, unsigned char packet_type, return 0; } + else if(session->kex_strict && + (session->state & LIBSSH2_STATE_INITIAL_KEX)) { + libssh2_session_disconnect(session, "strict KEX violation: " + "unexpected packet type"); + + return _libssh2_error(session, LIBSSH2_ERROR_SOCKET_DISCONNECT, + "strict KEX violation: " + "unexpected packet type"); + } packet = _libssh2_list_next(&packet->node); } return -1; @@ -1404,7 +1497,10 @@ _libssh2_packet_require(LIBSSH2_SESSION * session, unsigned char packet_type, } while(session->socket_state == LIBSSH2_SOCKET_CONNECTED) { - int ret = _libssh2_transport_read(session); + int ret; + session->fullpacket_required_type = packet_type; + ret = _libssh2_transport_read(session); + session->fullpacket_required_type = 0; if(ret == LIBSSH2_ERROR_EAGAIN) return ret; else if(ret < 0) { diff --git a/libs/libssh2/src/packet.h b/libs/libssh2/src/packet.h index 55428d0651..955351e5f6 100644 --- a/libs/libssh2/src/packet.h +++ b/libs/libssh2/src/packet.h @@ -1,5 +1,5 @@ -#ifndef __LIBSSH2_PACKET_H -#define __LIBSSH2_PACKET_H +#ifndef LIBSSH2_PACKET_H +#define LIBSSH2_PACKET_H /* * Copyright (C) Daniel Stenberg * All rights reserved. @@ -72,6 +72,6 @@ int _libssh2_packet_burn(LIBSSH2_SESSION * session, 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); + size_t datalen, int macstate, uint32_t seq); -#endif /* __LIBSSH2_PACKET_H */ +#endif /* LIBSSH2_PACKET_H */ diff --git a/libs/libssh2/src/pem.c b/libs/libssh2/src/pem.c index 912498c5d3..c658896809 100644 --- a/libs/libssh2/src/pem.c +++ b/libs/libssh2/src/pem.c @@ -106,12 +106,6 @@ static unsigned char hex_decode(char digit) ((digit >= 'A') ? (0xA + (digit - 'A')) : (digit - '0')); } -/* Hack to fix builds with crypto backends with MD5 support disabled. - FIXME: Honor our LIBSSH2_MD5 macro for MD5-dependent logic. */ -#ifdef OPENSSL_NO_MD5 -#define MD5_DIGEST_LENGTH 16 -#endif - int _libssh2_pem_parse(LIBSSH2_SESSION * session, const char *headerbegin, @@ -215,6 +209,7 @@ _libssh2_pem_parse(LIBSSH2_SESSION * session, } if(method) { +#if LIBSSH2_MD5_PEM /* Set up decryption */ int free_iv = 0, free_secret = 0, len_decrypted = 0, padding = 0; int blocksize = method->blocksize; @@ -223,24 +218,26 @@ _libssh2_pem_parse(LIBSSH2_SESSION * session, libssh2_md5_ctx fingerprint_ctx; /* Perform key derivation (PBKDF1/MD5) */ - if(!libssh2_md5_init(&fingerprint_ctx)) { + if(!libssh2_md5_init(&fingerprint_ctx) || + !libssh2_md5_update(fingerprint_ctx, passphrase, + strlen((char *)passphrase)) || + !libssh2_md5_update(fingerprint_ctx, iv, 8) || + !libssh2_md5_final(fingerprint_ctx, secret)) { 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)) { + if(!libssh2_md5_init(&fingerprint_ctx) || + !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)) { 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 */ @@ -292,6 +289,10 @@ _libssh2_pem_parse(LIBSSH2_SESSION * session, /* Clean up */ _libssh2_explicit_zero((char *)secret, sizeof(secret)); method->dtor(session, &abstract); +#else + ret = -1; + goto out; +#endif } ret = 0; @@ -599,13 +600,17 @@ _libssh2_openssh_pem_parse_data(LIBSSH2_SESSION * session, } while((size_t)len_decrypted <= decrypted.len - blocksize) { + /* We always pass MIDDLE_BLOCK here because OpenSSH Key Files + * do not use AAD to authenticate the length. + * Furthermore, the authentication tag is appended after the + * encrypted key, and the length of the authentication tag is + * not included in the key length, so we check it after the + * loop. + */ if(method->crypt(session, decrypted.data + len_decrypted, blocksize, &abstract, - len_decrypted == 0 ? FIRST_BLOCK : ( - ((size_t)len_decrypted == decrypted.len - blocksize) ? - LAST_BLOCK : MIDDLE_BLOCK) - )) { + MIDDLE_BLOCK)) { ret = LIBSSH2_ERROR_DECRYPT; method->dtor(session, &abstract); goto out; @@ -616,6 +621,26 @@ _libssh2_openssh_pem_parse_data(LIBSSH2_SESSION * session, /* No padding */ + /* for the AES GCM methods, the 16 byte authentication tag is + * appended to the encrypted key */ + if(strcmp(method->name, "aes256-gcm@openssh.com") == 0 || + strcmp(method->name, "aes128-gcm@openssh.com") == 0) { + if(!_libssh2_check_length(&decoded, 16)) { + ret = _libssh2_error(session, LIBSSH2_ERROR_PROTO, + "GCM auth tag missing"); + method->dtor(session, &abstract); + goto out; + } + if(method->crypt(session, decoded.dataptr, 16, &abstract, + LAST_BLOCK)) { + ret = _libssh2_error(session, LIBSSH2_ERROR_DECRYPT, + "GCM auth tag invalid"); + method->dtor(session, &abstract); + goto out; + } + decoded.dataptr += 16; + } + method->dtor(session, &abstract); } diff --git a/libs/libssh2/src/publickey.c b/libs/libssh2/src/publickey.c index db45be99be..9c9fa61884 100644 --- a/libs/libssh2/src/publickey.c +++ b/libs/libssh2/src/publickey.c @@ -516,13 +516,13 @@ static LIBSSH2_PUBLICKEY *publickey_init(LIBSSH2_SESSION *session) LIBSSH2_PUBLICKEY_VERSION) { _libssh2_debug((session, LIBSSH2_TRACE_PUBLICKEY, "Truncate remote publickey version " - "from %lu", + "from %u", session->pkeyInit_pkey->version)); session->pkeyInit_pkey->version = LIBSSH2_PUBLICKEY_VERSION; } _libssh2_debug((session, LIBSSH2_TRACE_PUBLICKEY, - "Enabling publickey subsystem version %lu", + "Enabling publickey subsystem version %u", session->pkeyInit_pkey->version)); LIBSSH2_FREE(session, session->pkeyInit_data); session->pkeyInit_data = NULL; diff --git a/libs/libssh2/src/scp.c b/libs/libssh2/src/scp.c index ff20a80ae5..0900655aac 100644 --- a/libs/libssh2/src/scp.c +++ b/libs/libssh2/src/scp.c @@ -748,7 +748,7 @@ scp_recv(LIBSSH2_SESSION * session, const char *path, libssh2_struct_stat * sb) } _libssh2_debug((session, LIBSSH2_TRACE_SCP, "mode = 0%lo size = %ld", session->scpRecv_mode, - session->scpRecv_size)); + (long)session->scpRecv_size)); /* We *should* check that basename is valid, but why let that stop us? */ @@ -792,6 +792,7 @@ scp_recv_error: return NULL; } +#ifndef LIBSSH2_NO_DEPRECATED /* * libssh2_scp_recv * @@ -828,6 +829,7 @@ libssh2_scp_recv(LIBSSH2_SESSION *session, const char *path, struct stat *sb) return ptr; } +#endif /* * libssh2_scp_recv2 diff --git a/libs/libssh2/src/session.c b/libs/libssh2/src/session.c index 4d9edc5c8c..9d89ade8ec 100644 --- a/libs/libssh2/src/session.c +++ b/libs/libssh2/src/session.c @@ -41,7 +41,7 @@ #include "libssh2_priv.h" -#ifdef WIN32 +#ifdef _WIN32 #include <ws2tcpip.h> /* for socklen_t */ #endif #ifdef HAVE_UNISTD_H @@ -60,7 +60,7 @@ #include "channel.h" #include "mac.h" -#if defined(WIN32) +#if defined(_WIN32) #define libssh2_usec_t long #elif defined(__APPLE__) #define libssh2_usec_t suseconds_t @@ -132,11 +132,11 @@ banner_receive(LIBSSH2_SESSION * session) if(session->api_block_mode || (ret != -EAGAIN)) /* ignore EAGAIN when non-blocking */ _libssh2_debug((session, LIBSSH2_TRACE_SOCKET, - "Error recving %d bytes: %d", 1, (int)-ret)); + "Error recving %d bytes: %ld", 1, (long)-ret)); } else _libssh2_debug((session, LIBSSH2_TRACE_SOCKET, - "Recved %d bytes banner", (int)ret)); + "Recved %ld bytes banner", (long)ret)); if(ret < 0) { if(ret == -EAGAIN) { @@ -253,13 +253,14 @@ banner_send(LIBSSH2_SESSION * session) 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)); + "Error sending %ld bytes: %ld", + (long)(banner_len - session->banner_TxRx_total_send), + (long)-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)); + "Sent %ld/%ld bytes at %p+%ld", (long)ret, + (long)(banner_len - session->banner_TxRx_total_send), + (void *)banner, (long)session->banner_TxRx_total_send)); if(ret != (ssize_t)(banner_len - session->banner_TxRx_total_send)) { if(ret >= 0 || ret == -EAGAIN) { @@ -313,7 +314,7 @@ session_nonblock(libssh2_socket_t sockfd, /* operate on this */ /* BeOS */ long b = nonblock ? 1 : 0; return setsockopt(sockfd, SOL_SOCKET, SO_NONBLOCK, &b, sizeof(b)); -#elif defined(WIN32) +#elif defined(_WIN32) unsigned long flags; flags = nonblock; @@ -366,7 +367,7 @@ get_socket_nonblocking(libssh2_socket_t sockfd) return 1; } return 0; -#elif defined(WIN32) +#elif defined(_WIN32) unsigned int option_value; socklen_t option_len = sizeof(option_value); @@ -417,6 +418,7 @@ libssh2_session_banner_set(LIBSSH2_SESSION * session, const char *banner) return 0; } +#ifndef LIBSSH2_NO_DEPRECATED /* libssh2_banner_set * Set the local banner. DEPRECATED VERSION */ @@ -425,6 +427,7 @@ libssh2_banner_set(LIBSSH2_SESSION * session, const char *banner) { return libssh2_session_banner_set(session, banner); } +#endif /* * libssh2_session_init_ex @@ -466,6 +469,8 @@ libssh2_session_init_ex(LIBSSH2_ALLOC_FUNC((*my_alloc)), session->abstract = abstract; session->api_timeout = 0; /* timeout-free API by default */ session->api_block_mode = 1; /* blocking API by default */ + session->state = LIBSSH2_STATE_INITIAL_KEX; + session->fullpacket_required_type = 0; session->packet_read_timeout = LIBSSH2_DEFAULT_READ_TIMEOUT; session->flag.quote_paths = 1; /* default behavior is to quote paths for the scp subsystem */ @@ -477,77 +482,68 @@ libssh2_session_init_ex(LIBSSH2_ALLOC_FUNC((*my_alloc)), } /* - * libssh2_session_callback_set + * libssh2_session_callback_set2 * * 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! */ -#ifdef _MSC_VER -#pragma warning(push) -/* nonstandard extension, function/data pointer conversion in expression */ -#pragma warning(disable:4152) -#else -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wpedantic" -#endif -LIBSSH2_API void * -libssh2_session_callback_set(LIBSSH2_SESSION * session, - int cbtype, void *callback) +LIBSSH2_API libssh2_cb_generic * +libssh2_session_callback_set2(LIBSSH2_SESSION *session, int cbtype, + libssh2_cb_generic *callback) { - void *oldcb; + libssh2_cb_generic *oldcb; switch(cbtype) { case LIBSSH2_CALLBACK_IGNORE: - oldcb = session->ssh_msg_ignore; - session->ssh_msg_ignore = callback; + oldcb = (libssh2_cb_generic *)session->ssh_msg_ignore; + session->ssh_msg_ignore = (LIBSSH2_IGNORE_FUNC((*)))callback; return oldcb; case LIBSSH2_CALLBACK_DEBUG: - oldcb = session->ssh_msg_debug; - session->ssh_msg_debug = callback; + oldcb = (libssh2_cb_generic *)session->ssh_msg_debug; + session->ssh_msg_debug = (LIBSSH2_DEBUG_FUNC((*)))callback; return oldcb; case LIBSSH2_CALLBACK_DISCONNECT: - oldcb = session->ssh_msg_disconnect; - session->ssh_msg_disconnect = callback; + oldcb = (libssh2_cb_generic *)session->ssh_msg_disconnect; + session->ssh_msg_disconnect = (LIBSSH2_DISCONNECT_FUNC((*)))callback; return oldcb; case LIBSSH2_CALLBACK_MACERROR: - oldcb = session->macerror; - session->macerror = callback; + oldcb = (libssh2_cb_generic *)session->macerror; + session->macerror = (LIBSSH2_MACERROR_FUNC((*)))callback; return oldcb; case LIBSSH2_CALLBACK_X11: - oldcb = session->x11; - session->x11 = callback; + oldcb = (libssh2_cb_generic *)session->x11; + session->x11 = (LIBSSH2_X11_OPEN_FUNC((*)))callback; return oldcb; case LIBSSH2_CALLBACK_SEND: - oldcb = session->send; - session->send = callback; + oldcb = (libssh2_cb_generic *)session->send; + session->send = (LIBSSH2_SEND_FUNC((*)))callback; return oldcb; case LIBSSH2_CALLBACK_RECV: - oldcb = session->recv; - session->recv = callback; + oldcb = (libssh2_cb_generic *)session->recv; + session->recv = (LIBSSH2_RECV_FUNC((*)))callback; return oldcb; case LIBSSH2_CALLBACK_AUTHAGENT: - oldcb = session->authagent; - session->authagent = callback; + oldcb = (libssh2_cb_generic *)session->authagent; + session->authagent = (LIBSSH2_AUTHAGENT_FUNC((*)))callback; return oldcb; case LIBSSH2_CALLBACK_AUTHAGENT_IDENTITIES: - oldcb = session->addLocalIdentities; - session->addLocalIdentities = callback; + oldcb = (libssh2_cb_generic *)session->addLocalIdentities; + session->addLocalIdentities = + (LIBSSH2_ADD_IDENTITIES_FUNC((*)))callback; return oldcb; case LIBSSH2_CALLBACK_AUTHAGENT_SIGN: - oldcb = session->agentSignCallback; - session->agentSignCallback = callback; + oldcb = (libssh2_cb_generic *)session->agentSignCallback; + session->agentSignCallback = + (LIBSSH2_AUTHAGENT_SIGN_FUNC((*)))callback; return oldcb; } _libssh2_debug((session, LIBSSH2_TRACE_TRANS, "Setting Callback %d", @@ -555,6 +551,33 @@ libssh2_session_callback_set(LIBSSH2_SESSION * session, return NULL; } + +/* + * libssh2_session_callback_set (DEPRECATED, DO NOT USE!) + * + * 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! + */ +#ifdef _MSC_VER +#pragma warning(push) +/* 'type cast': from data pointer to function pointer */ +#pragma warning(disable:4054) +/* 'type cast': from function pointer to data pointer */ +#pragma warning(disable:4055) +#else +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wpedantic" +#endif +LIBSSH2_API void * +libssh2_session_callback_set(LIBSSH2_SESSION * session, + int cbtype, void *callback) +{ + return (void *)libssh2_session_callback_set2(session, cbtype, + (libssh2_cb_generic *)callback); +} #ifdef _MSC_VER #pragma warning(pop) #else @@ -670,6 +693,18 @@ int _libssh2_wait_socket(LIBSSH2_SESSION *session, time_t start_time) "Timed out waiting on socket"); } if(rc < 0) { + int err; +#ifdef _WIN32 + err = _libssh2_wsa2errno(); +#else + err = errno; +#endif + /* Profiling tools that use SIGPROF can cause EINTR responses. + poll() / select() do not set any descriptor states on EINTR, + but some fds may be ready, so the caller should try again */ + if(err == EINTR) + return 0; + return _libssh2_error(session, LIBSSH2_ERROR_TIMEOUT, "Error waiting on socket"); } @@ -684,7 +719,7 @@ session_startup(LIBSSH2_SESSION *session, libssh2_socket_t sock) if(session->startup_state == libssh2_NB_state_idle) { _libssh2_debug((session, LIBSSH2_TRACE_TRANS, - "session_startup for socket %d", sock)); + "session_startup for socket %ld", (long)sock)); if(LIBSSH2_INVALID_SOCKET == sock) { /* Did we forget something? */ return _libssh2_error(session, LIBSSH2_ERROR_BAD_SOCKET, @@ -830,6 +865,7 @@ libssh2_session_handshake(LIBSSH2_SESSION *session, libssh2_socket_t sock) return rc; } +#ifndef LIBSSH2_NO_DEPRECATED /* * libssh2_session_startup * @@ -846,6 +882,7 @@ libssh2_session_startup(LIBSSH2_SESSION *session, int sock) { return libssh2_session_handshake(session, (libssh2_socket_t) sock); } +#endif /* * session_free @@ -864,8 +901,8 @@ session_free(LIBSSH2_SESSION *session) if(session->free_state == libssh2_NB_state_idle) { _libssh2_debug((session, LIBSSH2_TRACE_TRANS, - "Freeing session resource", - session->remote.banner)); + "Freeing session resource %p", + (void *)session->remote.banner)); session->free_state = libssh2_NB_state_created; } @@ -1188,6 +1225,7 @@ libssh2_session_disconnect_ex(LIBSSH2_SESSION *session, int reason, const char *desc, const char *lang) { int rc; + session->state &= ~LIBSSH2_STATE_INITIAL_KEX; session->state &= ~LIBSSH2_STATE_EXCHANGING_KEYS; BLOCK_ADJUST(rc, session, session_disconnect(session, reason, desc, lang)); @@ -1773,7 +1811,11 @@ libssh2_poll(LIBSSH2_POLLFD * fds, unsigned int nfds, long timeout) } #elif defined(HAVE_SELECT) tv.tv_sec = timeout_remaining / 1000; +#ifdef libssh2_usec_t + tv.tv_usec = (libssh2_usec_t)((timeout_remaining % 1000) * 1000); +#else tv.tv_usec = (timeout_remaining % 1000) * 1000; +#endif { struct timeval tv_begin, tv_end; diff --git a/libs/libssh2/src/session.h b/libs/libssh2/src/session.h index bfc9b545b8..d4fc5755e5 100644 --- a/libs/libssh2/src/session.h +++ b/libs/libssh2/src/session.h @@ -1,5 +1,5 @@ -#ifndef __LIBSSH2_SESSION_H -#define __LIBSSH2_SESSION_H +#ifndef LIBSSH2_SESSION_H +#define LIBSSH2_SESSION_H /* Copyright (C) Sara Golemon <sarag@libssh2.org> * Copyright (C) Daniel Stenberg * Copyright (C) Simon Josefsson <simon@josefsson.org> @@ -91,4 +91,4 @@ 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 */ +#endif /* LIBSSH2_SESSION_H */ diff --git a/libs/libssh2/src/sftp.c b/libs/libssh2/src/sftp.c index 16ee7b8689..f8f1323e02 100644 --- a/libs/libssh2/src/sftp.c +++ b/libs/libssh2/src/sftp.c @@ -152,7 +152,7 @@ remove_zombie_request(LIBSSH2_SFTP *sftp, uint32_t request_id) request_id); if(zombie) { _libssh2_debug((session, LIBSSH2_TRACE_SFTP, - "Removing request ID %ld from the list of " + "Removing request ID %u from the list of " "zombie requests", request_id)); @@ -169,13 +169,13 @@ add_zombie_request(LIBSSH2_SFTP *sftp, uint32_t request_id) struct sftp_zombie_requests *zombie; _libssh2_debug((session, LIBSSH2_TRACE_SFTP, - "Marking request ID %ld as a zombie request", request_id)); + "Marking request ID %u 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"); + "malloc fail for zombie request ID"); else { zombie->request_id = request_id; _libssh2_list_add(&sftp->zombie_requests, &zombie->node); @@ -199,8 +199,8 @@ sftp_packet_add(LIBSSH2_SFTP *sftp, unsigned char *data, } _libssh2_debug((session, LIBSSH2_TRACE_SFTP, - "Received packet type %d (len %d)", - (int) data[0], data_len)); + "Received packet type %u (len %lu)", + (unsigned int)data[0], (unsigned long)data_len)); /* * Experience shows that if we mess up EAGAIN handling somewhere or @@ -306,11 +306,11 @@ sftp_packet_read(LIBSSH2_SFTP *sftp) packet = sftp->partial_packet; _libssh2_debug((session, LIBSSH2_TRACE_SFTP, - "partial read cont, len: %lu", sftp->partial_len)); + "partial read cont, len: %u", sftp->partial_len)); _libssh2_debug((session, LIBSSH2_TRACE_SFTP, "partial read cont, already recvd: %lu", - sftp->partial_received)); - /* fall-through */ + (unsigned long)sftp->partial_received)); + LIBSSH2_FALLTHROUGH(); default: if(!packet) { /* only do this if there's not already a packet buffer allocated @@ -359,7 +359,7 @@ sftp_packet_read(LIBSSH2_SFTP *sftp) _libssh2_debug((session, LIBSSH2_TRACE_SFTP, "Data begin - Packet Length: %lu", - sftp->partial_len)); + (unsigned long)sftp->partial_len)); packet = LIBSSH2_ALLOC(session, sftp->partial_len); if(!packet) return _libssh2_error(session, LIBSSH2_ERROR_ALLOC, @@ -526,13 +526,13 @@ sftp_packet_require(LIBSSH2_SFTP *sftp, unsigned char packet_type, return LIBSSH2_ERROR_BAD_USE; } - _libssh2_debug((session, LIBSSH2_TRACE_SFTP, "Requiring packet %d id %ld", - (int) packet_type, request_id)); + _libssh2_debug((session, LIBSSH2_TRACE_SFTP, "Requiring packet %u id %u", + (unsigned 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)); + _libssh2_debug((session, LIBSSH2_TRACE_SFTP, "Got %u", + (unsigned int) packet_type)); if(*data_len < required_size) { return LIBSSH2_ERROR_BUFFER_TOO_SMALL; @@ -550,7 +550,7 @@ sftp_packet_require(LIBSSH2_SFTP *sftp, unsigned char packet_type, 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)); + (unsigned int) packet_type)); if(*data_len < required_size) { return LIBSSH2_ERROR_BUFFER_TOO_SMALL; @@ -979,12 +979,12 @@ static LIBSSH2_SFTP *sftp_init(LIBSSH2_SESSION *session) if(sftp_handle->version > LIBSSH2_SFTP_VERSION) { _libssh2_debug((session, LIBSSH2_TRACE_SFTP, - "Truncating remote SFTP version from %lu", + "Truncating remote SFTP version from %u", sftp_handle->version)); sftp_handle->version = LIBSSH2_SFTP_VERSION; } _libssh2_debug((session, LIBSSH2_TRACE_SFTP, - "Enabling SFTP version %lu compatibility", + "Enabling SFTP version %u compatibility", sftp_handle->version)); while(buf.dataptr < endp) { unsigned char *extname, *extdata; @@ -1567,10 +1567,11 @@ static ssize_t sftp_read(LIBSSH2_SFTP_HANDLE * handle, char *buffer, more packets */ count -= LIBSSH2_MIN(size, count); _libssh2_debug((session, LIBSSH2_TRACE_SFTP, - "read request id %d sent (offset: %d, size: %d)", - request_id, (int)chunk->offset, (int)chunk->len)); + "read request id %d sent (offset: %lu, size: %lu)", + request_id, (unsigned long)chunk->offset, + (unsigned long)chunk->len)); } - /* FALL-THROUGH */ + LIBSSH2_FALLTHROUGH(); case libssh2_NB_state_sent: sftp->read_state = libssh2_NB_state_idle; @@ -1610,7 +1611,7 @@ static ssize_t sftp_read(LIBSSH2_SFTP_HANDLE * handle, char *buffer, /* move on to the next chunk with data to send */ chunk = _libssh2_list_next(&chunk->node); } - /* FALL-THROUGH */ + LIBSSH2_FALLTHROUGH(); case libssh2_NB_state_sent2: @@ -1690,7 +1691,6 @@ static ssize_t sftp_read(LIBSSH2_SFTP_HANDLE * handle, char *buffer, return _libssh2_error(session, LIBSSH2_ERROR_SFTP_PROTOCOL, "SFTP READ error"); } - break; case SSH_FXP_DATA: if(chunk->offset != filep->offset) { @@ -1922,8 +1922,8 @@ static ssize_t sftp_readdir(LIBSSH2_SFTP_HANDLE *handle, char *buffer, end: _libssh2_debug((session, LIBSSH2_TRACE_SFTP, - "libssh2_sftp_readdir_ex() return %d", - filename_len)); + "libssh2_sftp_readdir_ex() return %lu", + (unsigned long)filename_len)); return (ssize_t)filename_len; } @@ -2003,7 +2003,7 @@ end: sftp->readdir_state = libssh2_NB_state_idle; num_names = _libssh2_ntohu32(data + 5); - _libssh2_debug((session, LIBSSH2_TRACE_SFTP, "%lu entries returned", + _libssh2_debug((session, LIBSSH2_TRACE_SFTP, "%u entries returned", num_names)); if(!num_names) { LIBSSH2_FREE(session, data); @@ -2185,7 +2185,8 @@ static ssize_t sftp_write(LIBSSH2_SFTP_HANDLE *handle, const char *buffer, chunk = _libssh2_list_next(&chunk->node); } - /* fall-through */ + LIBSSH2_FALLTHROUGH(); + case libssh2_NB_state_sent: sftp->write_state = libssh2_NB_state_idle; diff --git a/libs/libssh2/src/sftp.h b/libs/libssh2/src/sftp.h index 647ddbc007..267c8fef0d 100644 --- a/libs/libssh2/src/sftp.h +++ b/libs/libssh2/src/sftp.h @@ -1,5 +1,5 @@ -#ifndef __LIBSSH2_SFTP_H -#define __LIBSSH2_SFTP_H +#ifndef LIBSSH2_SFTP_PRIV_H +#define LIBSSH2_SFTP_PRIV_H /* * Copyright (C) Daniel Stenberg * All rights reserved. @@ -233,4 +233,4 @@ struct _LIBSSH2_SFTP uint32_t symlink_request_id; }; -#endif /* __LIBSSH2_SFTP_H */ +#endif /* LIBSSH2_SFTP_PRIV_H */ diff --git a/libs/libssh2/src/transport.c b/libs/libssh2/src/transport.c index c73b859e4d..531f5aa15a 100644 --- a/libs/libssh2/src/transport.c +++ b/libs/libssh2/src/transport.c @@ -51,9 +51,6 @@ #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 @@ -72,8 +69,8 @@ debugdump(LIBSSH2_SESSION * session, return; } - used = snprintf(buffer, sizeof(buffer), "=> %s (%d bytes)\n", - desc, (int) size); + used = snprintf(buffer, sizeof(buffer), "=> %s (%lu bytes)\n", + desc, (unsigned long) size); if(session->tracehandler) (session->tracehandler)(session, session->tracehandler_context, buffer, used); @@ -189,6 +186,7 @@ fullpacket(LIBSSH2_SESSION * session, int encrypted /* 1 or 0 */ ) struct transportpacket *p = &session->packet; int rc; int compressed; + uint32_t seq = session->remote.seqno; if(session->fullpacket_state == libssh2_NB_state_idle) { session->fullpacket_macstate = LIBSSH2_MAC_CONFIRMED; @@ -320,7 +318,7 @@ fullpacket(LIBSSH2_SESSION * session, int encrypted /* 1 or 0 */ ) if(session->fullpacket_state == libssh2_NB_state_created) { rc = _libssh2_packet_add(session, p->payload, session->fullpacket_payload_len, - session->fullpacket_macstate); + session->fullpacket_macstate, seq); if(rc == LIBSSH2_ERROR_EAGAIN) return rc; if(rc) { @@ -331,6 +329,11 @@ fullpacket(LIBSSH2_SESSION * session, int encrypted /* 1 or 0 */ ) session->fullpacket_state = libssh2_NB_state_idle; + if(session->kex_strict && + session->fullpacket_packet_type == SSH_MSG_NEWKEYS) { + session->remote.seqno = 0; + } + return session->fullpacket_packet_type; } @@ -467,13 +470,15 @@ int _libssh2_transport_read(LIBSSH2_SESSION * session) return LIBSSH2_ERROR_EAGAIN; } _libssh2_debug((session, LIBSSH2_TRACE_SOCKET, - "Error recving %d bytes (got %d)", - PACKETBUFSIZE - remainbuf, -nread)); + "Error recving %ld bytes (got %ld)", + (long)(PACKETBUFSIZE - remainbuf), + (long)-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)); + "Recved %ld/%ld bytes to %p+%ld", (long)nread, + (long)(PACKETBUFSIZE - remainbuf), (void *)p->buf, + (long)remainbuf)); debugdump(session, "libssh2_transport_read() raw", &p->buf[remainbuf], nread); @@ -790,11 +795,12 @@ send_existing(LIBSSH2_SESSION *session, const unsigned char *data, LIBSSH2_SOCKET_SEND_FLAGS(session)); if(rc < 0) _libssh2_debug((session, LIBSSH2_TRACE_SOCKET, - "Error sending %d bytes: %d", length, -rc)); + "Error sending %ld bytes: %ld", + (long)length, (long)-rc)); else { _libssh2_debug((session, LIBSSH2_TRACE_SOCKET, - "Sent %d/%d bytes at %p+%d", rc, length, p->outbuf, - p->osent)); + "Sent %ld/%ld bytes at %p+%lu", (long)rc, (long)length, + (void *)p->outbuf, (unsigned long)p->osent)); debugdump(session, "libssh2_transport_write send()", &p->outbuf[p->osent], rc); } @@ -1022,10 +1028,12 @@ int _libssh2_transport_send(LIBSSH2_SESSION *session, INTEGRATED_MAC case, where the crypto algorithm also does its own hash. */ if(!etm && !CRYPT_FLAG_R(session, INTEGRATED_MAC)) { - session->local.mac->hash(session, p->outbuf + packet_length, - session->local.seqno, p->outbuf, - packet_length, NULL, 0, - &session->local.mac_abstract); + if(session->local.mac->hash(session, p->outbuf + packet_length, + session->local.seqno, p->outbuf, + packet_length, NULL, 0, + &session->local.mac_abstract)) + return _libssh2_error(session, LIBSSH2_ERROR_MAC_FAILURE, + "Failed to calculate MAC"); } /* Encrypt the whole packet data, one block size at a time. @@ -1058,8 +1066,8 @@ int _libssh2_transport_send(LIBSSH2_SESSION *session, i += bsize - session->local.crypt->blocksize; } _libssh2_debug((session, LIBSSH2_TRACE_SOCKET, - "crypting bytes %d-%d", i, - i + session->local.crypt->blocksize - 1)); + "crypting bytes %lu-%lu", (unsigned long)i, + (unsigned long)(i + bsize - 1))); if(session->local.crypt->crypt(session, ptr, bsize, &session->local.crypt_abstract, @@ -1084,24 +1092,31 @@ int _libssh2_transport_send(LIBSSH2_SESSION *session, calculated on the entire packet (length plain the rest encrypted), 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); + if(session->local.mac->hash(session, p->outbuf + packet_length, + session->local.seqno, p->outbuf, + packet_length, NULL, 0, + &session->local.mac_abstract)) + return _libssh2_error(session, LIBSSH2_ERROR_MAC_FAILURE, + "Failed to calculate MAC"); } } session->local.seqno++; + if(session->kex_strict && data[0] == SSH_MSG_NEWKEYS) { + session->local.seqno = 0; + } + 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)); + "Error sending %ld bytes: %ld", + (long)total_length, (long)-ret)); else { _libssh2_debug((session, LIBSSH2_TRACE_SOCKET, - "Sent %d/%d bytes at %p", - ret, total_length, p->outbuf)); + "Sent %ld/%ld bytes at %p", + (long)ret, (long)total_length, (void *)p->outbuf)); debugdump(session, "libssh2_transport_write send()", p->outbuf, ret); } diff --git a/libs/libssh2/src/transport.h b/libs/libssh2/src/transport.h index 64482290ee..4b824e2096 100644 --- a/libs/libssh2/src/transport.h +++ b/libs/libssh2/src/transport.h @@ -1,5 +1,5 @@ -#ifndef __LIBSSH2_TRANSPORT_H -#define __LIBSSH2_TRANSPORT_H +#ifndef LIBSSH2_TRANSPORT_H +#define LIBSSH2_TRANSPORT_H /* Copyright (C) The Written Word, Inc. * Copyright (C) Daniel Stenberg * All rights reserved. @@ -84,4 +84,4 @@ int _libssh2_transport_send(LIBSSH2_SESSION *session, */ int _libssh2_transport_read(LIBSSH2_SESSION * session); -#endif /* __LIBSSH2_TRANSPORT_H */ +#endif /* LIBSSH2_TRANSPORT_H */ diff --git a/libs/libssh2/src/userauth.c b/libs/libssh2/src/userauth.c index e7578759f3..60fd48e47d 100644 --- a/libs/libssh2/src/userauth.c +++ b/libs/libssh2/src/userauth.c @@ -818,11 +818,17 @@ struct privkey_file { const char *passphrase; }; +struct privkey_mem { + const char *passphrase; + const char *data; + size_t data_len; +}; + 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); + struct privkey_mem *pk_mem = (struct privkey_mem *) (*abstract); const LIBSSH2_HOSTKEY_METHOD *privkeyobj; void *hostkey_abstract; struct iovec datavec; @@ -831,9 +837,9 @@ sign_frommemory(LIBSSH2_SESSION *session, unsigned char **sig, size_t *sig_len, 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); + pk_mem->data, + pk_mem->data_len, + pk_mem->passphrase); if(rc) return rc; @@ -1410,7 +1416,7 @@ _libssh2_key_sign_algorithm(LIBSSH2_SESSION *session, LIBSSH2_FREE(session, *key_method); *key_method = LIBSSH2_ALLOC(session, match_len); - if(key_method) { + if(*key_method) { memcpy(*key_method, match, match_len); *key_method_len = match_len; } @@ -1511,7 +1517,7 @@ retry_auth: _libssh2_debug((session, LIBSSH2_TRACE_KEX, "Signing using %.*s", - session->userauth_pblc_method_len, + (int)session->userauth_pblc_method_len, session->userauth_pblc_method)); } @@ -1835,12 +1841,13 @@ userauth_publickey_frommemory(LIBSSH2_SESSION *session, { unsigned char *pubkeydata = NULL; size_t pubkeydata_len = 0; - struct privkey_file privkey_file; - void *abstract = &privkey_file; + struct privkey_mem privkey_mem; + void *abstract = &privkey_mem; int rc; - privkey_file.filename = privatekeydata; - privkey_file.passphrase = passphrase; + privkey_mem.data = privatekeydata; + privkey_mem.data_len = privatekeydata_len; + privkey_mem.passphrase = passphrase; if(session->userauth_pblc_state == libssh2_NB_state_idle) { if(publickeydata_len && publickeydata) { diff --git a/libs/libssh2/src/userauth.h b/libs/libssh2/src/userauth.h index 24f8037ec2..2f53ac5be9 100644 --- a/libs/libssh2/src/userauth.h +++ b/libs/libssh2/src/userauth.h @@ -1,5 +1,5 @@ -#ifndef __LIBSSH2_USERAUTH_H -#define __LIBSSH2_USERAUTH_H +#ifndef LIBSSH2_USERAUTH_H +#define LIBSSH2_USERAUTH_H /* Copyright (C) Sara Golemon <sarag@libssh2.org> * Copyright (C) Daniel Stenberg * All rights reserved. @@ -50,4 +50,4 @@ _libssh2_userauth_publickey(LIBSSH2_SESSION *session, ((*sign_callback)), void *abstract); -#endif /* __LIBSSH2_USERAUTH_H */ +#endif /* LIBSSH2_USERAUTH_H */ diff --git a/libs/libssh2/src/userauth_kbd_packet.h b/libs/libssh2/src/userauth_kbd_packet.h index bee34495e1..56e88b3f32 100644 --- a/libs/libssh2/src/userauth_kbd_packet.h +++ b/libs/libssh2/src/userauth_kbd_packet.h @@ -37,9 +37,9 @@ * SPDX-License-Identifier: BSD-3-Clause */ -#ifndef __LIBSSH2_USERAUTH_KBD_PARSE_H -#define __LIBSSH2_USERAUTH_KBD_PARSE_H +#ifndef LIBSSH2_USERAUTH_KBD_PACKET_H +#define LIBSSH2_USERAUTH_KBD_PACKET_H int userauth_keyboard_interactive_decode_info_request(LIBSSH2_SESSION *); -#endif /* __LIBSSH2_USERAUTH_KBD_PARSE_H */ +#endif /* LIBSSH2_USERAUTH_KBD_PACKET_H */ |