Index: head/security/libssh2/Makefile =================================================================== --- head/security/libssh2/Makefile (revision 491662) +++ head/security/libssh2/Makefile (revision 491663) @@ -1,48 +1,49 @@ # Created by: Alexander Leidinger # $FreeBSD$ PORTNAME= libssh2 PORTVERSION= 1.8.0 +PORTREVISION= 1 PORTEPOCH= 3 CATEGORIES= security devel MASTER_SITES= http://www.libssh2.org/download/ \ LOCAL/sbz MAINTAINER= sbz@FreeBSD.org COMMENT= Library implementing the SSH2 protocol LICENSE= BSD3CLAUSE LICENSE_FILE= ${WRKSRC}/COPYING GNU_CONFIGURE= yes INSTALL_TARGET= install-strip USES= libtool pathfix USE_LDCONFIG= yes OPTIONS_DEFINE= GCRYPT TRACE ZLIB OPTIONS_DEFAULT= ZLIB TRACE_DESC= Enable debug packet traces TRACE_CONFIGURE_ENABLE= debug GCRYPT_LIB_DEPENDS= libgcrypt.so:security/libgcrypt GCRYPT_CONFIGURE_ON= --with-libgcrypt GCRYPT_CONFIGURE_OFF= --with-openssl GCRYPT_CPPFLAGS= -I${LOCALBASE}/include GCRYPT_LIBS= -L${LOCALBASE}/lib GCRYPT_USES_OFF= ssl ZLIB_CONFIGURE_WITH= libz .include post-patch: @${REINPLACE_CMD} -e '/Libs:/s/@LIBS@//' \ ${WRKSRC}/libssh2.pc.in .if ! ${PORT_OPTIONS:MGCRYPT} . if ${SSL_DEFAULT} == base @${REINPLACE_CMD} -e 's/LIBSREQUIRED=libssl,libcrypto/LIBS="$$LIBS -lssl -lcrypto"/' \ ${WRKSRC}/configure . endif .endif .include Index: head/security/libssh2/files/patch-include_libssh2.h =================================================================== --- head/security/libssh2/files/patch-include_libssh2.h (nonexistent) +++ head/security/libssh2/files/patch-include_libssh2.h (revision 491663) @@ -0,0 +1,43 @@ +--- include/libssh2.h.orig 2016-10-25 06:44:34 UTC ++++ include/libssh2.h +@@ -403,11 +403,15 @@ typedef struct _LIBSSH2_POLLFD { + /* Hash Types */ + #define LIBSSH2_HOSTKEY_HASH_MD5 1 + #define LIBSSH2_HOSTKEY_HASH_SHA1 2 ++#define LIBSSH2_HOSTKEY_HASH_SHA256 3 + + /* Hostkey Types */ +-#define LIBSSH2_HOSTKEY_TYPE_UNKNOWN 0 +-#define LIBSSH2_HOSTKEY_TYPE_RSA 1 +-#define LIBSSH2_HOSTKEY_TYPE_DSS 2 ++#define LIBSSH2_HOSTKEY_TYPE_UNKNOWN 0 ++#define LIBSSH2_HOSTKEY_TYPE_RSA 1 ++#define LIBSSH2_HOSTKEY_TYPE_DSS 2 ++#define LIBSSH2_HOSTKEY_TYPE_ECDSA_256 3 ++#define LIBSSH2_HOSTKEY_TYPE_ECDSA_384 4 ++#define LIBSSH2_HOSTKEY_TYPE_ECDSA_521 5 + + /* Disconnect Codes (defined by SSH protocol) */ + #define SSH_DISCONNECT_HOST_NOT_ALLOWED_TO_CONNECT 1 +@@ -960,12 +964,15 @@ libssh2_knownhost_init(LIBSSH2_SESSION * + #define LIBSSH2_KNOWNHOST_KEYENC_BASE64 (2<<16) + + /* type of key (2 bits) */ +-#define LIBSSH2_KNOWNHOST_KEY_MASK (7<<18) +-#define LIBSSH2_KNOWNHOST_KEY_SHIFT 18 +-#define LIBSSH2_KNOWNHOST_KEY_RSA1 (1<<18) +-#define LIBSSH2_KNOWNHOST_KEY_SSHRSA (2<<18) +-#define LIBSSH2_KNOWNHOST_KEY_SSHDSS (3<<18) +-#define LIBSSH2_KNOWNHOST_KEY_UNKNOWN (7<<18) ++#define LIBSSH2_KNOWNHOST_KEY_MASK (7<<18) ++#define LIBSSH2_KNOWNHOST_KEY_SHIFT 18 ++#define LIBSSH2_KNOWNHOST_KEY_RSA1 (1<<18) ++#define LIBSSH2_KNOWNHOST_KEY_SSHRSA (2<<18) ++#define LIBSSH2_KNOWNHOST_KEY_SSHDSS (3<<18) ++#define LIBSSH2_KNOWNHOST_KEY_ECDSA_256 (4<<18) ++#define LIBSSH2_KNOWNHOST_KEY_ECDSA_384 (5<<18) ++#define LIBSSH2_KNOWNHOST_KEY_ECDSA_521 (6<<18) ++#define LIBSSH2_KNOWNHOST_KEY_UNKNOWN (7<<18) + + LIBSSH2_API int + libssh2_knownhost_add(LIBSSH2_KNOWNHOSTS *hosts, Property changes on: head/security/libssh2/files/patch-include_libssh2.h ___________________________________________________________________ Added: fbsd:nokeywords ## -0,0 +1 ## +yes \ No newline at end of property Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: head/security/libssh2/files/patch-src_crypto.h =================================================================== --- head/security/libssh2/files/patch-src_crypto.h (nonexistent) +++ head/security/libssh2/files/patch-src_crypto.h (revision 491663) @@ -0,0 +1,56 @@ +--- src/crypto.h.orig 2016-10-17 14:28:29 UTC ++++ src/crypto.h +@@ -120,6 +120,53 @@ int _libssh2_dsa_new_private_frommemory( + unsigned const char *passphrase); + #endif + ++#if LIBSSH2_ECDSA ++int ++_libssh2_ecdsa_curve_name_with_octal_new(libssh2_ecdsa_ctx ** ecdsactx, ++ const unsigned char *k, ++ size_t k_len, libssh2_curve_type type); ++int ++_libssh2_ecdsa_new_private(libssh2_ecdsa_ctx ** ec_ctx, ++ LIBSSH2_SESSION * session, ++ const char *filename, unsigned const char *passphrase); ++ ++int _libssh2_ecdsa_new_openssh_private(libssh2_ecdsa_ctx ** dsa, ++ LIBSSH2_SESSION * session, ++ const char *filename, ++ unsigned const char *passphrase); ++int ++_libssh2_ecdsa_verify(libssh2_ecdsa_ctx * ctx, ++ const unsigned char *r, size_t r_len, ++ const unsigned char *s, size_t s_len, ++ const unsigned char *m, size_t m_len); ++ ++int ++_libssh2_ecdsa_create_key(_libssh2_ec_key **out_private_key, ++ unsigned char **out_public_key_octal, ++ size_t *out_public_key_octal_len, libssh2_curve_type curve_type); ++ ++int ++_libssh2_ecdh_gen_k(_libssh2_bn **k, _libssh2_ec_key *private_key, ++ const unsigned char *server_public_key, size_t server_public_key_len); ++ ++int ++_libssh2_ecdsa_sign(LIBSSH2_SESSION *session, libssh2_ecdsa_ctx *ec_ctx, ++ const unsigned char *hash, unsigned long hash_len, ++ unsigned char **signature, size_t *signature_len); ++ ++int _libssh2_ecdsa_new_private_frommemory(libssh2_ecdsa_ctx ** ec_ctx, ++ LIBSSH2_SESSION * session, ++ const char *filedata, size_t filedata_len, ++ unsigned const char *passphrase); ++ ++libssh2_curve_type ++_libssh2_ecdsa_key_get_curve_type(_libssh2_ec_key *key); ++ ++int ++_libssh2_ecdsa_curve_type_from_name(const char *name, libssh2_curve_type *out_type); ++ ++#endif /* LIBSSH2_ECDSA */ ++ + int _libssh2_cipher_init(_libssh2_cipher_ctx * h, + _libssh2_cipher_type(algo), + unsigned char *iv, Property changes on: head/security/libssh2/files/patch-src_crypto.h ___________________________________________________________________ Added: fbsd:nokeywords ## -0,0 +1 ## +yes \ No newline at end of property Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: head/security/libssh2/files/patch-src_hostkey.c =================================================================== --- head/security/libssh2/files/patch-src_hostkey.c (nonexistent) +++ head/security/libssh2/files/patch-src_hostkey.c (revision 491663) @@ -0,0 +1,363 @@ +--- src/hostkey.c.orig 2016-01-18 12:41:58 UTC ++++ src/hostkey.c +@@ -483,7 +483,296 @@ static const LIBSSH2_HOSTKEY_METHOD host + }; + #endif /* LIBSSH2_DSA */ + ++#if LIBSSH2_ECDSA ++ ++/* *********** ++ * ecdsa-sha2-nistp256/384/521 * ++ *********** */ ++ ++static int ++hostkey_method_ssh_ecdsa_dtor(LIBSSH2_SESSION * session, ++ void **abstract); ++ ++/* ++ * hostkey_method_ssh_ecdsa_init ++ * ++ * Initialize the server hostkey working area with e/n pair ++ */ ++static int ++hostkey_method_ssh_ecdsa_init(LIBSSH2_SESSION * session, ++ const unsigned char *hostkey_data, ++ size_t hostkey_data_len, ++ void **abstract) ++{ ++ libssh2_ecdsa_ctx *ecdsactx = NULL; ++ const unsigned char *s, *k; ++ size_t len, key_len, n_len; ++ libssh2_curve_type type; ++ ++ if (abstract != NULL && *abstract) { ++ hostkey_method_ssh_ecdsa_dtor(session, abstract); ++ *abstract = NULL; ++ } ++ ++ if ( hostkey_data_len < 23 ) ++ return -1; ++ ++ s = hostkey_data; ++ len = _libssh2_ntohu32(s); ++ s += 4; ++ ++ if (len != 19 ) ++ return -1; ++ ++ if (strncmp((char*) s, "ecdsa-sha2-nistp256", 19) == 0 ) { ++ type = LIBSSH2_EC_CURVE_NISTP256; ++ } else if(strncmp((char*) s, "ecdsa-sha2-nistp384", 19) == 0 ) { ++ type = LIBSSH2_EC_CURVE_NISTP384; ++ } else if(strncmp((char*) s, "ecdsa-sha2-nistp521", 19) == 0 ) { ++ type = LIBSSH2_EC_CURVE_NISTP521; ++ } else { ++ return -1; ++ } ++ s += 19; ++ ++ /* Domain length */ ++ n_len = _libssh2_ntohu32(s); ++ s += 4; ++ ++ if (n_len != 8) ++ return -1; ++ ++ if ( type == LIBSSH2_EC_CURVE_NISTP256 && strncmp((char*)s, "nistp256", 8) != 0) { ++ return -1; ++ } else if ( type == LIBSSH2_EC_CURVE_NISTP384 && strncmp((char*)s, "nistp384", 8) != 0) { ++ return -1; ++ } else if ( type == LIBSSH2_EC_CURVE_NISTP521 && strncmp((char*)s, "nistp521", 8) != 0) { ++ return -1; ++ } ++ ++ s += 8; ++ ++ /* public key */ ++ key_len = _libssh2_ntohu32(s); ++ s += 4; ++ ++ k = s; ++ ++ if (_libssh2_ecdsa_curve_name_with_octal_new(&ecdsactx, k, key_len, type) ) ++ return -1; ++ ++ if ( abstract != NULL ) ++ *abstract = ecdsactx; ++ ++ return 0; ++} ++ ++/* ++ * hostkey_method_ssh_ecdsa_initPEM ++ * ++ * Load a Private Key from a PEM file ++ */ ++static int ++hostkey_method_ssh_ecdsa_initPEM(LIBSSH2_SESSION * session, ++ const char *privkeyfile, ++ unsigned const char *passphrase, ++ void **abstract) ++{ ++ libssh2_ecdsa_ctx *ec_ctx = NULL; ++ int ret; ++ ++ if (abstract != NULL && *abstract) { ++ hostkey_method_ssh_ecdsa_dtor(session, abstract); ++ *abstract = NULL; ++ } ++ ++ ret = _libssh2_ecdsa_new_private(&ec_ctx, session, privkeyfile, passphrase); ++ ++ if ( abstract != NULL ) ++ *abstract = ec_ctx; ++ ++ return ret; ++} ++ ++/* ++ * hostkey_method_ssh_ecdsa_initPEMFromMemory ++ * ++ * Load a Private Key from memory ++ */ ++static int ++hostkey_method_ssh_ecdsa_initPEMFromMemory(LIBSSH2_SESSION * session, ++ const char *privkeyfiledata, ++ size_t privkeyfiledata_len, ++ unsigned const char *passphrase, ++ void **abstract) ++{ ++ libssh2_ecdsa_ctx *ec_ctx = NULL; ++ int ret; ++ ++ if (abstract != NULL && *abstract) { ++ hostkey_method_ssh_ecdsa_dtor(session, abstract); ++ *abstract = NULL; ++ } ++ ++ ret = _libssh2_ecdsa_new_private_frommemory(&ec_ctx, session, ++ privkeyfiledata, ++ privkeyfiledata_len, passphrase); ++ if (ret) { ++ return -1; ++ } ++ ++ if (abstract != NULL) ++ *abstract = ec_ctx; ++ ++ return 0; ++} ++ ++/* ++ * hostkey_method_ecdsa_sig_verify ++ * ++ * Verify signature created by remote ++ */ ++static int ++hostkey_method_ssh_ecdsa_sig_verify(LIBSSH2_SESSION * session, ++ const unsigned char *sig, ++ size_t sig_len, ++ const unsigned char *m, ++ size_t m_len, void **abstract) ++{ ++ const unsigned char *r, *s, *p; ++ size_t r_len, s_len; ++ libssh2_ecdsa_ctx *ctx = (libssh2_ecdsa_ctx *) (*abstract); ++ ++ (void) session; ++ ++ if ( sig_len < 35 ) ++ return -1; ++ ++ /* Skip past keyname_len(4) + keyname(19){"ecdsa-sha2-nistp256"} + signature_len(4) */ ++ p = sig; ++ p += 27; ++ ++ r_len = _libssh2_ntohu32(p); ++ p += 4; ++ r = p; ++ p += r_len; ++ ++ s_len = _libssh2_ntohu32(p); ++ p += 4; ++ s = p; ++ ++ return _libssh2_ecdsa_verify(ctx, r, r_len, s, s_len, m, m_len); ++} ++ ++ ++#define LIBSSH2_HOSTKEY_METHOD_EC_SIGNV_HASH(digest_type) \ ++{ \ ++ unsigned char hash[SHA##digest_type##_DIGEST_LENGTH]; \ ++ libssh2_sha##digest_type##_ctx ctx; \ ++ int i; \ ++ libssh2_sha##digest_type##_init(&ctx); \ ++ for(i = 0; i < veccount; i++) { \ ++ libssh2_sha##digest_type##_update(ctx, datavec[i].iov_base, datavec[i].iov_len); \ ++ } \ ++ libssh2_sha##digest_type##_final(ctx, hash); \ ++ ret = _libssh2_ecdsa_sign(session, ec_ctx, hash, SHA##digest_type##_DIGEST_LENGTH, \ ++ signature, signature_len); \ ++} ++ ++ ++/* ++ * hostkey_method_ecdsa_signv ++ * ++ * Construct a signature from an array of vectors ++ */ ++static int ++hostkey_method_ssh_ecdsa_signv(LIBSSH2_SESSION * session, ++ unsigned char **signature, ++ size_t *signature_len, ++ int veccount, ++ const struct iovec datavec[], ++ void **abstract) ++{ ++ libssh2_ecdsa_ctx *ec_ctx = (libssh2_ecdsa_ctx *) (*abstract); ++ libssh2_curve_type type = _libssh2_ecdsa_key_get_curve_type(ec_ctx); ++ int ret = 0; ++ ++ if ( type == LIBSSH2_EC_CURVE_NISTP256 ) { ++ LIBSSH2_HOSTKEY_METHOD_EC_SIGNV_HASH(256); ++ }else if ( type == LIBSSH2_EC_CURVE_NISTP384 ) { ++ LIBSSH2_HOSTKEY_METHOD_EC_SIGNV_HASH(384); ++ }else if ( type == LIBSSH2_EC_CURVE_NISTP521 ){ ++ LIBSSH2_HOSTKEY_METHOD_EC_SIGNV_HASH(512); ++ }else{ ++ return -1; ++ } ++ ++ return ret; ++} ++ ++/* ++ * hostkey_method_ssh_ecdsa_dtor ++ * ++ * Shutdown the hostkey by freeing EC_KEY context ++ */ ++static int ++hostkey_method_ssh_ecdsa_dtor(LIBSSH2_SESSION * session, void **abstract) ++{ ++ libssh2_ecdsa_ctx *keyctx = (libssh2_ecdsa_ctx *) (*abstract); ++ (void) session; ++ ++ if (keyctx != NULL) ++ _libssh2_ecdsa_free(keyctx); ++ ++ *abstract = NULL; ++ ++ return 0; ++} ++ ++static const LIBSSH2_HOSTKEY_METHOD hostkey_method_ecdsa_ssh_nistp256 = { ++ "ecdsa-sha2-nistp256", ++ SHA256_DIGEST_LENGTH, ++ hostkey_method_ssh_ecdsa_init, ++ hostkey_method_ssh_ecdsa_initPEM, ++ hostkey_method_ssh_ecdsa_initPEMFromMemory, ++ hostkey_method_ssh_ecdsa_sig_verify, ++ hostkey_method_ssh_ecdsa_signv, ++ NULL, /* encrypt */ ++ hostkey_method_ssh_ecdsa_dtor, ++}; ++ ++static const LIBSSH2_HOSTKEY_METHOD hostkey_method_ecdsa_ssh_nistp384 = { ++ "ecdsa-sha2-nistp384", ++ SHA384_DIGEST_LENGTH, ++ hostkey_method_ssh_ecdsa_init, ++ hostkey_method_ssh_ecdsa_initPEM, ++ hostkey_method_ssh_ecdsa_initPEMFromMemory, ++ hostkey_method_ssh_ecdsa_sig_verify, ++ hostkey_method_ssh_ecdsa_signv, ++ NULL, /* encrypt */ ++ hostkey_method_ssh_ecdsa_dtor, ++}; ++ ++static const LIBSSH2_HOSTKEY_METHOD hostkey_method_ecdsa_ssh_nistp521 = { ++ "ecdsa-sha2-nistp521", ++ SHA512_DIGEST_LENGTH, ++ hostkey_method_ssh_ecdsa_init, ++ hostkey_method_ssh_ecdsa_initPEM, ++ hostkey_method_ssh_ecdsa_initPEMFromMemory, ++ hostkey_method_ssh_ecdsa_sig_verify, ++ hostkey_method_ssh_ecdsa_signv, ++ NULL, /* encrypt */ ++ hostkey_method_ssh_ecdsa_dtor, ++}; ++#endif /* LIBSSH2_ECDSA */ ++ ++ + static const LIBSSH2_HOSTKEY_METHOD *hostkey_methods[] = { ++#if LIBSSH2_ECDSA ++ &hostkey_method_ecdsa_ssh_nistp256, ++ &hostkey_method_ecdsa_ssh_nistp384, ++ &hostkey_method_ecdsa_ssh_nistp521, ++#endif + #if LIBSSH2_RSA + &hostkey_method_ssh_rsa, + #endif /* LIBSSH2_RSA */ +@@ -505,7 +794,7 @@ libssh2_hostkey_methods(void) + * Returns hash signature + * Returned buffer should NOT be freed + * Length of buffer is determined by hash type +- * i.e. MD5 == 16, SHA1 == 20 ++ * i.e. MD5 == 16, SHA1 == 20, SHA256 == 32 + */ + LIBSSH2_API const char * + libssh2_hostkey_hash(LIBSSH2_SESSION * session, int hash_type) +@@ -523,6 +812,11 @@ libssh2_hostkey_hash(LIBSSH2_SESSION * s + ? (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; + } +@@ -536,6 +830,15 @@ static int hostkey_type(const unsigned c + const unsigned char dss[] = { + 0, 0, 0, 0x07, 's', 's', 'h', '-', 'd', 's', 's' + }; ++ const unsigned char ecdsa_256[] = { ++ 0, 0, 0, 0x13, 'e', 'c', 'd', 's', 'a', '-', 's', 'h', 'a', '2', '-', 'n', 'i', 's', 't', 'p', '2', '5', '6' ++ }; ++ const unsigned char ecdsa_384[] = { ++ 0, 0, 0, 0x13, 'e', 'c', 'd', 's', 'a', '-', 's', 'h', 'a', '2', '-', 'n', 'i', 's', 't', 'p', '3', '8', '4' ++ }; ++ const unsigned char ecdsa_521[] = { ++ 0, 0, 0, 0x13, 'e', 'c', 'd', 's', 'a', '-', 's', 'h', 'a', '2', '-', 'n', 'i', 's', 't', 'p', '5', '2', '1' ++ }; + + if (len < 11) + return LIBSSH2_HOSTKEY_TYPE_UNKNOWN; +@@ -546,6 +849,21 @@ static int hostkey_type(const unsigned c + if (!memcmp(dss, hostkey, 11)) + return LIBSSH2_HOSTKEY_TYPE_DSS; + ++ if ( len < 15 ) ++ return LIBSSH2_HOSTKEY_TYPE_UNKNOWN; ++ ++ if ( len < 23 ) ++ return LIBSSH2_HOSTKEY_TYPE_UNKNOWN; ++ ++ if(!memcmp(ecdsa_256, hostkey, 23)) ++ return LIBSSH2_HOSTKEY_TYPE_ECDSA_256; ++ ++ if(!memcmp(ecdsa_384, hostkey, 23)) ++ return LIBSSH2_HOSTKEY_TYPE_ECDSA_384; ++ ++ if(!memcmp(ecdsa_521, hostkey, 23)) ++ return LIBSSH2_HOSTKEY_TYPE_ECDSA_521; ++ + return LIBSSH2_HOSTKEY_TYPE_UNKNOWN; + } + +@@ -570,4 +888,3 @@ libssh2_session_hostkey(LIBSSH2_SESSION + *len = 0; + return NULL; + } +- Property changes on: head/security/libssh2/files/patch-src_hostkey.c ___________________________________________________________________ Added: fbsd:nokeywords ## -0,0 +1 ## +yes \ No newline at end of property Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: head/security/libssh2/files/patch-src_kex.c =================================================================== --- head/security/libssh2/files/patch-src_kex.c (nonexistent) +++ head/security/libssh2/files/patch-src_kex.c (revision 491663) @@ -0,0 +1,1040 @@ +--- src/kex.c.orig 2016-10-17 14:28:29 UTC ++++ src/kex.c +@@ -68,34 +68,47 @@ + libssh2_sha1_final(hash, (value) + len); \ + len += SHA_DIGEST_LENGTH; \ + } \ +- } ++ } \ + + +-/* Helper macro called from kex_method_diffie_hellman_group1_sha256_key_exchange */ +-#define LIBSSH2_KEX_METHOD_DIFFIE_HELLMAN_SHA256_HASH(value, reqlen, version) \ +- { \ +- libssh2_sha256_ctx hash; \ +- unsigned long len = 0; \ +- if (!(value)) { \ +- value = LIBSSH2_ALLOC(session, reqlen + SHA256_DIGEST_LENGTH); \ +- } \ +- if (value) \ +- while (len < (unsigned long)reqlen) { \ +- libssh2_sha256_init(&hash); \ +- libssh2_sha256_update(hash, exchange_state->k_value, \ +- exchange_state->k_value_len); \ +- libssh2_sha256_update(hash, exchange_state->h_sig_comp, \ +- SHA256_DIGEST_LENGTH); \ +- if (len > 0) { \ +- libssh2_sha256_update(hash, value, len); \ +- } else { \ +- libssh2_sha256_update(hash, (version), 1); \ +- libssh2_sha256_update(hash, session->session_id, \ +- session->session_id_len); \ +- } \ +- libssh2_sha256_final(hash, (value) + len); \ +- len += SHA256_DIGEST_LENGTH; \ +- } \ ++#define LIBSSH2_KEX_METHOD_EC_SHA_VALUE_HASH(value, reqlen, version) \ ++ { \ ++ if (type == LIBSSH2_EC_CURVE_NISTP256) { \ ++ LIBSSH2_KEX_METHOD_SHA_VALUE_HASH(256, value, reqlen, version); \ ++ } \ ++ else if (type == LIBSSH2_EC_CURVE_NISTP384 ) { \ ++ LIBSSH2_KEX_METHOD_SHA_VALUE_HASH(384, value, reqlen, version); \ ++ } \ ++ else if (type == LIBSSH2_EC_CURVE_NISTP521 ) { \ ++ LIBSSH2_KEX_METHOD_SHA_VALUE_HASH(512, value, reqlen, version); \ ++ } \ ++} \ ++ ++ ++#define LIBSSH2_KEX_METHOD_SHA_VALUE_HASH(digest_type, value, reqlen, version) \ ++ { \ ++ libssh2_sha##digest_type##_ctx hash; \ ++ unsigned long len = 0; \ ++ if (!(value)) { \ ++ value = LIBSSH2_ALLOC(session, reqlen + SHA##digest_type##_DIGEST_LENGTH); \ ++ } \ ++ if (value) \ ++ while (len < (unsigned long)reqlen) { \ ++ libssh2_sha##digest_type##_init(&hash); \ ++ libssh2_sha##digest_type##_update(hash, exchange_state->k_value, \ ++ exchange_state->k_value_len); \ ++ libssh2_sha##digest_type##_update(hash, exchange_state->h_sig_comp, \ ++ SHA##digest_type##_DIGEST_LENGTH); \ ++ if (len > 0) { \ ++ libssh2_sha##digest_type##_update(hash, value, len); \ ++ } else { \ ++ libssh2_sha##digest_type##_update(hash, (version), 1); \ ++ libssh2_sha##digest_type##_update(hash, session->session_id, \ ++ session->session_id_len); \ ++ } \ ++ libssh2_sha##digest_type##_final(hash, (value) + len); \ ++ len += SHA##digest_type##_DIGEST_LENGTH; \ ++ } \ + } + + +@@ -304,6 +317,62 @@ static int diffie_hellman_sha1(LIBSSH2_S + "Server's SHA1 Fingerprint: %s", fingerprint); + } + #endif /* LIBSSH2DEBUG */ ++ ++ { ++ libssh2_sha256_ctx fingerprint_ctx; ++ ++ if (libssh2_sha256_init(&fingerprint_ctx)) { ++ libssh2_sha256_update(fingerprint_ctx, session->server_hostkey, ++ session->server_hostkey_len); ++ libssh2_sha256_final(fingerprint_ctx, ++ session->server_hostkey_sha256); ++ session->server_hostkey_sha256_valid = TRUE; ++ } ++ else { ++ session->server_hostkey_sha256_valid = FALSE; ++ } ++ } ++#ifdef LIBSSH2DEBUG ++ { ++ char *base64Fingerprint = NULL; ++ _libssh2_base64_encode(session, (const char*)session->server_hostkey_sha256, ++ SHA256_DIGEST_LENGTH, &base64Fingerprint); ++ if (base64Fingerprint != NULL) { ++ _libssh2_debug(session, LIBSSH2_TRACE_KEX, ++ "Server's SHA256 Fingerprint: %s", base64Fingerprint); ++ LIBSSH2_FREE(session, base64Fingerprint); ++ } ++ } ++#endif /* LIBSSH2DEBUG */ ++ ++ ++ { ++ libssh2_sha256_ctx fingerprint_ctx; ++ ++ if (libssh2_sha256_init(&fingerprint_ctx)) { ++ libssh2_sha256_update(fingerprint_ctx, session->server_hostkey, ++ session->server_hostkey_len); ++ libssh2_sha256_final(fingerprint_ctx, ++ session->server_hostkey_sha256); ++ session->server_hostkey_sha256_valid = TRUE; ++ } ++ else { ++ session->server_hostkey_sha256_valid = FALSE; ++ } ++ } ++#ifdef LIBSSH2DEBUG ++ { ++ char *base64Fingerprint = NULL; ++ _libssh2_base64_encode(session, (const char*)session->server_hostkey_sha256, ++ SHA256_DIGEST_LENGTH, &base64Fingerprint); ++ if (base64Fingerprint != NULL) { ++ _libssh2_debug(session, LIBSSH2_TRACE_KEX, ++ "Server's SHA256 Fingerprint: %s", base64Fingerprint); ++ LIBSSH2_FREE(session, base64Fingerprint); ++ } ++ } ++#endif /* LIBSSH2DEBUG */ ++ + + if (session->hostkey->init(session, session->server_hostkey, + session->server_hostkey_len, +@@ -924,6 +993,60 @@ static int diffie_hellman_sha256(LIBSSH2 + "Server's SHA1 Fingerprint: %s", fingerprint); + } + #endif /* LIBSSH2DEBUG */ ++ ++ { ++ libssh2_sha256_ctx fingerprint_ctx; ++ ++ if (libssh2_sha256_init(&fingerprint_ctx)) { ++ libssh2_sha256_update(fingerprint_ctx, session->server_hostkey, ++ session->server_hostkey_len); ++ libssh2_sha256_final(fingerprint_ctx, ++ session->server_hostkey_sha256); ++ session->server_hostkey_sha256_valid = TRUE; ++ } ++ else { ++ session->server_hostkey_sha256_valid = FALSE; ++ } ++ } ++#ifdef LIBSSH2DEBUG ++ { ++ char *base64Fingerprint = NULL; ++ _libssh2_base64_encode(session, (const char*)session->server_hostkey_sha256, ++ SHA256_DIGEST_LENGTH, &base64Fingerprint); ++ if (base64Fingerprint != NULL) { ++ _libssh2_debug(session, LIBSSH2_TRACE_KEX, ++ "Server's SHA256 Fingerprint: %s", base64Fingerprint); ++ LIBSSH2_FREE(session, base64Fingerprint); ++ } ++ } ++#endif /* LIBSSH2DEBUG */ ++ ++ { ++ libssh2_sha256_ctx fingerprint_ctx; ++ ++ if (libssh2_sha256_init(&fingerprint_ctx)) { ++ libssh2_sha256_update(fingerprint_ctx, session->server_hostkey, ++ session->server_hostkey_len); ++ libssh2_sha256_final(fingerprint_ctx, ++ session->server_hostkey_sha256); ++ session->server_hostkey_sha256_valid = TRUE; ++ } ++ else { ++ session->server_hostkey_sha256_valid = FALSE; ++ } ++ } ++#ifdef LIBSSH2DEBUG ++ { ++ char *base64Fingerprint = NULL; ++ _libssh2_base64_encode(session, (const char*)session->server_hostkey_sha256, ++ SHA256_DIGEST_LENGTH, &base64Fingerprint); ++ if (base64Fingerprint != NULL) { ++ _libssh2_debug(session, LIBSSH2_TRACE_KEX, ++ "Server's SHA256 Fingerprint: %s", base64Fingerprint); ++ LIBSSH2_FREE(session, base64Fingerprint); ++ } ++ } ++#endif /* LIBSSH2DEBUG */ + + if (session->hostkey->init(session, session->server_hostkey, + session->server_hostkey_len, +@@ -1137,16 +1260,18 @@ static int diffie_hellman_sha256(LIBSSH2 + unsigned char *iv = NULL, *secret = NULL; + int free_iv = 0, free_secret = 0; + +- LIBSSH2_KEX_METHOD_DIFFIE_HELLMAN_SHA256_HASH(iv, +- session->local.crypt-> +- iv_len, "A"); ++ LIBSSH2_KEX_METHOD_SHA_VALUE_HASH(256, iv, ++ session->local.crypt-> ++ iv_len, ++ (const unsigned char *)"A"); + if (!iv) { + ret = -1; + goto clean_exit; + } +- LIBSSH2_KEX_METHOD_DIFFIE_HELLMAN_SHA256_HASH(secret, +- session->local.crypt-> +- secret_len, "C"); ++ LIBSSH2_KEX_METHOD_SHA_VALUE_HASH(256, secret, ++ session->local.crypt-> ++ secret_len, ++ (const unsigned char *)"C"); + if (!secret) { + LIBSSH2_FREE(session, iv); + ret = LIBSSH2_ERROR_KEX_FAILURE; +@@ -1184,16 +1309,18 @@ static int diffie_hellman_sha256(LIBSSH2 + unsigned char *iv = NULL, *secret = NULL; + int free_iv = 0, free_secret = 0; + +- LIBSSH2_KEX_METHOD_DIFFIE_HELLMAN_SHA256_HASH(iv, +- session->remote.crypt-> +- iv_len, "B"); ++ LIBSSH2_KEX_METHOD_SHA_VALUE_HASH(256, iv, ++ session->remote.crypt-> ++ iv_len, ++ (const unsigned char *)"B"); + if (!iv) { + ret = LIBSSH2_ERROR_KEX_FAILURE; + goto clean_exit; + } +- LIBSSH2_KEX_METHOD_DIFFIE_HELLMAN_SHA256_HASH(secret, +- session->remote.crypt-> +- secret_len, "D"); ++ LIBSSH2_KEX_METHOD_SHA_VALUE_HASH(256, secret, ++ session->remote.crypt-> ++ secret_len, ++ (const unsigned char *)"D"); + if (!secret) { + LIBSSH2_FREE(session, iv); + ret = LIBSSH2_ERROR_KEX_FAILURE; +@@ -1229,9 +1356,10 @@ static int diffie_hellman_sha256(LIBSSH2 + unsigned char *key = NULL; + int free_key = 0; + +- LIBSSH2_KEX_METHOD_DIFFIE_HELLMAN_SHA256_HASH(key, +- session->local.mac-> +- key_len, "E"); ++ LIBSSH2_KEX_METHOD_SHA_VALUE_HASH(256, key, ++ session->local.mac-> ++ key_len, ++ (const unsigned char *)"E"); + if (!key) { + ret = LIBSSH2_ERROR_KEX_FAILURE; + goto clean_exit; +@@ -1255,9 +1383,10 @@ static int diffie_hellman_sha256(LIBSSH2 + unsigned char *key = NULL; + int free_key = 0; + +- LIBSSH2_KEX_METHOD_DIFFIE_HELLMAN_SHA256_HASH(key, +- session->remote.mac-> +- key_len, "F"); ++ LIBSSH2_KEX_METHOD_SHA_VALUE_HASH(256, key, ++ session->remote.mac-> ++ key_len, ++ (const unsigned char *)"F"); + if (!key) { + ret = LIBSSH2_ERROR_KEX_FAILURE; + goto clean_exit; +@@ -1678,6 +1807,725 @@ kex_method_diffie_hellman_group_exchange + } + + ++#if LIBSSH2_ECDSA ++ ++/* kex_session_ecdh_curve_type ++ * returns the EC curve type by name used in key exchange ++ */ ++ ++static int ++kex_session_ecdh_curve_type(const char *name, libssh2_curve_type *out_type) ++{ ++ int ret = 0; ++ libssh2_curve_type type; ++ ++ if ( name == NULL ) ++ return -1; ++ ++ if ( strcmp(name, "ecdh-sha2-nistp256") == 0) ++ type = LIBSSH2_EC_CURVE_NISTP256; ++ else if ( strcmp(name, "ecdh-sha2-nistp384") == 0) ++ type = LIBSSH2_EC_CURVE_NISTP384; ++ else if ( strcmp(name, "ecdh-sha2-nistp521") == 0) ++ type = LIBSSH2_EC_CURVE_NISTP521; ++ else { ++ ret = -1; ++ } ++ ++ if (ret == 0 && out_type) { ++ *out_type = type; ++ } ++ ++ return ret; ++} ++ ++ ++/* LIBSSH2_KEX_METHOD_EC_SHA_HASH_CREATE_VERIFY ++ * ++ * Macro that create and verifies EC SHA hash with a given digest bytes ++ * ++ * Payload format: ++ * ++ * string V_C, client's identification string (CR and LF excluded) ++ * string V_S, server's identification string (CR and LF excluded) ++ * string I_C, payload of the client's SSH_MSG_KEXINIT ++ * string I_S, payload of the server's SSH_MSG_KEXINIT ++ * string K_S, server's public host key ++ * string Q_C, client's ephemeral public key octet string ++ * string Q_S, server's ephemeral public key octet string ++ * mpint K, shared secret ++ * ++ */ ++ ++#define LIBSSH2_KEX_METHOD_EC_SHA_HASH_CREATE_VERIFY(digest_type) \ ++ { \ ++ \ ++ libssh2_sha##digest_type##_ctx ctx; \ ++ exchange_state->exchange_hash = (void*)&ctx; \ ++ \ ++ libssh2_sha##digest_type##_init(&ctx); \ ++ if (session->local.banner) { \ ++ _libssh2_htonu32(exchange_state->h_sig_comp, \ ++ strlen((char *) session->local.banner) - 2); \ ++ libssh2_sha##digest_type##_update(ctx, \ ++ exchange_state->h_sig_comp, 4); \ ++ libssh2_sha##digest_type##_update(ctx, \ ++ (char *) session->local.banner, \ ++ strlen((char *) session->local.banner) - 2); \ ++ } else { \ ++ _libssh2_htonu32(exchange_state->h_sig_comp, \ ++ sizeof(LIBSSH2_SSH_DEFAULT_BANNER) - 1); \ ++ libssh2_sha##digest_type##_update(ctx, \ ++ exchange_state->h_sig_comp, 4); \ ++ libssh2_sha##digest_type##_update(ctx, \ ++ LIBSSH2_SSH_DEFAULT_BANNER, \ ++ sizeof(LIBSSH2_SSH_DEFAULT_BANNER) - 1); \ ++ } \ ++ \ ++ _libssh2_htonu32(exchange_state->h_sig_comp, \ ++ strlen((char *) session->remote.banner)); \ ++ libssh2_sha##digest_type##_update(ctx, \ ++ exchange_state->h_sig_comp, 4); \ ++ libssh2_sha##digest_type##_update(ctx, \ ++ session->remote.banner, \ ++ strlen((char *) session->remote.banner)); \ ++ \ ++ _libssh2_htonu32(exchange_state->h_sig_comp, \ ++ session->local.kexinit_len); \ ++ libssh2_sha##digest_type##_update(ctx, \ ++ exchange_state->h_sig_comp, 4); \ ++ libssh2_sha##digest_type##_update(ctx, \ ++ session->local.kexinit, \ ++ session->local.kexinit_len); \ ++ \ ++ _libssh2_htonu32(exchange_state->h_sig_comp, \ ++ session->remote.kexinit_len); \ ++ libssh2_sha##digest_type##_update(ctx, \ ++ exchange_state->h_sig_comp, 4); \ ++ libssh2_sha##digest_type##_update(ctx, \ ++ session->remote.kexinit, \ ++ session->remote.kexinit_len); \ ++ \ ++ _libssh2_htonu32(exchange_state->h_sig_comp, \ ++ session->server_hostkey_len); \ ++ libssh2_sha##digest_type##_update(ctx, \ ++ exchange_state->h_sig_comp, 4); \ ++ libssh2_sha##digest_type##_update(ctx, \ ++ session->server_hostkey, \ ++ session->server_hostkey_len); \ ++ \ ++ _libssh2_htonu32(exchange_state->h_sig_comp, \ ++ public_key_len); \ ++ libssh2_sha##digest_type##_update(ctx, \ ++ exchange_state->h_sig_comp, 4); \ ++ libssh2_sha##digest_type##_update(ctx, \ ++ public_key, \ ++ public_key_len); \ ++ \ ++ _libssh2_htonu32(exchange_state->h_sig_comp, \ ++ server_public_key_len); \ ++ libssh2_sha##digest_type##_update(ctx, \ ++ exchange_state->h_sig_comp, 4); \ ++ libssh2_sha##digest_type##_update(ctx, \ ++ server_public_key, \ ++ server_public_key_len); \ ++ \ ++ libssh2_sha##digest_type##_update(ctx, \ ++ exchange_state->k_value, \ ++ exchange_state->k_value_len); \ ++ \ ++ libssh2_sha##digest_type##_final(ctx, exchange_state->h_sig_comp); \ ++ \ ++ if (session->hostkey-> \ ++ sig_verify(session, exchange_state->h_sig, \ ++ exchange_state->h_sig_len, exchange_state->h_sig_comp, \ ++ SHA##digest_type##_DIGEST_LENGTH, &session->server_hostkey_abstract)) { \ ++ rc = -1; \ ++ } \ ++ } \ ++ ++ ++/* ecdh_sha2_nistp ++ * Elliptic Curve Diffie Hellman Key Exchange ++ */ ++ ++static int ecdh_sha2_nistp(LIBSSH2_SESSION *session, libssh2_curve_type type, ++ unsigned char *data, size_t data_len, unsigned char *public_key, ++ size_t public_key_len, _libssh2_ec_key *private_key, ++ kmdhgGPshakex_state_t *exchange_state) ++{ ++ int ret = 0; ++ int rc; ++ ++ if (exchange_state->state == libssh2_NB_state_idle) { ++ ++ /* Setup initial values */ ++ exchange_state->k = _libssh2_bn_init(); ++ ++ exchange_state->state = libssh2_NB_state_created; ++ } ++ ++ if ( exchange_state->state == libssh2_NB_state_created ) ++ { ++ /* parse INIT reply data */ ++ ++ /* host key K_S */ ++ unsigned char *s = data + 1; /* Advance past packet type */ ++ unsigned char *server_public_key; ++ size_t server_public_key_len; ++ size_t host_sig_len; ++ ++ session->server_hostkey_len = _libssh2_ntohu32((const unsigned char*)s); ++ s += 4; ++ ++ session->server_hostkey = LIBSSH2_ALLOC(session, session->server_hostkey_len); ++ if (!session->server_hostkey) { ++ ret = _libssh2_error(session, LIBSSH2_ERROR_ALLOC, ++ "Unable to allocate memory for a copy " ++ "of the host key"); ++ goto clean_exit; ++ } ++ ++ memcpy(session->server_hostkey, s, session->server_hostkey_len); ++ s += session->server_hostkey_len; ++ ++#if LIBSSH2_MD5 ++ { ++ libssh2_md5_ctx fingerprint_ctx; ++ ++ if (libssh2_md5_init(&fingerprint_ctx)) { ++ libssh2_md5_update(fingerprint_ctx, session->server_hostkey, ++ session->server_hostkey_len); ++ libssh2_md5_final(fingerprint_ctx, session->server_hostkey_md5); ++ session->server_hostkey_md5_valid = TRUE; ++ } ++ else { ++ session->server_hostkey_md5_valid = FALSE; ++ } ++ } ++#ifdef LIBSSH2DEBUG ++ { ++ char fingerprint[50], *fprint = fingerprint; ++ int i; ++ for(i = 0; i < 16; i++, fprint += 3) { ++ snprintf(fprint, 4, "%02x:", session->server_hostkey_md5[i]); ++ } ++ *(--fprint) = '\0'; ++ _libssh2_debug(session, LIBSSH2_TRACE_KEX, ++ "Server's MD5 Fingerprint: %s", fingerprint); ++ } ++#endif /* LIBSSH2DEBUG */ ++#endif /* ! LIBSSH2_MD5 */ ++ ++ { ++ libssh2_sha1_ctx fingerprint_ctx; ++ ++ if (libssh2_sha1_init(&fingerprint_ctx)) { ++ libssh2_sha1_update(fingerprint_ctx, session->server_hostkey, ++ session->server_hostkey_len); ++ libssh2_sha1_final(fingerprint_ctx, session->server_hostkey_sha1); ++ session->server_hostkey_sha1_valid = TRUE; ++ } ++ else { ++ session->server_hostkey_sha1_valid = FALSE; ++ } ++ } ++#ifdef LIBSSH2DEBUG ++ { ++ char fingerprint[64], *fprint = fingerprint; ++ int i; ++ ++ for(i = 0; i < 20; i++, fprint += 3) { ++ snprintf(fprint, 4, "%02x:", session->server_hostkey_sha1[i]); ++ } ++ *(--fprint) = '\0'; ++ _libssh2_debug(session, LIBSSH2_TRACE_KEX, ++ "Server's SHA1 Fingerprint: %s", fingerprint); ++ } ++#endif /* LIBSSH2DEBUG */ ++ ++ /* SHA256 */ ++ { ++ libssh2_sha256_ctx fingerprint_ctx; ++ ++ if (libssh2_sha256_init(&fingerprint_ctx)) { ++ libssh2_sha256_update(fingerprint_ctx, session->server_hostkey, ++ session->server_hostkey_len); ++ libssh2_sha256_final(fingerprint_ctx, session->server_hostkey_sha256); ++ session->server_hostkey_sha256_valid = TRUE; ++ } ++ else { ++ session->server_hostkey_sha256_valid = FALSE; ++ } ++ } ++#ifdef LIBSSH2DEBUG ++ { ++ char *base64Fingerprint = NULL; ++ _libssh2_base64_encode(session, (const char*)session->server_hostkey_sha256, SHA256_DIGEST_LENGTH, &base64Fingerprint); ++ if ( base64Fingerprint != NULL ) { ++ _libssh2_debug(session, LIBSSH2_TRACE_KEX, ++ "Server's SHA256 Fingerprint: %s", base64Fingerprint); ++ LIBSSH2_FREE(session, base64Fingerprint); ++ } ++ } ++#endif /* LIBSSH2DEBUG */ ++ ++ if (session->hostkey->init(session, session->server_hostkey, ++ session->server_hostkey_len, ++ &session->server_hostkey_abstract)) { ++ ret = _libssh2_error(session, LIBSSH2_ERROR_HOSTKEY_INIT, ++ "Unable to initialize hostkey importer"); ++ goto clean_exit; ++ } ++ ++ /* server public key Q_S */ ++ server_public_key_len = _libssh2_ntohu32((const unsigned char*)s); ++ s += 4; ++ ++ server_public_key = s; ++ s += server_public_key_len; ++ ++ /* server signature */ ++ host_sig_len = _libssh2_ntohu32((const unsigned char*)s); ++ s += 4; ++ ++ exchange_state->h_sig = s; ++ exchange_state->h_sig_len = host_sig_len; ++ s += host_sig_len; ++ ++ /* Compute the shared secret K */ ++ rc = _libssh2_ecdh_gen_k(&exchange_state->k, private_key, server_public_key, server_public_key_len); ++ if ( rc != 0 ) { ++ ret = _libssh2_error(session, LIBSSH2_ERROR_KEX_FAILURE, ++ "Unable to create ECDH shared secret"); ++ goto clean_exit; ++ } ++ ++ exchange_state->k_value_len = _libssh2_bn_bytes(exchange_state->k) + 5; ++ if (_libssh2_bn_bits(exchange_state->k) % 8) { ++ /* don't need leading 00 */ ++ exchange_state->k_value_len--; ++ } ++ exchange_state->k_value = ++ LIBSSH2_ALLOC(session, exchange_state->k_value_len); ++ if (!exchange_state->k_value) { ++ ret = _libssh2_error(session, LIBSSH2_ERROR_ALLOC, ++ "Unable to allocate buffer for K"); ++ goto clean_exit; ++ } ++ _libssh2_htonu32(exchange_state->k_value, ++ exchange_state->k_value_len - 4); ++ if (_libssh2_bn_bits(exchange_state->k) % 8) { ++ _libssh2_bn_to_bin(exchange_state->k, exchange_state->k_value + 4); ++ } else { ++ exchange_state->k_value[4] = 0; ++ _libssh2_bn_to_bin(exchange_state->k, exchange_state->k_value + 5); ++ } ++ ++ /* verify hash */ ++ ++ switch ( type ) { ++ case LIBSSH2_EC_CURVE_NISTP256: ++ LIBSSH2_KEX_METHOD_EC_SHA_HASH_CREATE_VERIFY(256); ++ break; ++ ++ case LIBSSH2_EC_CURVE_NISTP384: ++ LIBSSH2_KEX_METHOD_EC_SHA_HASH_CREATE_VERIFY(384); ++ break; ++ case LIBSSH2_EC_CURVE_NISTP521: ++ LIBSSH2_KEX_METHOD_EC_SHA_HASH_CREATE_VERIFY(512); ++ break; ++ } ++ ++ if ( rc != 0 ) { ++ ret = _libssh2_error(session, LIBSSH2_ERROR_HOSTKEY_SIGN, ++ "Unable to verify hostkey signature"); ++ goto clean_exit; ++ } ++ ++ exchange_state->c = SSH_MSG_NEWKEYS; ++ exchange_state->state = libssh2_NB_state_sent; ++ } ++ ++ if (exchange_state->state == libssh2_NB_state_sent) { ++ rc = _libssh2_transport_send(session, &exchange_state->c, 1, NULL, 0); ++ if (rc == LIBSSH2_ERROR_EAGAIN) { ++ return rc; ++ } else if (rc) { ++ ret = _libssh2_error(session, rc, "Unable to send NEWKEYS message"); ++ goto clean_exit; ++ } ++ ++ exchange_state->state = libssh2_NB_state_sent2; ++ } ++ ++ if (exchange_state->state == libssh2_NB_state_sent2) { ++ rc = _libssh2_packet_require(session, SSH_MSG_NEWKEYS, ++ &exchange_state->tmp, ++ &exchange_state->tmp_len, 0, NULL, 0, ++ &exchange_state->req_state); ++ if (rc == LIBSSH2_ERROR_EAGAIN) { ++ return rc; ++ } else if (rc) { ++ ret = _libssh2_error(session, rc, "Timed out waiting for NEWKEYS"); ++ goto clean_exit; ++ } ++ ++ /* The first key exchange has been performed, ++ switch to active crypt/comp/mac mode */ ++ session->state |= LIBSSH2_STATE_NEWKEYS; ++ _libssh2_debug(session, LIBSSH2_TRACE_KEX, "Received NEWKEYS message"); ++ ++ /* This will actually end up being just packet_type(1) ++ for this packet type anyway */ ++ LIBSSH2_FREE(session, exchange_state->tmp); ++ ++ if (!session->session_id) { ++ ++ size_t digest_length = 0; ++ ++ if ( type == LIBSSH2_EC_CURVE_NISTP256 ) ++ digest_length = SHA256_DIGEST_LENGTH; ++ else if ( type == LIBSSH2_EC_CURVE_NISTP384 ) ++ digest_length = SHA384_DIGEST_LENGTH; ++ else if ( type == LIBSSH2_EC_CURVE_NISTP521 ) ++ digest_length = SHA512_DIGEST_LENGTH; ++ else{ ++ ret = _libssh2_error(session, LIBSSH2_ERROR_KEX_FAILURE, ++ "Unknown SHA digest for EC curve"); ++ goto clean_exit; ++ ++ } ++ session->session_id = LIBSSH2_ALLOC(session, digest_length); ++ if (!session->session_id) { ++ ret = _libssh2_error(session, LIBSSH2_ERROR_ALLOC, ++ "Unable to allocate buffer for SHA digest"); ++ goto clean_exit; ++ } ++ memcpy(session->session_id, exchange_state->h_sig_comp, ++ digest_length); ++ session->session_id_len = digest_length; ++ _libssh2_debug(session, LIBSSH2_TRACE_KEX, "session_id calculated"); ++ } ++ ++ /* Cleanup any existing cipher */ ++ if (session->local.crypt->dtor) { ++ session->local.crypt->dtor(session, ++ &session->local.crypt_abstract); ++ } ++ ++ /* Calculate IV/Secret/Key for each direction */ ++ if (session->local.crypt->init) { ++ unsigned char *iv = NULL, *secret = NULL; ++ int free_iv = 0, free_secret = 0; ++ ++ LIBSSH2_KEX_METHOD_EC_SHA_VALUE_HASH(iv, ++ session->local.crypt-> ++ iv_len, "A"); ++ if (!iv) { ++ ret = -1; ++ goto clean_exit; ++ } ++ ++ LIBSSH2_KEX_METHOD_EC_SHA_VALUE_HASH(secret, ++ session->local.crypt-> ++ secret_len, "C"); ++ ++ if (!secret) { ++ LIBSSH2_FREE(session, iv); ++ ret = LIBSSH2_ERROR_KEX_FAILURE; ++ goto clean_exit; ++ } ++ if (session->local.crypt-> ++ init(session, session->local.crypt, iv, &free_iv, secret, ++ &free_secret, 1, &session->local.crypt_abstract)) { ++ LIBSSH2_FREE(session, iv); ++ LIBSSH2_FREE(session, secret); ++ ret = LIBSSH2_ERROR_KEX_FAILURE; ++ goto clean_exit; ++ } ++ ++ if (free_iv) { ++ memset(iv, 0, session->local.crypt->iv_len); ++ LIBSSH2_FREE(session, iv); ++ } ++ ++ if (free_secret) { ++ memset(secret, 0, session->local.crypt->secret_len); ++ LIBSSH2_FREE(session, secret); ++ } ++ } ++ _libssh2_debug(session, LIBSSH2_TRACE_KEX, ++ "Client to Server IV and Key calculated"); ++ ++ if (session->remote.crypt->dtor) { ++ /* Cleanup any existing cipher */ ++ session->remote.crypt->dtor(session, ++ &session->remote.crypt_abstract); ++ } ++ ++ if (session->remote.crypt->init) { ++ unsigned char *iv = NULL, *secret = NULL; ++ int free_iv = 0, free_secret = 0; ++ ++ LIBSSH2_KEX_METHOD_EC_SHA_VALUE_HASH(iv, ++ session->remote.crypt-> ++ iv_len, "B"); ++ ++ if (!iv) { ++ ret = LIBSSH2_ERROR_KEX_FAILURE; ++ goto clean_exit; ++ } ++ LIBSSH2_KEX_METHOD_EC_SHA_VALUE_HASH(secret, ++ session->remote.crypt-> ++ secret_len, "D"); ++ ++ if (!secret) { ++ LIBSSH2_FREE(session, iv); ++ ret = LIBSSH2_ERROR_KEX_FAILURE; ++ goto clean_exit; ++ } ++ if (session->remote.crypt-> ++ init(session, session->remote.crypt, iv, &free_iv, secret, ++ &free_secret, 0, &session->remote.crypt_abstract)) { ++ LIBSSH2_FREE(session, iv); ++ LIBSSH2_FREE(session, secret); ++ ret = LIBSSH2_ERROR_KEX_FAILURE; ++ goto clean_exit; ++ } ++ ++ if (free_iv) { ++ memset(iv, 0, session->remote.crypt->iv_len); ++ LIBSSH2_FREE(session, iv); ++ } ++ ++ if (free_secret) { ++ memset(secret, 0, session->remote.crypt->secret_len); ++ LIBSSH2_FREE(session, secret); ++ } ++ } ++ _libssh2_debug(session, LIBSSH2_TRACE_KEX, ++ "Server to Client IV and Key calculated"); ++ ++ if (session->local.mac->dtor) { ++ session->local.mac->dtor(session, &session->local.mac_abstract); ++ } ++ ++ if (session->local.mac->init) { ++ unsigned char *key = NULL; ++ int free_key = 0; ++ ++ LIBSSH2_KEX_METHOD_EC_SHA_VALUE_HASH(key, ++ session->local.mac-> ++ key_len, "E"); ++ ++ if (!key) { ++ ret = LIBSSH2_ERROR_KEX_FAILURE; ++ goto clean_exit; ++ } ++ session->local.mac->init(session, key, &free_key, ++ &session->local.mac_abstract); ++ ++ if (free_key) { ++ memset(key, 0, session->local.mac->key_len); ++ LIBSSH2_FREE(session, key); ++ } ++ } ++ _libssh2_debug(session, LIBSSH2_TRACE_KEX, ++ "Client to Server HMAC Key calculated"); ++ ++ if (session->remote.mac->dtor) { ++ session->remote.mac->dtor(session, &session->remote.mac_abstract); ++ } ++ ++ if (session->remote.mac->init) { ++ unsigned char *key = NULL; ++ int free_key = 0; ++ ++ LIBSSH2_KEX_METHOD_EC_SHA_VALUE_HASH(key, ++ session->remote.mac-> ++ key_len, "F"); ++ ++ if (!key) { ++ ret = LIBSSH2_ERROR_KEX_FAILURE; ++ goto clean_exit; ++ } ++ session->remote.mac->init(session, key, &free_key, ++ &session->remote.mac_abstract); ++ ++ if (free_key) { ++ memset(key, 0, session->remote.mac->key_len); ++ LIBSSH2_FREE(session, key); ++ } ++ } ++ _libssh2_debug(session, LIBSSH2_TRACE_KEX, ++ "Server to Client HMAC Key calculated"); ++ ++ /* Initialize compression for each direction */ ++ ++ /* Cleanup any existing compression */ ++ if (session->local.comp && session->local.comp->dtor) { ++ session->local.comp->dtor(session, 1, ++ &session->local.comp_abstract); ++ } ++ ++ if (session->local.comp && session->local.comp->init) { ++ if (session->local.comp->init(session, 1, ++ &session->local.comp_abstract)) { ++ ret = LIBSSH2_ERROR_KEX_FAILURE; ++ goto clean_exit; ++ } ++ } ++ _libssh2_debug(session, LIBSSH2_TRACE_KEX, ++ "Client to Server compression initialized"); ++ ++ if (session->remote.comp && session->remote.comp->dtor) { ++ session->remote.comp->dtor(session, 0, ++ &session->remote.comp_abstract); ++ } ++ ++ if (session->remote.comp && session->remote.comp->init) { ++ if (session->remote.comp->init(session, 0, ++ &session->remote.comp_abstract)) { ++ ret = LIBSSH2_ERROR_KEX_FAILURE; ++ goto clean_exit; ++ } ++ } ++ _libssh2_debug(session, LIBSSH2_TRACE_KEX, ++ "Server to Client compression initialized"); ++ ++ } ++ ++clean_exit: ++ _libssh2_bn_free(exchange_state->k); ++ exchange_state->k = NULL; ++ ++ if (exchange_state->k_value) { ++ LIBSSH2_FREE(session, exchange_state->k_value); ++ exchange_state->k_value = NULL; ++ } ++ ++ exchange_state->state = libssh2_NB_state_idle; ++ ++ return ret; ++} ++ ++/* kex_method_ecdh_key_exchange ++ * ++ * Elliptic Curve Diffie Hellman Key Exchange ++ * supports SHA256/384/512 hashes based on negotated ecdh method ++ * ++ */ ++ ++static int ++kex_method_ecdh_key_exchange ++(LIBSSH2_SESSION * session, key_exchange_state_low_t * key_state) ++{ ++ int ret = 0; ++ int rc = 0; ++ unsigned char *s; ++ libssh2_curve_type type; ++ ++ if (key_state->state == libssh2_NB_state_idle) { ++ ++ key_state->public_key_oct = NULL; ++ key_state->state = libssh2_NB_state_created; ++ } ++ ++ if ( key_state->state == libssh2_NB_state_created ) ++ { ++ rc = kex_session_ecdh_curve_type(session->kex->name, &type); ++ ++ if ( rc != 0 ) { ++ ret = _libssh2_error(session, -1, ++ "Unknown KEX nistp curve type"); ++ goto ecdh_clean_exit; ++ } ++ ++ rc = _libssh2_ecdsa_create_key(&key_state->private_key, &key_state->public_key_oct, ++ &key_state->public_key_oct_len, type); ++ ++ if ( rc != 0 ) ++ { ++ ret = _libssh2_error(session, rc, ++ "Unable to create private key"); ++ goto ecdh_clean_exit; ++ } ++ ++ key_state->request[0] = SSH2_MSG_KEX_ECDH_INIT; ++ s = key_state->request + 1; ++ _libssh2_store_str(&s, (const char*)key_state->public_key_oct, key_state->public_key_oct_len); ++ key_state->request_len = key_state->public_key_oct_len + 5; ++ ++ _libssh2_debug(session, LIBSSH2_TRACE_KEX, ++ "Initiating ECDH SHA2 NISTP256"); ++ ++ key_state->state = libssh2_NB_state_sent; ++ } ++ ++ if ( key_state->state == libssh2_NB_state_sent ) { ++ rc = _libssh2_transport_send(session, key_state->request, ++ key_state->request_len, NULL, 0); ++ if (rc == LIBSSH2_ERROR_EAGAIN) { ++ return rc; ++ } else if (rc) { ++ ret = _libssh2_error(session, rc, ++ "Unable to send ECDH_INIT"); ++ goto ecdh_clean_exit; ++ } ++ ++ key_state->state = libssh2_NB_state_sent1; ++ } ++ ++ if ( key_state->state == libssh2_NB_state_sent1 ) { ++ rc = _libssh2_packet_require(session, SSH2_MSG_KEX_ECDH_REPLY, ++ &key_state->data, &key_state->data_len, ++ 0, NULL, 0, &key_state->req_state); ++ if (rc == LIBSSH2_ERROR_EAGAIN) { ++ return rc; ++ } else if (rc) { ++ ret = _libssh2_error(session, rc, ++ "Timeout waiting for ECDH_REPLY reply"); ++ goto ecdh_clean_exit; ++ } ++ ++ key_state->state = libssh2_NB_state_sent2; ++ } ++ ++ if ( key_state->state == libssh2_NB_state_sent2 ) { ++ ++ (void)kex_session_ecdh_curve_type(session->kex->name, &type); ++ ++ ret = ecdh_sha2_nistp(session, type, key_state->data, key_state->data_len, (unsigned char*)key_state->public_key_oct, ++ key_state->public_key_oct_len, key_state->private_key, &key_state->exchange_state); ++ ++ if (ret == LIBSSH2_ERROR_EAGAIN) { ++ return ret; ++ } ++ ++ LIBSSH2_FREE(session, key_state->data); ++ } ++ ++ecdh_clean_exit: ++ ++ if (key_state->public_key_oct) { ++ free(key_state->public_key_oct); ++ key_state->public_key_oct = NULL; ++ } ++ ++ if (key_state->private_key) { ++ _libssh2_ecdsa_free(key_state->private_key); ++ key_state->private_key = NULL; ++ } ++ ++ key_state->state = libssh2_NB_state_idle; ++ ++ return ret; ++} ++ ++#endif /*LIBSSH2_ECDSA*/ ++ ++ + #define LIBSSH2_KEX_METHOD_FLAG_REQ_ENC_HOSTKEY 0x0001 + #define LIBSSH2_KEX_METHOD_FLAG_REQ_SIGN_HOSTKEY 0x0002 + +@@ -1707,7 +2555,35 @@ kex_method_diffie_helman_group_exchange_ + LIBSSH2_KEX_METHOD_FLAG_REQ_SIGN_HOSTKEY, + }; + ++#if LIBSSH2_ECDSA ++static const LIBSSH2_KEX_METHOD ++kex_method_ecdh_sha2_nistp256 = { ++ "ecdh-sha2-nistp256", ++ kex_method_ecdh_key_exchange, ++ LIBSSH2_KEX_METHOD_FLAG_REQ_SIGN_HOSTKEY, ++}; ++ ++static const LIBSSH2_KEX_METHOD ++kex_method_ecdh_sha2_nistp384 = { ++ "ecdh-sha2-nistp384", ++ kex_method_ecdh_key_exchange, ++ LIBSSH2_KEX_METHOD_FLAG_REQ_SIGN_HOSTKEY, ++}; ++ ++static const LIBSSH2_KEX_METHOD ++kex_method_ecdh_sha2_nistp521 = { ++ "ecdh-sha2-nistp521", ++ kex_method_ecdh_key_exchange, ++ LIBSSH2_KEX_METHOD_FLAG_REQ_SIGN_HOSTKEY, ++}; ++#endif ++ + static const LIBSSH2_KEX_METHOD *libssh2_kex_methods[] = { ++#if LIBSSH2_ECDSA ++ &kex_method_ecdh_sha2_nistp256, ++ &kex_method_ecdh_sha2_nistp384, ++ &kex_method_ecdh_sha2_nistp521, ++#endif + &kex_method_diffie_helman_group_exchange_sha256, + &kex_method_diffie_helman_group_exchange_sha1, + &kex_method_diffie_helman_group14_sha1, Property changes on: head/security/libssh2/files/patch-src_kex.c ___________________________________________________________________ Added: fbsd:nokeywords ## -0,0 +1 ## +yes \ No newline at end of property Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: head/security/libssh2/files/patch-src_knownhost.c =================================================================== --- head/security/libssh2/files/patch-src_knownhost.c (nonexistent) +++ head/security/libssh2/files/patch-src_knownhost.c (revision 491663) @@ -0,0 +1,34 @@ +--- src/knownhost.c.orig 2015-03-19 13:01:33 UTC ++++ src/knownhost.c +@@ -777,6 +777,12 @@ static int hostline(LIBSSH2_KNOWNHOSTS * + key_type = LIBSSH2_KNOWNHOST_KEY_SSHDSS; + else if (!strncmp(key_type_name, "ssh-rsa", key_type_len)) + key_type = LIBSSH2_KNOWNHOST_KEY_SSHRSA; ++ else if (!strncmp(key_type_name, "ecdsa-sha2-nistp256", key_type_len)) ++ key_type = LIBSSH2_KNOWNHOST_KEY_ECDSA_256; ++ else if (!strncmp(key_type_name, "ecdsa-sha2-nistp384", key_type_len)) ++ key_type = LIBSSH2_KNOWNHOST_KEY_ECDSA_384; ++ else if (!strncmp(key_type_name, "ecdsa-sha2-nistp521", key_type_len)) ++ key_type = LIBSSH2_KNOWNHOST_KEY_ECDSA_521; + else + key_type = LIBSSH2_KNOWNHOST_KEY_UNKNOWN; + +@@ -1016,6 +1022,18 @@ knownhost_writeline(LIBSSH2_KNOWNHOSTS * + key_type_name = "ssh-dss"; + key_type_len = 7; + break; ++ case LIBSSH2_KNOWNHOST_KEY_ECDSA_256: ++ key_type_name = "ecdsa-sha2-nistp256"; ++ key_type_len = 19; ++ break; ++ case LIBSSH2_KNOWNHOST_KEY_ECDSA_384: ++ key_type_name = "ecdsa-sha2-nistp384"; ++ key_type_len = 19; ++ break; ++ case LIBSSH2_KNOWNHOST_KEY_ECDSA_521: ++ key_type_name = "ecdsa-sha2-nistp521"; ++ key_type_len = 19; ++ break; + case LIBSSH2_KNOWNHOST_KEY_UNKNOWN: + key_type_name = node->key_type_name; + if (key_type_name) { Property changes on: head/security/libssh2/files/patch-src_knownhost.c ___________________________________________________________________ Added: fbsd:nokeywords ## -0,0 +1 ## +yes \ No newline at end of property Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: head/security/libssh2/files/patch-src_libgcrypt.h =================================================================== --- head/security/libssh2/files/patch-src_libgcrypt.h (nonexistent) +++ head/security/libssh2/files/patch-src_libgcrypt.h (revision 491663) @@ -0,0 +1,59 @@ +--- src/libgcrypt.h.orig 2016-01-18 12:41:58 UTC ++++ src/libgcrypt.h +@@ -54,10 +54,15 @@ + + #define LIBSSH2_RSA 1 + #define LIBSSH2_DSA 1 ++#define LIBSSH2_ECDSA 0 + + #define MD5_DIGEST_LENGTH 16 + #define SHA_DIGEST_LENGTH 20 + #define SHA256_DIGEST_LENGTH 32 ++#define SHA384_DIGEST_LENGTH 48 ++#define SHA512_DIGEST_LENGTH 64 ++ ++#define EC_MAX_POINT_LEN ((528 * 2 / 8) + 1) + + #define _libssh2_random(buf, len) \ + (gcry_randomize ((buf), (len), GCRY_STRONG_RANDOM), 1) +@@ -87,6 +92,28 @@ + #define libssh2_sha256(message, len, out) \ + gcry_md_hash_buffer (GCRY_MD_SHA256, out, message, len) + ++#define libssh2_sha384_ctx gcry_md_hd_t ++ ++#define libssh2_sha384_init(ctx) \ ++ (GPG_ERR_NO_ERROR == gcry_md_open (ctx, GCRY_MD_SHA384, 0)) ++#define libssh2_sha384_update(ctx, data, len) \ ++ gcry_md_write (ctx, (unsigned char *) data, len) ++#define libssh2_sha384_final(ctx, out) \ ++ memcpy (out, gcry_md_read (ctx, 0), SHA384_DIGEST_LENGTH), gcry_md_close (ctx) ++#define libssh2_sha384(message, len, out) \ ++ gcry_md_hash_buffer (GCRY_MD_SHA384, out, message, len) ++ ++#define libssh2_sha512_ctx gcry_md_hd_t ++ ++#define libssh2_sha512_init(ctx) \ ++ (GPG_ERR_NO_ERROR == gcry_md_open (ctx, GCRY_MD_SHA512, 0)) ++#define libssh2_sha512_update(ctx, data, len) \ ++ gcry_md_write (ctx, (unsigned char *) data, len) ++#define libssh2_sha512_final(ctx, out) \ ++ memcpy (out, gcry_md_read (ctx, 0), SHA512_DIGEST_LENGTH), gcry_md_close (ctx) ++#define libssh2_sha512(message, len, out) \ ++ gcry_md_hash_buffer (GCRY_MD_SHA512, out, message, len) ++ + #define libssh2_md5_ctx gcry_md_hd_t + + /* returns 0 in case of failure */ +@@ -135,6 +162,11 @@ + + #define _libssh2_dsa_free(dsactx) gcry_sexp_release (dsactx) + ++#if LIBSSH2_ECDSA ++#else ++#define _libssh2_ec_key void ++#endif ++ + #define _libssh2_cipher_type(name) int name + #define _libssh2_cipher_ctx gcry_cipher_hd_t + Property changes on: head/security/libssh2/files/patch-src_libgcrypt.h ___________________________________________________________________ Added: fbsd:nokeywords ## -0,0 +1 ## +yes \ No newline at end of property Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: head/security/libssh2/files/patch-src_libssh2__priv.h =================================================================== --- head/security/libssh2/files/patch-src_libssh2__priv.h (nonexistent) +++ head/security/libssh2/files/patch-src_libssh2__priv.h (revision 491663) @@ -0,0 +1,47 @@ +--- src/libssh2_priv.h.orig 2016-02-24 22:44:12 UTC ++++ src/libssh2_priv.h +@@ -154,7 +154,7 @@ static inline int writev(int sock, struc + * padding length, payload, padding, and MAC.)." + */ + #define MAX_SSH_PACKET_LEN 35000 +-#define MAX_SHA_DIGEST_LEN SHA256_DIGEST_LENGTH ++#define MAX_SHA_DIGEST_LEN SHA512_DIGEST_LENGTH + + #define LIBSSH2_ALLOC(session, count) \ + session->alloc((count), &(session)->abstract) +@@ -271,10 +271,13 @@ typedef struct key_exchange_state_low_t + kmdhgGPshakex_state_t exchange_state; + _libssh2_bn *p; /* SSH2 defined value (p_value) */ + _libssh2_bn *g; /* SSH2 defined value (2) */ +- unsigned char request[13]; ++ unsigned char request[256]; /* Must fit EC_MAX_POINT_LEN + data */ + unsigned char *data; + size_t request_len; + size_t data_len; ++ _libssh2_ec_key *private_key; /* SSH2 ecdh private key */ ++ unsigned char *public_key_oct; /* SSH2 ecdh public key octal value */ ++ size_t public_key_oct_len; /* SSH2 ecdh public key octal value length */ + } key_exchange_state_low_t; + + typedef struct key_exchange_state_t +@@ -609,6 +612,9 @@ struct _LIBSSH2_SESSION + unsigned char server_hostkey_sha1[SHA_DIGEST_LENGTH]; + int server_hostkey_sha1_valid; + ++ unsigned char server_hostkey_sha256[SHA256_DIGEST_LENGTH]; ++ int server_hostkey_sha256_valid; ++ + /* (remote as source of data -- packet_read ) */ + libssh2_endpoint_data remote; + +@@ -983,6 +989,10 @@ _libssh2_debug(LIBSSH2_SESSION * session + #define SSH_MSG_KEX_DH_GEX_INIT 32 + #define SSH_MSG_KEX_DH_GEX_REPLY 33 + ++/* ecdh */ ++#define SSH2_MSG_KEX_ECDH_INIT 30 ++#define SSH2_MSG_KEX_ECDH_REPLY 31 ++ + /* User Authentication */ + #define SSH_MSG_USERAUTH_REQUEST 50 + #define SSH_MSG_USERAUTH_FAILURE 51 Property changes on: head/security/libssh2/files/patch-src_libssh2__priv.h ___________________________________________________________________ Added: fbsd:nokeywords ## -0,0 +1 ## +yes \ No newline at end of property Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: head/security/libssh2/files/patch-src_mbedtls.h =================================================================== --- head/security/libssh2/files/patch-src_mbedtls.h (nonexistent) +++ head/security/libssh2/files/patch-src_mbedtls.h (revision 491663) @@ -0,0 +1,57 @@ +--- src/mbedtls.h.orig 2016-09-27 06:06:29 UTC ++++ src/mbedtls.h +@@ -27,12 +27,21 @@ + + #define LIBSSH2_RSA 1 + #define LIBSSH2_DSA 0 ++#define LIBSSH2_ECDSA 0 + + #define MD5_DIGEST_LENGTH 16 + #define SHA_DIGEST_LENGTH 20 + #define SHA256_DIGEST_LENGTH 32 ++#define SHA384_DIGEST_LENGTH 48 + #define SHA512_DIGEST_LENGTH 64 + ++#define EC_MAX_POINT_LEN ((528 * 2 / 8) + 1) ++ ++#if LIBSSH2_ECDSA ++#else ++#define _libssh2_ec_key void ++#endif ++ + /*******************************************************************/ + /* + * mbedTLS backend: Global context handles +@@ -80,6 +89,8 @@ mbedtls_ctr_drbg_context _libssh2_mbedtl + _libssh2_mbedtls_hash_init(pctx, MBEDTLS_MD_RIPEMD160, key, keylen) + #define libssh2_hmac_sha256_init(pctx, key, keylen) \ + _libssh2_mbedtls_hash_init(pctx, MBEDTLS_MD_SHA256, key, keylen) ++#define libssh2_hmac_sha384_init(pctx, key, keylen) \ ++ _libssh2_mbedtls_hash_init(pctx, MBEDTLS_MD_SHA384, key, keylen) + #define libssh2_hmac_sha512_init(pctx, key, keylen) \ + _libssh2_mbedtls_hash_init(pctx, MBEDTLS_MD_SHA512, key, keylen) + +@@ -119,6 +130,23 @@ mbedtls_ctr_drbg_context _libssh2_mbedtl + + /*******************************************************************/ + /* ++ * mbedTLS backend: SHA384 functions ++ */ ++ ++#define libssh2_sha384_ctx mbedtls_md_context_t ++ ++#define libssh2_sha384_init(pctx) \ ++ _libssh2_mbedtls_hash_init(pctx, MBEDTLS_MD_SHA384, NULL, 0) ++#define libssh2_sha384_update(ctx, data, datalen) \ ++ mbedtls_md_update(&ctx, (unsigned char *) data, datalen) ++#define libssh2_sha384_final(ctx, hash) \ ++ _libssh2_mbedtls_hash_final(&ctx, hash) ++#define libssh2_sha384(data, datalen, hash) \ ++ _libssh2_mbedtls_hash(data, datalen, MBEDTLS_MD_SHA384, hash) ++ ++ ++/*******************************************************************/ ++/* + * mbedTLS backend: SHA512 functions + */ + Property changes on: head/security/libssh2/files/patch-src_mbedtls.h ___________________________________________________________________ Added: fbsd:nokeywords ## -0,0 +1 ## +yes \ No newline at end of property Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: head/security/libssh2/files/patch-src_openssl.c =================================================================== --- head/security/libssh2/files/patch-src_openssl.c (nonexistent) +++ head/security/libssh2/files/patch-src_openssl.c (revision 491663) @@ -0,0 +1,727 @@ +--- src/openssl.c.orig 2016-10-22 14:16:47 UTC ++++ src/openssl.c +@@ -48,6 +48,24 @@ + #define EVP_MAX_BLOCK_LENGTH 32 + #endif + ++static unsigned char * ++write_bn(unsigned char *buf, const BIGNUM *bn, int bn_bytes) ++{ ++ unsigned char *p = buf; ++ ++ /* Left space for bn size which will be written below. */ ++ p += 4; ++ ++ *p = 0; ++ BN_bn2bin(bn, p + 1); ++ if (!(*(p + 1) & 0x80)) { ++ memmove(p, p + 1, --bn_bytes); ++ } ++ _libssh2_htonu32(p - 4, bn_bytes); /* Post write bn size. */ ++ ++ return p + bn_bytes; ++} ++ + int + _libssh2_rsa_new(libssh2_rsa_ctx ** rsa, + const unsigned char *edata, +@@ -230,6 +248,144 @@ _libssh2_dsa_sha1_verify(libssh2_dsa_ctx + } + #endif /* LIBSSH_DSA */ + ++#if LIBSSH2_ECDSA ++ ++/* _libssh2_ecdsa_key_get_curve_type ++ * ++ * returns key curve type that maps to libssh2_curve_type ++ * ++ */ ++ ++libssh2_curve_type ++_libssh2_ecdsa_key_get_curve_type(_libssh2_ec_key *key) ++{ ++ const EC_GROUP *group = EC_KEY_get0_group(key); ++ return EC_GROUP_get_curve_name(group); ++} ++ ++/* _libssh2_ecdsa_curve_type_from_name ++ * ++ * returns 0 for success, key curve type that maps to libssh2_curve_type ++ * ++ */ ++ ++int ++_libssh2_ecdsa_curve_type_from_name(const char *name, libssh2_curve_type *out_type) ++{ ++ int ret = 0; ++ libssh2_curve_type type; ++ ++ if ( name == NULL || strlen(name) != 19 ) ++ return -1; ++ ++ if ( strcmp(name, "ecdsa-sha2-nistp256") == 0) ++ type = LIBSSH2_EC_CURVE_NISTP256; ++ else if ( strcmp(name, "ecdsa-sha2-nistp384") == 0) ++ type = LIBSSH2_EC_CURVE_NISTP384; ++ else if ( strcmp(name, "ecdsa-sha2-nistp521") == 0) ++ type = LIBSSH2_EC_CURVE_NISTP521; ++ else { ++ ret = -1; ++ } ++ ++ if (ret == 0 && out_type) { ++ *out_type = type; ++ } ++ ++ return ret; ++} ++ ++/* _libssh2_ecdsa_curve_name_with_octal_new ++ * ++ * Creates a new public key given an octal string, length and type ++ * ++ */ ++ ++int ++_libssh2_ecdsa_curve_name_with_octal_new(libssh2_ecdsa_ctx ** ec_ctx, ++ const unsigned char *k, ++ size_t k_len, libssh2_curve_type curve) ++{ ++ ++ int ret = 0; ++ const EC_GROUP *ec_group = NULL; ++ EC_KEY *ec_key = EC_KEY_new_by_curve_name(curve); ++ EC_POINT *point = NULL; ++ ++ if ( ec_key ) { ++ ec_group = EC_KEY_get0_group(ec_key); ++ point = EC_POINT_new(ec_group); ++ ret = EC_POINT_oct2point(ec_group, point, k, k_len, NULL); ++ ret = EC_KEY_set_public_key(ec_key, point); ++ ++ if (point != NULL) ++ EC_POINT_free(point); ++ ++ if ( ec_ctx != NULL ) ++ *ec_ctx = ec_key; ++ } ++ ++ return (ret == 1) ? 0 : -1; ++} ++ ++#define LIBSSH2_ECDSA_VERIFY(digest_type) \ ++{ \ ++ unsigned char hash[SHA##digest_type##_DIGEST_LENGTH]; \ ++ libssh2_sha##digest_type(m, m_len, hash); \ ++ ret = ECDSA_do_verify(hash, SHA##digest_type##_DIGEST_LENGTH, \ ++ ecdsa_sig, ec_key); \ ++ \ ++} ++ ++int ++_libssh2_ecdsa_verify(libssh2_ecdsa_ctx * ctx, ++ const unsigned char *r, size_t r_len, ++ const unsigned char *s, size_t s_len, ++ const unsigned char *m, size_t m_len) ++{ ++ int ret = 0; ++ EC_KEY *ec_key = (EC_KEY*)ctx; ++ libssh2_curve_type type = _libssh2_ecdsa_key_get_curve_type(ec_key); ++ ++#if HAVE_OPAQUE_STRUCTS ++ ECDSA_SIG *ecdsa_sig = ECDSA_SIG_new(); ++ BIGNUM *pr = BN_new(); ++ BIGNUM *ps = BN_new(); ++ ++ BN_bin2bn(r, r_len, pr); ++ BN_bin2bn(s, s_len, ps); ++ ECDSA_SIG_set0(ecdsa_sig, pr, ps); ++ ++#else ++ ECDSA_SIG ecdsa_sig_; ++ ECDSA_SIG *ecdsa_sig = &ecdsa_sig_; ++ ecdsa_sig_.r = BN_new(); ++ BN_bin2bn(r, r_len, ecdsa_sig_.r); ++ ecdsa_sig_.s = BN_new(); ++ BN_bin2bn(s, s_len, ecdsa_sig_.s); ++#endif ++ ++ if ( type == LIBSSH2_EC_CURVE_NISTP256 ) { ++ LIBSSH2_ECDSA_VERIFY(256); ++ }else if ( type == LIBSSH2_EC_CURVE_NISTP384 ) { ++ LIBSSH2_ECDSA_VERIFY(384); ++ }else if ( type == LIBSSH2_EC_CURVE_NISTP521 ) { ++ LIBSSH2_ECDSA_VERIFY(512); ++ } ++ ++#if HAVE_OPAQUE_STRUCTS ++ if ( ecdsa_sig ) ++ ECDSA_SIG_free(ecdsa_sig); ++#else ++ BN_clear_free(ecdsa_sig_.s); ++ BN_clear_free(ecdsa_sig_.r); ++#endif ++ ++ return (ret == 1) ? 0 : -1; ++} ++ ++#endif /* LIBSSH2_ECDSA */ ++ + int + _libssh2_cipher_init(_libssh2_cipher_ctx * h, + _libssh2_cipher_type(algo), +@@ -606,6 +762,41 @@ _libssh2_dsa_new_private(libssh2_dsa_ctx + } + #endif /* LIBSSH_DSA */ + ++#if LIBSSH2_ECDSA ++ ++int ++_libssh2_ecdsa_new_private_frommemory(libssh2_ecdsa_ctx ** ec_ctx, ++ LIBSSH2_SESSION * session, ++ const char *filedata, size_t filedata_len, ++ unsigned const char *passphrase) ++{ ++ pem_read_bio_func read_ec = ++ (pem_read_bio_func) &PEM_read_bio_ECPrivateKey; ++ (void) session; ++ ++ _libssh2_init_if_needed(); ++ ++ return read_private_key_from_memory((void **) ec_ctx, read_ec, ++ filedata, filedata_len, passphrase); ++} ++ ++int ++_libssh2_ecdsa_new_private(libssh2_ecdsa_ctx ** ec_ctx, ++ LIBSSH2_SESSION * session, ++ const char *filename, unsigned const char *passphrase) ++{ ++ pem_read_bio_func read_ec = (pem_read_bio_func) &PEM_read_bio_ECPrivateKey; ++ (void) session; ++ ++ _libssh2_init_if_needed (); ++ ++ return read_private_key_from_file((void **) ec_ctx, read_ec, ++ filename, passphrase); ++} ++ ++#endif /* LIBSSH2_ECDSA */ ++ ++ + int + _libssh2_rsa_sha1_sign(LIBSSH2_SESSION * session, + libssh2_rsa_ctx * rsactx, +@@ -682,6 +873,69 @@ _libssh2_dsa_sha1_sign(libssh2_dsa_ctx * + } + #endif /* LIBSSH_DSA */ + ++#if LIBSSH2_ECDSA ++ ++int ++_libssh2_ecdsa_sign(LIBSSH2_SESSION * session, libssh2_ecdsa_ctx * ec_ctx, ++ const unsigned char *hash, unsigned long hash_len, ++ unsigned char **signature, size_t *signature_len) ++{ ++ int r_len, s_len; ++ int rc = 0; ++ size_t out_buffer_len = 0; ++ unsigned char *sp; ++ const BIGNUM *pr = NULL, *ps = NULL; ++ unsigned char *temp_buffer = NULL; ++ unsigned char *out_buffer = NULL; ++ ++ ECDSA_SIG *sig = ECDSA_do_sign(hash, hash_len, ec_ctx); ++ if ( sig == NULL ) ++ return -1; ++#if HAVE_OPAQUE_STRUCTS ++ ECDSA_SIG_get0(sig, &pr, &ps); ++#else ++ pr = sig->r; ++ ps = sig->s; ++#endif ++ ++ r_len = BN_num_bytes(pr) + 1; ++ s_len = BN_num_bytes(ps) + 1; ++ ++ temp_buffer = malloc(r_len + s_len + 8); ++ if ( temp_buffer == NULL ) { ++ rc = -1; ++ goto clean_exit; ++ } ++ ++ sp = temp_buffer; ++ sp = write_bn(sp, pr, r_len); ++ sp = write_bn(sp, ps, s_len); ++ ++ out_buffer_len = (size_t)(sp - temp_buffer); ++ ++ out_buffer = LIBSSH2_CALLOC(session, out_buffer_len); ++ if ( out_buffer == NULL ) { ++ rc = -1; ++ goto clean_exit; ++ } ++ ++ memcpy(out_buffer, temp_buffer, out_buffer_len); ++ ++ *signature = out_buffer; ++ *signature_len = out_buffer_len; ++ ++clean_exit: ++ ++ if ( temp_buffer != NULL ) ++ free(temp_buffer); ++ ++ if ( sig ) ++ ECDSA_SIG_free(sig); ++ ++ return rc; ++} ++#endif /* LIBSSH2_ECDSA */ ++ + int + _libssh2_sha1_init(libssh2_sha1_ctx *ctx) + { +@@ -787,7 +1041,7 @@ _libssh2_sha256(const unsigned char *mes + } + + int +-_libssh2_md5_init(libssh2_md5_ctx *ctx) ++_libssh2_sha384_init(libssh2_sha384_ctx *ctx) + { + #ifdef HAVE_OPAQUE_STRUCTS + *ctx = EVP_MD_CTX_new(); +@@ -795,7 +1049,7 @@ _libssh2_md5_init(libssh2_md5_ctx *ctx) + if (*ctx == NULL) + return 0; + +- if (EVP_DigestInit(*ctx, EVP_get_digestbyname("md5"))) ++ if (EVP_DigestInit(*ctx, EVP_get_digestbyname("sha384"))) + return 1; + + EVP_MD_CTX_free(*ctx); +@@ -804,26 +1058,112 @@ _libssh2_md5_init(libssh2_md5_ctx *ctx) + return 0; + #else + EVP_MD_CTX_init(ctx); +- return EVP_DigestInit(ctx, EVP_get_digestbyname("md5")); ++ return EVP_DigestInit(ctx, EVP_get_digestbyname("sha384")); + #endif + } + +-static unsigned char * +-write_bn(unsigned char *buf, const BIGNUM *bn, int bn_bytes) ++int ++_libssh2_sha384(const unsigned char *message, unsigned long len, ++ unsigned char *out) + { +- unsigned char *p = buf; ++#ifdef HAVE_OPAQUE_STRUCTS ++ EVP_MD_CTX * ctx = EVP_MD_CTX_new(); + +- /* Left space for bn size which will be written below. */ +- p += 4; ++ if (ctx == NULL) ++ return 1; /* error */ + +- *p = 0; +- BN_bn2bin(bn, p + 1); +- if (!(*(p + 1) & 0x80)) { +- memmove(p, p + 1, --bn_bytes); ++ if(EVP_DigestInit(ctx, EVP_get_digestbyname("sha384"))) { ++ EVP_DigestUpdate(ctx, message, len); ++ EVP_DigestFinal(ctx, out, NULL); ++ EVP_MD_CTX_free(ctx); ++ return 0; /* success */ + } +- _libssh2_htonu32(p - 4, bn_bytes); /* Post write bn size. */ ++ EVP_MD_CTX_free(ctx); ++#else ++ EVP_MD_CTX ctx; + +- return p + bn_bytes; ++ EVP_MD_CTX_init(&ctx); ++ if(EVP_DigestInit(&ctx, EVP_get_digestbyname("sha384"))) { ++ EVP_DigestUpdate(&ctx, message, len); ++ EVP_DigestFinal(&ctx, out, NULL); ++ return 0; /* success */ ++ } ++#endif ++ return 1; /* error */ ++} ++ ++int ++_libssh2_sha512_init(libssh2_sha512_ctx *ctx) ++{ ++#ifdef HAVE_OPAQUE_STRUCTS ++ *ctx = EVP_MD_CTX_new(); ++ ++ if (*ctx == NULL) ++ return 0; ++ ++ if (EVP_DigestInit(*ctx, EVP_get_digestbyname("sha512"))) ++ return 1; ++ ++ EVP_MD_CTX_free(*ctx); ++ *ctx = NULL; ++ ++ return 0; ++#else ++ EVP_MD_CTX_init(ctx); ++ return EVP_DigestInit(ctx, EVP_get_digestbyname("sha512")); ++#endif ++} ++ ++int ++_libssh2_sha512(const unsigned char *message, unsigned long len, ++ unsigned char *out) ++{ ++#ifdef HAVE_OPAQUE_STRUCTS ++ EVP_MD_CTX * ctx = EVP_MD_CTX_new(); ++ ++ if (ctx == NULL) ++ return 1; /* error */ ++ ++ if(EVP_DigestInit(ctx, EVP_get_digestbyname("sha512"))) { ++ EVP_DigestUpdate(ctx, message, len); ++ EVP_DigestFinal(ctx, out, NULL); ++ EVP_MD_CTX_free(ctx); ++ return 0; /* success */ ++ } ++ EVP_MD_CTX_free(ctx); ++#else ++ EVP_MD_CTX ctx; ++ ++ EVP_MD_CTX_init(&ctx); ++ if(EVP_DigestInit(&ctx, EVP_get_digestbyname("sha512"))) { ++ EVP_DigestUpdate(&ctx, message, len); ++ EVP_DigestFinal(&ctx, out, NULL); ++ return 0; /* success */ ++ } ++#endif ++ return 1; /* error */ ++} ++ ++int ++_libssh2_md5_init(libssh2_md5_ctx *ctx) ++{ ++#ifdef HAVE_OPAQUE_STRUCTS ++ *ctx = EVP_MD_CTX_new(); ++ ++ if (*ctx == NULL) ++ return 0; ++ ++ if (EVP_DigestInit(*ctx, EVP_get_digestbyname("md5"))) ++ return 1; ++ ++ EVP_MD_CTX_free(*ctx); ++ *ctx = NULL; ++ ++ return 0; ++#else ++ EVP_MD_CTX_init(ctx); ++ return EVP_DigestInit(ctx, EVP_get_digestbyname("md5")); ++#endif + } + + static unsigned char * +@@ -1036,6 +1376,272 @@ gen_publickey_from_dsa_evp(LIBSSH2_SESSI + } + #endif /* LIBSSH_DSA */ + ++#if LIBSSH2_ECDSA ++ ++static int ++gen_publickey_from_ec_evp(LIBSSH2_SESSION *session, ++ unsigned char **method, ++ size_t *method_len, ++ unsigned char **pubkeydata, ++ size_t *pubkeydata_len, ++ EVP_PKEY *pk) ++{ ++ int rc = 0; ++ EC_KEY *ec = NULL; ++ unsigned char *p; ++ unsigned char* method_buf = NULL; ++ unsigned char *key; ++ size_t key_len = 0; ++ unsigned char *octal_value = NULL; ++ size_t octal_len; ++ const EC_POINT *public_key; ++ const EC_GROUP *group; ++ BN_CTX *bn_ctx; ++ libssh2_curve_type type; ++ ++ _libssh2_debug(session, ++ LIBSSH2_TRACE_AUTH, ++ "Computing public key from EC private key envelop"); ++ ++ bn_ctx = BN_CTX_new(); ++ if ( bn_ctx == NULL ) ++ return -1; ++ ++ ec = EVP_PKEY_get1_EC_KEY(pk); ++ if ( ec == NULL ) { ++ rc = -1; ++ goto clean_exit; ++ } ++ ++ public_key = EC_KEY_get0_public_key(ec); ++ group = EC_KEY_get0_group(ec); ++ type = _libssh2_ecdsa_key_get_curve_type(ec); ++ ++ method_buf = LIBSSH2_ALLOC(session, 19); ++ if (method_buf == NULL) { ++ return _libssh2_error(session, LIBSSH2_ERROR_ALLOC, ++ "out of memory"); ++ } ++ ++ if ( type == LIBSSH2_EC_CURVE_NISTP256 ) ++ memcpy(method_buf, "ecdsa-sha2-nistp256", 19); ++ else if ( type == LIBSSH2_EC_CURVE_NISTP384 ) ++ memcpy(method_buf, "ecdsa-sha2-nistp384", 19); ++ else if ( type == LIBSSH2_EC_CURVE_NISTP521 ) ++ memcpy(method_buf, "ecdsa-sha2-nistp521", 19); ++ else { ++ _libssh2_debug(session, ++ LIBSSH2_TRACE_ERROR, ++ "Unsupported EC private key type"); ++ rc = -1; ++ goto clean_exit; ++ } ++ ++ /* get length */ ++ octal_len = EC_POINT_point2oct(group, public_key, POINT_CONVERSION_UNCOMPRESSED, NULL, 0, bn_ctx); ++ if (octal_len > EC_MAX_POINT_LEN) { ++ rc = -1; ++ goto clean_exit; ++ } ++ ++ octal_value = malloc(octal_len); ++ if ( octal_value == NULL ) { ++ rc = -1; ++ goto clean_exit; ++ } ++ ++ /* convert to octal */ ++ if (EC_POINT_point2oct(group, public_key, POINT_CONVERSION_UNCOMPRESSED, ++ octal_value, octal_len, bn_ctx) != octal_len) { ++ rc = -1; ++ goto clean_exit; ++ } ++ ++ /* Key form is: type_len(4) + type(19) + domain_len(4) + domain(8) + pub_key_len(4) + pub_key(~65). */ ++ key_len = 4 + 19 + 4 + 8 + 4 + octal_len; ++ key = LIBSSH2_ALLOC(session, key_len); ++ if (key == NULL) { ++ rc = -1; ++ goto clean_exit; ++ } ++ ++ /* Process key encoding. */ ++ p = key; ++ ++ /* Key type */ ++ _libssh2_store_str(&p, (const char*)method_buf, 19); ++ ++ /* Name domain */ ++ _libssh2_store_str(&p, (const char*)method_buf + 11, 8); ++ ++ /* Public key */ ++ _libssh2_store_str(&p, (const char*)octal_value, octal_len); ++ ++ *method = method_buf; ++ *method_len = 19; ++ *pubkeydata = key; ++ *pubkeydata_len = key_len; ++ ++clean_exit: ++ ++ if ( ec != NULL) ++ EC_KEY_free(ec); ++ ++ if (bn_ctx != NULL) { ++ BN_CTX_free(bn_ctx); ++ } ++ ++ if ( octal_value != NULL ) ++ free(octal_value); ++ ++ if ( rc == 0 ) ++ return 0; ++ ++ if (method_buf != NULL ) ++ LIBSSH2_FREE(session, method_buf); ++ ++ return -1; ++} ++ ++/* ++ * _libssh2_ecdsa_create_key ++ * ++ * Creates a local private key based on input curve ++ * and returns octal value and octal length ++ * ++ */ ++ ++int ++_libssh2_ecdsa_create_key(_libssh2_ec_key **out_private_key, ++ unsigned char **out_public_key_octal, ++ size_t *out_public_key_octal_len, libssh2_curve_type curve_type) ++{ ++ int ret = 1; ++ size_t octal_len = 0; ++ unsigned char octal_value[EC_MAX_POINT_LEN]; ++ const EC_POINT *public_key = NULL; ++ EC_KEY *private_key = NULL; ++ const EC_GROUP *group = NULL; ++ ++ /* create key */ ++ BN_CTX *bn_ctx = BN_CTX_new(); ++ if (!bn_ctx) ++ return -1; ++ ++ private_key = EC_KEY_new_by_curve_name(curve_type); ++ group = EC_KEY_get0_group(private_key); ++ ++ EC_KEY_generate_key(private_key); ++ public_key = EC_KEY_get0_public_key(private_key); ++ ++ /* get length */ ++ octal_len = EC_POINT_point2oct(group, public_key, POINT_CONVERSION_UNCOMPRESSED, NULL, 0, bn_ctx); ++ if (octal_len > EC_MAX_POINT_LEN) { ++ ret = -1; ++ goto clean_exit; ++ } ++ ++ /* convert to octal */ ++ if (EC_POINT_point2oct(group, public_key, POINT_CONVERSION_UNCOMPRESSED, ++ octal_value, octal_len, bn_ctx) != octal_len){ ++ ret = -1; ++ goto clean_exit; ++ } ++ ++ if (out_private_key != NULL) ++ *out_private_key = private_key; ++ ++ if (out_public_key_octal) { ++ *out_public_key_octal = malloc(octal_len); ++ if (out_public_key_octal == NULL) { ++ ret = -1; ++ goto clean_exit; ++ } ++ ++ memcpy(*out_public_key_octal, octal_value, octal_len); ++ } ++ ++ if (out_public_key_octal_len != NULL) ++ *out_public_key_octal_len = octal_len; ++ ++clean_exit: ++ ++ if (bn_ctx) ++ BN_CTX_free(bn_ctx); ++ ++ return (ret == 1) ? 0 : -1; ++} ++ ++/* _libssh2_ecdh_gen_k ++ * ++ * Computes the shared secret K given a local private key, ++ * remote public key and length ++ */ ++ ++int ++_libssh2_ecdh_gen_k(_libssh2_bn **k, _libssh2_ec_key *private_key, ++ const unsigned char *server_public_key, size_t server_public_key_len) ++{ ++ int ret = 0; ++ int rc; ++ size_t secret_len; ++ unsigned char *secret; ++ const EC_GROUP *private_key_group; ++ EC_POINT *server_public_key_point; ++ ++ BN_CTX *bn_ctx = BN_CTX_new(); ++ ++ if ( !bn_ctx ) ++ return -1; ++ ++ if ( k == NULL ) ++ return -1; ++ ++ private_key_group = EC_KEY_get0_group(private_key); ++ ++ server_public_key_point = EC_POINT_new(private_key_group); ++ if ( server_public_key_point == NULL ) ++ return -1; ++ ++ rc = EC_POINT_oct2point(private_key_group, server_public_key_point, server_public_key, server_public_key_len, bn_ctx); ++ if ( rc != 1 ) { ++ ret = -1; ++ goto clean_exit; ++ } ++ ++ secret_len = (EC_GROUP_get_degree(private_key_group) + 7) / 8; ++ secret = malloc(secret_len); ++ if (!secret) { ++ ret = -1; ++ goto clean_exit; ++ } ++ ++ secret_len = ECDH_compute_key(secret, secret_len, server_public_key_point, private_key, NULL); ++ ++ if( secret_len <= 0 || secret_len > EC_MAX_POINT_LEN ) { ++ ret = -1; ++ goto clean_exit; ++ } ++ ++ BN_bin2bn(secret, secret_len, *k); ++ ++clean_exit: ++ ++ if ( server_public_key_point != NULL ) ++ EC_POINT_free(server_public_key_point); ++ ++ if ( bn_ctx != NULL ) ++ BN_CTX_free(bn_ctx); ++ ++ if ( secret != NULL ) ++ free(secret); ++ ++ return ret; ++} ++ ++ ++#endif /* LIBSSH2_ECDSA */ ++ + int + _libssh2_pub_priv_keyfile(LIBSSH2_SESSION *session, + unsigned char **method, +@@ -1102,6 +1708,13 @@ _libssh2_pub_priv_keyfile(LIBSSH2_SESSIO + break; + #endif /* LIBSSH_DSA */ + ++#if LIBSSH2_ECDSA ++ case EVP_PKEY_EC : ++ st = gen_publickey_from_ec_evp( ++ session, method, method_len, pubkeydata, pubkeydata_len, pk); ++ break; ++#endif ++ + default : + st = _libssh2_error(session, + LIBSSH2_ERROR_FILE, +@@ -1176,6 +1789,12 @@ _libssh2_pub_priv_keyfilememory(LIBSSH2_ + pubkeydata, pubkeydata_len, pk); + break; + #endif /* LIBSSH_DSA */ ++#if LIBSSH2_ECDSA ++ case EVP_PKEY_EC : ++ st = gen_publickey_from_ec_evp(session, method, method_len, ++ pubkeydata, pubkeydata_len, pk); ++ break; ++#endif + default : + st = _libssh2_error(session, + LIBSSH2_ERROR_FILE, Property changes on: head/security/libssh2/files/patch-src_openssl.c ___________________________________________________________________ Added: fbsd:nokeywords ## -0,0 +1 ## +yes \ No newline at end of property Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: head/security/libssh2/files/patch-src_openssl.h =================================================================== --- head/security/libssh2/files/patch-src_openssl.h (nonexistent) +++ head/security/libssh2/files/patch-src_openssl.h (revision 491663) @@ -0,0 +1,107 @@ +--- src/openssl.h.orig 2016-02-17 21:59:57 UTC ++++ src/openssl.h +@@ -70,6 +70,12 @@ + # define LIBSSH2_DSA 1 + #endif + ++#ifdef OPENSSL_NO_ECDSA ++# define LIBSSH2_ECDSA 0 ++#else ++# define LIBSSH2_ECDSA 1 ++#endif ++ + #ifdef OPENSSL_NO_MD5 + # define LIBSSH2_MD5 0 + #else +@@ -117,6 +123,8 @@ + # define LIBSSH2_3DES 1 + #endif + ++#define EC_MAX_POINT_LEN ((528 * 2 / 8) + 1) ++ + #define _libssh2_random(buf, len) RAND_bytes ((buf), (len)) + + #define libssh2_prepare_iovec(vec, len) /* Empty. */ +@@ -168,6 +176,52 @@ int _libssh2_sha256(const unsigned char + #define libssh2_sha256(x,y,z) _libssh2_sha256(x,y,z) + + #ifdef HAVE_OPAQUE_STRUCTS ++#define libssh2_sha384_ctx EVP_MD_CTX * ++#else ++#define libssh2_sha384_ctx EVP_MD_CTX ++#endif ++ ++/* returns 0 in case of failure */ ++int _libssh2_sha384_init(libssh2_sha384_ctx *ctx); ++#define libssh2_sha384_init(x) _libssh2_sha384_init(x) ++#ifdef HAVE_OPAQUE_STRUCTS ++#define libssh2_sha384_update(ctx, data, len) EVP_DigestUpdate(ctx, data, len) ++#define libssh2_sha384_final(ctx, out) do { \ ++ EVP_DigestFinal(ctx, out, NULL); \ ++ EVP_MD_CTX_free(ctx); \ ++ } while(0) ++#else ++#define libssh2_sha384_update(ctx, data, len) EVP_DigestUpdate(&(ctx), data, len) ++#define libssh2_sha384_final(ctx, out) EVP_DigestFinal(&(ctx), out, NULL) ++#endif ++int _libssh2_sha384(const unsigned char *message, unsigned long len, ++ unsigned char *out); ++#define libssh2_sha384(x,y,z) _libssh2_sha384(x,y,z) ++ ++#ifdef HAVE_OPAQUE_STRUCTS ++#define libssh2_sha512_ctx EVP_MD_CTX * ++#else ++#define libssh2_sha512_ctx EVP_MD_CTX ++#endif ++ ++/* returns 0 in case of failure */ ++int _libssh2_sha512_init(libssh2_sha512_ctx *ctx); ++#define libssh2_sha512_init(x) _libssh2_sha512_init(x) ++#ifdef HAVE_OPAQUE_STRUCTS ++#define libssh2_sha512_update(ctx, data, len) EVP_DigestUpdate(ctx, data, len) ++#define libssh2_sha512_final(ctx, out) do { \ ++ EVP_DigestFinal(ctx, out, NULL); \ ++ EVP_MD_CTX_free(ctx); \ ++ } while(0) ++#else ++#define libssh2_sha512_update(ctx, data, len) EVP_DigestUpdate(&(ctx), data, len) ++#define libssh2_sha512_final(ctx, out) EVP_DigestFinal(&(ctx), out, NULL) ++#endif ++int _libssh2_sha512(const unsigned char *message, unsigned long len, ++ unsigned char *out); ++#define libssh2_sha512(x,y,z) _libssh2_sha512(x,y,z) ++ ++#ifdef HAVE_OPAQUE_STRUCTS + #define libssh2_md5_ctx EVP_MD_CTX * + #else + #define libssh2_md5_ctx EVP_MD_CTX +@@ -239,9 +293,23 @@ int _libssh2_md5_init(libssh2_md5_ctx *c + + #define libssh2_dsa_ctx DSA + +- + #define _libssh2_dsa_free(dsactx) DSA_free(dsactx) + ++#if LIBSSH2_ECDSA ++#define libssh2_ecdsa_ctx EC_KEY ++#define _libssh2_ecdsa_free(ecdsactx) EC_KEY_free(ecdsactx) ++#define _libssh2_ec_key EC_KEY ++ ++typedef enum { ++ LIBSSH2_EC_CURVE_NISTP256 = NID_X9_62_prime256v1, ++ LIBSSH2_EC_CURVE_NISTP384 = NID_secp384r1, ++ LIBSSH2_EC_CURVE_NISTP521 = NID_secp521r1, ++} ++libssh2_curve_type; ++#else ++#define _libssh2_ec_key void ++#endif ++ + #define _libssh2_cipher_type(name) const EVP_CIPHER *(*name)(void) + #ifdef HAVE_OPAQUE_STRUCTS + #define _libssh2_cipher_ctx EVP_CIPHER_CTX * +@@ -290,4 +358,3 @@ int _libssh2_md5_init(libssh2_md5_ctx *c + 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); +- Property changes on: head/security/libssh2/files/patch-src_openssl.h ___________________________________________________________________ Added: fbsd:nokeywords ## -0,0 +1 ## +yes \ No newline at end of property Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: head/security/libssh2/files/patch-tests_openssh__server_Dockerfile =================================================================== --- head/security/libssh2/files/patch-tests_openssh__server_Dockerfile (nonexistent) +++ head/security/libssh2/files/patch-tests_openssh__server_Dockerfile (revision 491663) @@ -0,0 +1,13 @@ +--- tests/openssh_server/Dockerfile.orig 2016-08-20 15:37:25 UTC ++++ tests/openssh_server/Dockerfile +@@ -50,6 +50,10 @@ COPY ssh_host_rsa_key /tmp/etc/ssh/ssh_h + RUN mv /tmp/etc/ssh/ssh_host_rsa_key /etc/ssh/ssh_host_rsa_key + RUN chmod 600 /etc/ssh/ssh_host_rsa_key + ++COPY ssh_host_ecdsa_key /tmp/etc/ssh/ssh_host_ecdsa_key ++RUN mv /tmp/etc/ssh/ssh_host_ecdsa_key /etc/ssh/ssh_host_ecdsa_key ++RUN chmod 600 /etc/ssh/ssh_host_ecdsa_key ++ + RUN adduser --disabled-password --gecos 'Test user for libssh2 integration tests' libssh2 + RUN echo 'libssh2:my test password' | chpasswd + Property changes on: head/security/libssh2/files/patch-tests_openssh__server_Dockerfile ___________________________________________________________________ Added: fbsd:nokeywords ## -0,0 +1 ## +yes \ No newline at end of property Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: head/security/libssh2/files/patch-tests_openssh__server_ssh__host__ecdsa__key =================================================================== --- head/security/libssh2/files/patch-tests_openssh__server_ssh__host__ecdsa__key (nonexistent) +++ head/security/libssh2/files/patch-tests_openssh__server_ssh__host__ecdsa__key (revision 491663) @@ -0,0 +1,8 @@ +--- tests/openssh_server/ssh_host_ecdsa_key.orig 2019-01-29 21:00:05 UTC ++++ tests/openssh_server/ssh_host_ecdsa_key +@@ -0,0 +1,5 @@ ++-----BEGIN EC PRIVATE KEY----- ++MHcCAQEEIKdqGrp+52U1ehslMI4fX0cmvgHFmKSkMzQGmj6B07ecoAoGCCqGSM49 ++AwEHoUQDQgAEL7+zLJ4okP10LZkf1DuIkZF5HhgzetQIyxLKeTJeiN19IKUYIxjs ++m9aW3fQRKNi/GhN9JEbHpa9qpgr+8+hhDg== ++-----END EC PRIVATE KEY----- Property changes on: head/security/libssh2/files/patch-tests_openssh__server_ssh__host__ecdsa__key ___________________________________________________________________ Added: fbsd:nokeywords ## -0,0 +1 ## +yes \ No newline at end of property Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: head/security/libssh2/files/patch-tests_test__hostkey.c =================================================================== --- head/security/libssh2/files/patch-tests_test__hostkey.c (nonexistent) +++ head/security/libssh2/files/patch-tests_test__hostkey.c (revision 491663) @@ -0,0 +1,47 @@ +--- tests/test_hostkey.c.orig 2016-08-20 15:37:25 UTC ++++ tests/test_hostkey.c +@@ -4,7 +4,7 @@ + + #include + +-const char *EXPECTED_HOSTKEY = ++const char *EXPECTED_RSA_HOSTKEY = + "AAAAB3NzaC1yc2EAAAABIwAAAQEArrr/JuJmaZligyfS8vcNur+mWR2ddDQtVdhHzdKU" + "UoR6/Om6cvxpe61H1YZO1xCpLUBXmkki4HoNtYOpPB2W4V+8U4BDeVBD5crypEOE1+7B" + "Am99fnEDxYIOZq2/jTP0yQmzCpWYS3COyFmkOL7sfX1wQMeW5zQT2WKcxC6FSWbhDqrB" +@@ -12,6 +12,10 @@ const char *EXPECTED_HOSTKEY = + "i6ELfP3r+q6wdu0P4jWaoo3De1aYxnToV/ldXykpipON4NPamsb6Ph2qlJQKypq7J4iQ" + "gkIIbCU1A31+4ExvcIVoxLQw/aTSbw=="; + ++const char *EXPECTED_ECDSA_HOSTKEY = ++ "AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBC+/syyeKJD9dC2ZH" ++ "9Q7iJGReR4YM3rUCMsSynkyXojdfSClGCMY7JvWlt30ESjYvxoTfSRGx6WvaqYK/vPoYQ4="; ++ + int test(LIBSSH2_SESSION *session) + { + int rc; +@@ -26,14 +30,19 @@ int test(LIBSSH2_SESSION *session) + return 1; + } + +- if (type != LIBSSH2_HOSTKEY_TYPE_RSA) { +- /* Hostkey configured in docker container is RSA */ +- fprintf(stderr, "Wrong type of hostkey\n"); ++ if(type == LIBSSH2_HOSTKEY_TYPE_ECDSA_256) { ++ rc = libssh2_base64_decode(session, &expected_hostkey, &expected_len, ++ EXPECTED_ECDSA_HOSTKEY, strlen(EXPECTED_ECDSA_HOSTKEY)); ++ } ++ else if (type == LIBSSH2_HOSTKEY_TYPE_RSA) { ++ rc = libssh2_base64_decode(session, &expected_hostkey, &expected_len, ++ EXPECTED_RSA_HOSTKEY, strlen(EXPECTED_RSA_HOSTKEY)); ++ } ++ else { ++ fprintf(stderr, "Unexpected type of hostkey: %i\n", type); + return 1; + } + +- rc = libssh2_base64_decode(session, &expected_hostkey, &expected_len, +- EXPECTED_HOSTKEY, strlen(EXPECTED_HOSTKEY)); + if (rc != 0) { + print_last_session_error("libssh2_base64_decode"); + return 1; Property changes on: head/security/libssh2/files/patch-tests_test__hostkey.c ___________________________________________________________________ Added: fbsd:nokeywords ## -0,0 +1 ## +yes \ No newline at end of property Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: head/security/libssh2/files/patch-tests_test__hostkey__hash.c =================================================================== --- head/security/libssh2/files/patch-tests_test__hostkey__hash.c (nonexistent) +++ head/security/libssh2/files/patch-tests_test__hostkey__hash.c (revision 491663) @@ -0,0 +1,173 @@ +--- tests/test_hostkey_hash.c.orig 2016-08-20 15:37:25 UTC ++++ tests/test_hostkey_hash.c +@@ -5,7 +5,7 @@ + + #include + +-const char *EXPECTED_HOSTKEY = ++const char *EXPECTED_RSA_HOSTKEY = + "AAAAB3NzaC1yc2EAAAABIwAAAQEArrr/JuJmaZligyfS8vcNur+mWR2ddDQtVdhHzdKU" + "UoR6/Om6cvxpe61H1YZO1xCpLUBXmkki4HoNtYOpPB2W4V+8U4BDeVBD5crypEOE1+7B" + "Am99fnEDxYIOZq2/jTP0yQmzCpWYS3COyFmkOL7sfX1wQMeW5zQT2WKcxC6FSWbhDqrB" +@@ -13,13 +13,27 @@ const char *EXPECTED_HOSTKEY = + "i6ELfP3r+q6wdu0P4jWaoo3De1aYxnToV/ldXykpipON4NPamsb6Ph2qlJQKypq7J4iQ" + "gkIIbCU1A31+4ExvcIVoxLQw/aTSbw=="; + +-const char *EXPECTED_MD5_HASH_DIGEST = "0C0ED1A5BB10275F76924CE187CE5C5E"; ++const char *EXPECTED_ECDSA_HOSTKEY = ++ "AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBC+/syyeKJD9dC2ZH" ++ "9Q7iJGReR4YM3rUCMsSynkyXojdfSClGCMY7JvWlt30ESjYvxoTfSRGx6WvaqYK/vPoYQ4="; + +-const char *EXPECTED_SHA1_HASH_DIGEST = ++const char *EXPECTED_RSA_MD5_HASH_DIGEST = "0C0ED1A5BB10275F76924CE187CE5C5E"; ++ ++const char *EXPECTED_RSA_SHA1_HASH_DIGEST = + "F3CD59E2913F4422B80F7B0A82B2B89EAE449387"; + ++const char *EXPECTED_RSA_SHA256_HASH_DIGEST = "92E3DA49DF3C7F99A828F505ED8239397A5D1F62914459760F878F7510F563A3"; ++ ++const char *EXPECTED_ECDSA_MD5_HASH_DIGEST = "0402E4D897580BBC911379CBD88BCD3D"; ++ ++const char *EXPECTED_ECDSA_SHA1_HASH_DIGEST = ++ "12FDAD1E3B31B10BABB00F2A8D1B9A62C326BD2F"; ++ ++const char *EXPECTED_ECDSA_SHA256_HASH_DIGEST = "56FCD975B166C3F0342D0036E44C311A86C0EAE40713B53FC776369BAE7F5264"; ++ + const int MD5_HASH_SIZE = 16; + const int SHA1_HASH_SIZE = 20; ++const int SHA256_HASH_SIZE = 32; + + static void calculate_digest(const char *hash, size_t hash_len, char *buffer, + size_t buffer_len) +@@ -39,34 +53,111 @@ int test(LIBSSH2_SESSION *session) + + const char *md5_hash; + const char *sha1_hash; ++ const char *sha256_hash; ++ int type; ++ size_t len; + +- md5_hash = libssh2_hostkey_hash(session, LIBSSH2_HOSTKEY_HASH_MD5); +- if (md5_hash == NULL) { +- print_last_session_error( +- "libssh2_hostkey_hash(LIBSSH2_HOSTKEY_HASH_MD5)"); ++ const char *hostkey = libssh2_session_hostkey(session, &len, &type); ++ if (hostkey == NULL) { ++ print_last_session_error("libssh2_session_hostkey"); + return 1; + } + +- calculate_digest(md5_hash, MD5_HASH_SIZE, buf, BUFSIZ); ++ if(type == LIBSSH2_HOSTKEY_TYPE_ECDSA_256) { + +- if (strcmp(buf, EXPECTED_MD5_HASH_DIGEST) != 0) { +- fprintf(stderr, "MD5 hash not as expected - digest %s != %s\n", buf, +- EXPECTED_MD5_HASH_DIGEST); +- return 1; +- } ++ md5_hash = libssh2_hostkey_hash(session, LIBSSH2_HOSTKEY_HASH_MD5); ++ if (md5_hash == NULL) { ++ print_last_session_error( ++ "libssh2_hostkey_hash(LIBSSH2_HOSTKEY_HASH_MD5)"); ++ return 1; ++ } + +- sha1_hash = libssh2_hostkey_hash(session, LIBSSH2_HOSTKEY_HASH_SHA1); +- if (sha1_hash == NULL) { +- print_last_session_error( +- "libssh2_hostkey_hash(LIBSSH2_HOSTKEY_HASH_SHA1)"); +- return 1; +- } ++ calculate_digest(md5_hash, MD5_HASH_SIZE, buf, BUFSIZ); + +- calculate_digest(sha1_hash, SHA1_HASH_SIZE, buf, BUFSIZ); ++ if (strcmp(buf, EXPECTED_ECDSA_MD5_HASH_DIGEST) != 0) { ++ fprintf(stderr, "ECDSA MD5 hash not as expected - digest %s != %s\n", buf, ++ EXPECTED_ECDSA_MD5_HASH_DIGEST); ++ return 1; ++ } + +- if (strcmp(buf, EXPECTED_SHA1_HASH_DIGEST) != 0) { +- fprintf(stderr, "SHA1 hash not as expected - digest %s != %s\n", buf, +- EXPECTED_SHA1_HASH_DIGEST); ++ sha1_hash = libssh2_hostkey_hash(session, LIBSSH2_HOSTKEY_HASH_SHA1); ++ if (sha1_hash == NULL) { ++ print_last_session_error( ++ "libssh2_hostkey_hash(LIBSSH2_HOSTKEY_HASH_SHA1)"); ++ return 1; ++ } ++ ++ calculate_digest(sha1_hash, SHA1_HASH_SIZE, buf, BUFSIZ); ++ ++ if (strcmp(buf, EXPECTED_ECDSA_SHA1_HASH_DIGEST) != 0) { ++ fprintf(stderr, "ECDSA SHA1 hash not as expected - digest %s != %s\n", buf, ++ EXPECTED_ECDSA_SHA1_HASH_DIGEST); ++ return 1; ++ } ++ ++ sha256_hash = libssh2_hostkey_hash(session, LIBSSH2_HOSTKEY_HASH_SHA256); ++ if (sha256_hash == NULL) { ++ print_last_session_error( ++ "libssh2_hostkey_hash(LIBSSH2_HOSTKEY_HASH_SHA256)"); ++ return 1; ++ } ++ ++ calculate_digest(sha256_hash, SHA256_HASH_SIZE, buf, BUFSIZ); ++ ++ if (strcmp(buf, EXPECTED_ECDSA_SHA256_HASH_DIGEST) != 0) { ++ fprintf(stderr, "ECDSA SHA256 hash not as expected - digest %s != %s\n", buf, ++ EXPECTED_ECDSA_SHA256_HASH_DIGEST); ++ return 1; ++ } ++ ++ } else if ( type == LIBSSH2_HOSTKEY_TYPE_RSA ) { ++ ++ md5_hash = libssh2_hostkey_hash(session, LIBSSH2_HOSTKEY_HASH_MD5); ++ if (md5_hash == NULL) { ++ print_last_session_error( ++ "libssh2_hostkey_hash(LIBSSH2_HOSTKEY_HASH_MD5)"); ++ return 1; ++ } ++ ++ calculate_digest(md5_hash, MD5_HASH_SIZE, buf, BUFSIZ); ++ ++ if (strcmp(buf, EXPECTED_RSA_MD5_HASH_DIGEST) != 0) { ++ fprintf(stderr, "MD5 hash not as expected - digest %s != %s\n", buf, ++ EXPECTED_RSA_MD5_HASH_DIGEST); ++ return 1; ++ } ++ ++ sha1_hash = libssh2_hostkey_hash(session, LIBSSH2_HOSTKEY_HASH_SHA1); ++ if (sha1_hash == NULL) { ++ print_last_session_error( ++ "libssh2_hostkey_hash(LIBSSH2_HOSTKEY_HASH_SHA1)"); ++ return 1; ++ } ++ ++ calculate_digest(sha1_hash, SHA1_HASH_SIZE, buf, BUFSIZ); ++ ++ if (strcmp(buf, EXPECTED_RSA_SHA1_HASH_DIGEST) != 0) { ++ fprintf(stderr, "SHA1 hash not as expected - digest %s != %s\n", buf, ++ EXPECTED_RSA_SHA1_HASH_DIGEST); ++ return 1; ++ } ++ ++ sha256_hash = libssh2_hostkey_hash(session, LIBSSH2_HOSTKEY_HASH_SHA256); ++ if (sha256_hash == NULL) { ++ print_last_session_error( ++ "libssh2_hostkey_hash(LIBSSH2_HOSTKEY_HASH_SHA256)"); ++ return 1; ++ } ++ ++ calculate_digest(sha256_hash, SHA256_HASH_SIZE, buf, BUFSIZ); ++ ++ if (strcmp(buf, EXPECTED_RSA_SHA256_HASH_DIGEST) != 0) { ++ fprintf(stderr, "SHA256 hash not as expected - digest %s != %s\n", buf, ++ EXPECTED_RSA_SHA256_HASH_DIGEST); ++ return 1; ++ } ++ } else { ++ fprintf(stderr, "Unexpected type of hostkey: %i\n", type); + return 1; + } + Property changes on: head/security/libssh2/files/patch-tests_test__hostkey__hash.c ___________________________________________________________________ Added: fbsd:nokeywords ## -0,0 +1 ## +yes \ No newline at end of property Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property