Add support for ECDSA key exchange and SHA256 MAC.
Note these patches were cherry-piecked from the following upstream commits: https://github.com/libssh2/libssh2/commit/bbc43cb https://github.com/libssh2/libssh2/commit/aba34f5 https://github.com/libssh2/libssh2/commit/62b825c Submitted by: Andrew Heybey <ath@heybey.org> Reviewed by: sbz (maintainer)
This commit is contained in:
parent
cffa68613d
commit
0b987dd74d
Notes:
svn2git
2021-03-31 03:12:20 +00:00
svn path=/head/; revision=491663
15 changed files with 2775 additions and 0 deletions
|
@ -3,6 +3,7 @@
|
|||
|
||||
PORTNAME= libssh2
|
||||
PORTVERSION= 1.8.0
|
||||
PORTREVISION= 1
|
||||
PORTEPOCH= 3
|
||||
CATEGORIES= security devel
|
||||
MASTER_SITES= http://www.libssh2.org/download/ \
|
||||
|
|
43
security/libssh2/files/patch-include_libssh2.h
Normal file
43
security/libssh2/files/patch-include_libssh2.h
Normal file
|
@ -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,
|
56
security/libssh2/files/patch-src_crypto.h
Normal file
56
security/libssh2/files/patch-src_crypto.h
Normal file
|
@ -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,
|
363
security/libssh2/files/patch-src_hostkey.c
Normal file
363
security/libssh2/files/patch-src_hostkey.c
Normal file
|
@ -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;
|
||||
}
|
||||
-
|
1040
security/libssh2/files/patch-src_kex.c
Normal file
1040
security/libssh2/files/patch-src_kex.c
Normal file
File diff suppressed because it is too large
Load diff
34
security/libssh2/files/patch-src_knownhost.c
Normal file
34
security/libssh2/files/patch-src_knownhost.c
Normal file
|
@ -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) {
|
59
security/libssh2/files/patch-src_libgcrypt.h
Normal file
59
security/libssh2/files/patch-src_libgcrypt.h
Normal file
|
@ -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
|
||||
|
47
security/libssh2/files/patch-src_libssh2__priv.h
Normal file
47
security/libssh2/files/patch-src_libssh2__priv.h
Normal file
|
@ -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
|
57
security/libssh2/files/patch-src_mbedtls.h
Normal file
57
security/libssh2/files/patch-src_mbedtls.h
Normal file
|
@ -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
|
||||
*/
|
||||
|
727
security/libssh2/files/patch-src_openssl.c
Normal file
727
security/libssh2/files/patch-src_openssl.c
Normal file
|
@ -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,
|
107
security/libssh2/files/patch-src_openssl.h
Normal file
107
security/libssh2/files/patch-src_openssl.h
Normal file
|
@ -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);
|
||||
-
|
|
@ -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
|
||||
|
|
@ -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-----
|
47
security/libssh2/files/patch-tests_test__hostkey.c
Normal file
47
security/libssh2/files/patch-tests_test__hostkey.c
Normal file
|
@ -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 <stdio.h>
|
||||
|
||||
-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;
|
173
security/libssh2/files/patch-tests_test__hostkey__hash.c
Normal file
173
security/libssh2/files/patch-tests_test__hostkey__hash.c
Normal file
|
@ -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 <stdio.h>
|
||||
|
||||
-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;
|
||||
}
|
||||
|
Loading…
Reference in a new issue