diff options
author | dartraiden <wowemuh@gmail.com> | 2019-06-20 22:31:19 +0300 |
---|---|---|
committer | dartraiden <wowemuh@gmail.com> | 2019-06-20 22:31:19 +0300 |
commit | 1d72e07ffb7b349ac9a8f825eae7cce082b5e2cd (patch) | |
tree | 03a97724b412a04a7a3848dc8c5edb24b2d29c0e /libs/libssh2/src/hostkey.c | |
parent | fdf29bb66f0b9be0b8518db0a827cc2bd20a38ac (diff) |
iibssh2: update to 1.9.0
Diffstat (limited to 'libs/libssh2/src/hostkey.c')
-rw-r--r-- | libs/libssh2/src/hostkey.c | 708 |
1 files changed, 632 insertions, 76 deletions
diff --git a/libs/libssh2/src/hostkey.c b/libs/libssh2/src/hostkey.c index 2a0a8f943b..a8bd42b7a0 100644 --- a/libs/libssh2/src/hostkey.c +++ b/libs/libssh2/src/hostkey.c @@ -1,5 +1,5 @@ /* Copyright (c) 2004-2006, Sara Golemon <sarag@libssh2.org> - * Copyright (c) 2009-2014 by Daniel Stenberg + * Copyright (c) 2009-2019 by Daniel Stenberg * All rights reserved. * * Redistribution and use in source and binary forms, @@ -64,38 +64,36 @@ hostkey_method_ssh_rsa_init(LIBSSH2_SESSION * session, void **abstract) { libssh2_rsa_ctx *rsactx; - const unsigned char *s, *e, *n; - unsigned long len, e_len, n_len; - int ret; - - (void) hostkey_data_len; + unsigned char *e, *n; + size_t e_len, n_len; + struct string_buf buf; - if (*abstract) { + if(*abstract) { hostkey_method_ssh_rsa_dtor(session, abstract); *abstract = NULL; } - s = hostkey_data; - len = _libssh2_ntohu32(s); - s += 4; - - if (len != 7 || strncmp((char *) s, "ssh-rsa", 7) != 0) { + if(hostkey_data_len < 19) { + _libssh2_debug(session, LIBSSH2_TRACE_ERROR, + "host key length too short"); return -1; } - s += 7; - e_len = _libssh2_ntohu32(s); - s += 4; + buf.data = (unsigned char *)hostkey_data; + buf.dataptr = buf.data; + buf.len = hostkey_data_len; - e = s; - s += e_len; - n_len = _libssh2_ntohu32(s); - s += 4; - n = s; + if(_libssh2_match_string(&buf, "ssh-rsa")) + return -1; + + if(_libssh2_get_string(&buf, &e, &e_len)) + return -1; + + if(_libssh2_get_string(&buf, &n, &n_len)) + return -1; - ret = _libssh2_rsa_new(&rsactx, e, e_len, n, n_len, NULL, 0, - NULL, 0, NULL, 0, NULL, 0, NULL, 0, NULL, 0); - if (ret) { + if(_libssh2_rsa_new(&rsactx, e, e_len, n, n_len, NULL, 0, + NULL, 0, NULL, 0, NULL, 0, NULL, 0, NULL, 0)) { return -1; } @@ -118,13 +116,13 @@ hostkey_method_ssh_rsa_initPEM(LIBSSH2_SESSION * session, libssh2_rsa_ctx *rsactx; int ret; - if (*abstract) { + if(*abstract) { hostkey_method_ssh_rsa_dtor(session, abstract); *abstract = NULL; } ret = _libssh2_rsa_new_private(&rsactx, session, privkeyfile, passphrase); - if (ret) { + if(ret) { return -1; } @@ -148,7 +146,7 @@ hostkey_method_ssh_rsa_initPEMFromMemory(LIBSSH2_SESSION * session, libssh2_rsa_ctx *rsactx; int ret; - if (*abstract) { + if(*abstract) { hostkey_method_ssh_rsa_dtor(session, abstract); *abstract = NULL; } @@ -156,7 +154,7 @@ hostkey_method_ssh_rsa_initPEMFromMemory(LIBSSH2_SESSION * session, ret = _libssh2_rsa_new_private_frommemory(&rsactx, session, privkeyfiledata, privkeyfiledata_len, passphrase); - if (ret) { + if(ret) { return -1; } @@ -181,6 +179,9 @@ hostkey_method_ssh_rsa_sig_verify(LIBSSH2_SESSION * session, (void) session; /* Skip past keyname_len(4) + keyname(7){"ssh-rsa"} + signature_len(4) */ + if(sig_len < 15) + return -1; + sig += 15; sig_len -= 15; return _libssh2_rsa_sha1_verify(rsactx, sig, sig_len, m, m_len); @@ -218,7 +219,7 @@ hostkey_method_ssh_rsa_signv(LIBSSH2_SESSION * session, ret = _libssh2_rsa_sha1_sign(session, rsactx, hash, SHA_DIGEST_LENGTH, signature, signature_len); - if (ret) { + if(ret) { return -1; } @@ -281,45 +282,42 @@ hostkey_method_ssh_dss_init(LIBSSH2_SESSION * session, void **abstract) { libssh2_dsa_ctx *dsactx; - const unsigned char *p, *q, *g, *y, *s; - unsigned long p_len, q_len, g_len, y_len, len; - int ret; - - (void) hostkey_data_len; + unsigned char *p, *q, *g, *y; + size_t p_len, q_len, g_len, y_len; + struct string_buf buf; - if (*abstract) { + if(*abstract) { hostkey_method_ssh_dss_dtor(session, abstract); *abstract = NULL; } - s = hostkey_data; - len = _libssh2_ntohu32(s); - s += 4; - if (len != 7 || strncmp((char *) s, "ssh-dss", 7) != 0) { + if(hostkey_data_len < 27) { + _libssh2_debug(session, LIBSSH2_TRACE_ERROR, + "host key length too short"); return -1; } - s += 7; - p_len = _libssh2_ntohu32(s); - s += 4; - p = s; - s += p_len; - q_len = _libssh2_ntohu32(s); - s += 4; - q = s; - s += q_len; - g_len = _libssh2_ntohu32(s); - s += 4; - g = s; - s += g_len; - y_len = _libssh2_ntohu32(s); - s += 4; - y = s; - /* s += y_len; */ + buf.data = (unsigned char *)hostkey_data; + buf.dataptr = buf.data; + buf.len = hostkey_data_len; + + if(_libssh2_match_string(&buf, "ssh-dss")) + return -1; + + if(_libssh2_get_string(&buf, &p, &p_len)) + return -1; + + if(_libssh2_get_string(&buf, &q, &q_len)) + return -1; + + if(_libssh2_get_string(&buf, &g, &g_len)) + return -1; + + if(_libssh2_get_string(&buf, &y, &y_len)) + return -1; - ret = _libssh2_dsa_new(&dsactx, p, p_len, q, q_len, - g, g_len, y, y_len, NULL, 0); - if (ret) { + if(_libssh2_dsa_new(&dsactx, p, p_len, q, q_len, + g, g_len, y, y_len, NULL, 0)) { return -1; } @@ -342,13 +340,13 @@ hostkey_method_ssh_dss_initPEM(LIBSSH2_SESSION * session, libssh2_dsa_ctx *dsactx; int ret; - if (*abstract) { + if(*abstract) { hostkey_method_ssh_dss_dtor(session, abstract); *abstract = NULL; } ret = _libssh2_dsa_new_private(&dsactx, session, privkeyfile, passphrase); - if (ret) { + if(ret) { return -1; } @@ -372,7 +370,7 @@ hostkey_method_ssh_dss_initPEMFromMemory(LIBSSH2_SESSION * session, libssh2_dsa_ctx *dsactx; int ret; - if (*abstract) { + if(*abstract) { hostkey_method_ssh_dss_dtor(session, abstract); *abstract = NULL; } @@ -380,7 +378,7 @@ hostkey_method_ssh_dss_initPEMFromMemory(LIBSSH2_SESSION * session, ret = _libssh2_dsa_new_private_frommemory(&dsactx, session, privkeyfiledata, privkeyfiledata_len, passphrase); - if (ret) { + if(ret) { return -1; } @@ -404,12 +402,14 @@ hostkey_method_ssh_dss_sig_verify(LIBSSH2_SESSION * session, libssh2_dsa_ctx *dsactx = (libssh2_dsa_ctx *) (*abstract); /* Skip past keyname_len(4) + keyname(7){"ssh-dss"} + signature_len(4) */ - sig += 15; - sig_len -= 15; - if (sig_len != 40) { + if(sig_len != 55) { return _libssh2_error(session, LIBSSH2_ERROR_PROTO, "Invalid DSS signature length"); } + + sig += 15; + sig_len -= 15; + return _libssh2_dsa_sha1_verify(dsactx, sig, m, m_len); } @@ -432,7 +432,7 @@ hostkey_method_ssh_dss_signv(LIBSSH2_SESSION * session, int i; *signature = LIBSSH2_CALLOC(session, 2 * SHA_DIGEST_LENGTH); - if (!*signature) { + if(!*signature) { return -1; } @@ -444,7 +444,7 @@ hostkey_method_ssh_dss_signv(LIBSSH2_SESSION * session, } libssh2_sha1_final(ctx, hash); - if (_libssh2_dsa_sha1_sign(dsactx, hash, SHA_DIGEST_LENGTH, *signature)) { + if(_libssh2_dsa_sha1_sign(dsactx, hash, SHA_DIGEST_LENGTH, *signature)) { LIBSSH2_FREE(session, *signature); return -1; } @@ -483,7 +483,526 @@ static const LIBSSH2_HOSTKEY_METHOD hostkey_method_ssh_dss = { }; #endif /* LIBSSH2_DSA */ +#if LIBSSH2_ECDSA + +/* *********** + * ecdsa-sha2-nistp256/384/521 * + *********** */ + +static int +hostkey_method_ssh_ecdsa_dtor(LIBSSH2_SESSION * session, + void **abstract); + +/* + * hostkey_method_ssh_ecdsa_init + * + * Initialize the server hostkey working area with e/n pair + */ +static int +hostkey_method_ssh_ecdsa_init(LIBSSH2_SESSION * session, + const unsigned char *hostkey_data, + size_t hostkey_data_len, + void **abstract) +{ + libssh2_ecdsa_ctx *ecdsactx = NULL; + unsigned char *type_str, *domain, *public_key; + size_t key_len, len; + libssh2_curve_type type; + struct string_buf buf; + + if(abstract != NULL && *abstract) { + hostkey_method_ssh_ecdsa_dtor(session, abstract); + *abstract = NULL; + } + + if(hostkey_data_len < 39) { + _libssh2_debug(session, LIBSSH2_TRACE_ERROR, + "host key length too short"); + return -1; + } + + buf.data = (unsigned char *)hostkey_data; + buf.dataptr = buf.data; + buf.len = hostkey_data_len; + + if(_libssh2_get_string(&buf, &type_str, &len) || len != 19) + return -1; + + if(strncmp((char *) type_str, "ecdsa-sha2-nistp256", 19) == 0) { + type = LIBSSH2_EC_CURVE_NISTP256; + } + else if(strncmp((char *) type_str, "ecdsa-sha2-nistp384", 19) == 0) { + type = LIBSSH2_EC_CURVE_NISTP384; + } + else if(strncmp((char *) type_str, "ecdsa-sha2-nistp521", 19) == 0) { + type = LIBSSH2_EC_CURVE_NISTP521; + } + else { + return -1; + } + + if(_libssh2_get_string(&buf, &domain, &len) || len != 8) + return -1; + + if(type == LIBSSH2_EC_CURVE_NISTP256 && + strncmp((char *)domain, "nistp256", 8) != 0) { + return -1; + } + else if(type == LIBSSH2_EC_CURVE_NISTP384 && + strncmp((char *)domain, "nistp384", 8) != 0) { + return -1; + } + else if(type == LIBSSH2_EC_CURVE_NISTP521 && + strncmp((char *)domain, "nistp521", 8) != 0) { + return -1; + } + + /* public key */ + if(_libssh2_get_string(&buf, &public_key, &key_len)) + return -1; + + if(_libssh2_ecdsa_curve_name_with_octal_new(&ecdsactx, public_key, + key_len, type)) + return -1; + + if(abstract != NULL) + *abstract = ecdsactx; + + return 0; +} + +/* + * hostkey_method_ssh_ecdsa_initPEM + * + * Load a Private Key from a PEM file + */ +static int +hostkey_method_ssh_ecdsa_initPEM(LIBSSH2_SESSION * session, + const char *privkeyfile, + unsigned const char *passphrase, + void **abstract) +{ + libssh2_ecdsa_ctx *ec_ctx = NULL; + int ret; + + if(abstract != NULL && *abstract) { + hostkey_method_ssh_ecdsa_dtor(session, abstract); + *abstract = NULL; + } + + ret = _libssh2_ecdsa_new_private(&ec_ctx, session, + privkeyfile, passphrase); + + if(abstract != NULL) + *abstract = ec_ctx; + + return ret; +} + +/* + * hostkey_method_ssh_ecdsa_initPEMFromMemory + * + * Load a Private Key from memory + */ +static int +hostkey_method_ssh_ecdsa_initPEMFromMemory(LIBSSH2_SESSION * session, + const char *privkeyfiledata, + size_t privkeyfiledata_len, + unsigned const char *passphrase, + void **abstract) +{ + libssh2_ecdsa_ctx *ec_ctx = NULL; + int ret; + + if(abstract != NULL && *abstract) { + hostkey_method_ssh_ecdsa_dtor(session, abstract); + *abstract = NULL; + } + + ret = _libssh2_ecdsa_new_private_frommemory(&ec_ctx, session, + privkeyfiledata, + privkeyfiledata_len, + passphrase); + if(ret) { + return -1; + } + + if(abstract != NULL) + *abstract = ec_ctx; + + return 0; +} + +/* + * hostkey_method_ecdsa_sig_verify + * + * Verify signature created by remote + */ +static int +hostkey_method_ssh_ecdsa_sig_verify(LIBSSH2_SESSION * session, + const unsigned char *sig, + size_t sig_len, + const unsigned char *m, + size_t m_len, void **abstract) +{ + unsigned char *r, *s, *name; + size_t r_len, s_len, name_len; + unsigned int len; + struct string_buf buf; + libssh2_ecdsa_ctx *ctx = (libssh2_ecdsa_ctx *) (*abstract); + + (void) session; + + if(sig_len < 35) + return -1; + + /* keyname_len(4) + keyname(19){"ecdsa-sha2-nistp256"} + + signature_len(4) */ + buf.data = (unsigned char *)sig; + buf.dataptr = buf.data; + buf.len = sig_len; + + if(_libssh2_get_string(&buf, &name, &name_len) || name_len != 19) + return -1; + + if(_libssh2_get_u32(&buf, &len) != 0 || len < 8) + return -1; + + if(_libssh2_get_string(&buf, &r, &r_len)) + return -1; + + if(_libssh2_get_string(&buf, &s, &s_len)) + return -1; + + return _libssh2_ecdsa_verify(ctx, r, r_len, s, s_len, m, m_len); +} + + +#define LIBSSH2_HOSTKEY_METHOD_EC_SIGNV_HASH(digest_type) \ + { \ + unsigned char hash[SHA##digest_type##_DIGEST_LENGTH]; \ + libssh2_sha##digest_type##_ctx ctx; \ + int i; \ + libssh2_sha##digest_type##_init(&ctx); \ + for(i = 0; i < veccount; i++) { \ + libssh2_sha##digest_type##_update(ctx, datavec[i].iov_base, \ + datavec[i].iov_len); \ + } \ + libssh2_sha##digest_type##_final(ctx, hash); \ + ret = _libssh2_ecdsa_sign(session, ec_ctx, hash, \ + SHA##digest_type##_DIGEST_LENGTH, \ + signature, signature_len); \ + } + + +/* + * hostkey_method_ecdsa_signv + * + * Construct a signature from an array of vectors + */ +static int +hostkey_method_ssh_ecdsa_signv(LIBSSH2_SESSION * session, + unsigned char **signature, + size_t *signature_len, + int veccount, + const struct iovec datavec[], + void **abstract) +{ + libssh2_ecdsa_ctx *ec_ctx = (libssh2_ecdsa_ctx *) (*abstract); + libssh2_curve_type type = _libssh2_ecdsa_key_get_curve_type(ec_ctx); + int ret = 0; + + if(type == LIBSSH2_EC_CURVE_NISTP256) { + LIBSSH2_HOSTKEY_METHOD_EC_SIGNV_HASH(256); + } + else if(type == LIBSSH2_EC_CURVE_NISTP384) { + LIBSSH2_HOSTKEY_METHOD_EC_SIGNV_HASH(384); + } + else if(type == LIBSSH2_EC_CURVE_NISTP521) { + LIBSSH2_HOSTKEY_METHOD_EC_SIGNV_HASH(512); + } + else { + return -1; + } + + return ret; +} + +/* + * hostkey_method_ssh_ecdsa_dtor + * + * Shutdown the hostkey by freeing EC_KEY context + */ +static int +hostkey_method_ssh_ecdsa_dtor(LIBSSH2_SESSION * session, void **abstract) +{ + libssh2_ecdsa_ctx *keyctx = (libssh2_ecdsa_ctx *) (*abstract); + (void) session; + + if(keyctx != NULL) + _libssh2_ecdsa_free(keyctx); + + *abstract = NULL; + + return 0; +} + +static const LIBSSH2_HOSTKEY_METHOD hostkey_method_ecdsa_ssh_nistp256 = { + "ecdsa-sha2-nistp256", + SHA256_DIGEST_LENGTH, + hostkey_method_ssh_ecdsa_init, + hostkey_method_ssh_ecdsa_initPEM, + hostkey_method_ssh_ecdsa_initPEMFromMemory, + hostkey_method_ssh_ecdsa_sig_verify, + hostkey_method_ssh_ecdsa_signv, + NULL, /* encrypt */ + hostkey_method_ssh_ecdsa_dtor, +}; + +static const LIBSSH2_HOSTKEY_METHOD hostkey_method_ecdsa_ssh_nistp384 = { + "ecdsa-sha2-nistp384", + SHA384_DIGEST_LENGTH, + hostkey_method_ssh_ecdsa_init, + hostkey_method_ssh_ecdsa_initPEM, + hostkey_method_ssh_ecdsa_initPEMFromMemory, + hostkey_method_ssh_ecdsa_sig_verify, + hostkey_method_ssh_ecdsa_signv, + NULL, /* encrypt */ + hostkey_method_ssh_ecdsa_dtor, +}; + +static const LIBSSH2_HOSTKEY_METHOD hostkey_method_ecdsa_ssh_nistp521 = { + "ecdsa-sha2-nistp521", + SHA512_DIGEST_LENGTH, + hostkey_method_ssh_ecdsa_init, + hostkey_method_ssh_ecdsa_initPEM, + hostkey_method_ssh_ecdsa_initPEMFromMemory, + hostkey_method_ssh_ecdsa_sig_verify, + hostkey_method_ssh_ecdsa_signv, + NULL, /* encrypt */ + hostkey_method_ssh_ecdsa_dtor, +}; + +#endif /* LIBSSH2_ECDSA */ + +#if LIBSSH2_ED25519 + +/* *********** + * ed25519 * + *********** */ + +static int hostkey_method_ssh_ed25519_dtor(LIBSSH2_SESSION * session, + void **abstract); + +/* + * hostkey_method_ssh_ed25519_init + * + * Initialize the server hostkey working area with e/n pair + */ +static int +hostkey_method_ssh_ed25519_init(LIBSSH2_SESSION * session, + const unsigned char *hostkey_data, + size_t hostkey_data_len, + void **abstract) +{ + const unsigned char *s; + unsigned long len, key_len; + libssh2_ed25519_ctx *ctx = NULL; + + if(*abstract) { + hostkey_method_ssh_ed25519_dtor(session, abstract); + *abstract = NULL; + } + + if(hostkey_data_len < 19) { + _libssh2_debug(session, LIBSSH2_TRACE_ERROR, + "host key length too short"); + return -1; + } + + s = hostkey_data; + len = _libssh2_ntohu32(s); + s += 4; + + if(len != 11 || strncmp((char *) s, "ssh-ed25519", 11) != 0) { + return -1; + } + + s += 11; + + /* public key */ + key_len = _libssh2_ntohu32(s); + s += 4; + + if(_libssh2_ed25519_new_public(&ctx, session, s, key_len) != 0) { + return -1; + } + + *abstract = ctx; + + return 0; +} + +/* + * hostkey_method_ssh_ed25519_initPEM + * + * Load a Private Key from a PEM file + */ +static int +hostkey_method_ssh_ed25519_initPEM(LIBSSH2_SESSION * session, + const char *privkeyfile, + unsigned const char *passphrase, + void **abstract) +{ + libssh2_ed25519_ctx *ec_ctx = NULL; + int ret; + + if(*abstract) { + hostkey_method_ssh_ed25519_dtor(session, abstract); + *abstract = NULL; + } + + ret = _libssh2_ed25519_new_private(&ec_ctx, session, + privkeyfile, passphrase); + if(ret) { + return -1; + } + + *abstract = ec_ctx; + + return ret; +} + +/* + * hostkey_method_ssh_ed25519_initPEMFromMemory + * + * Load a Private Key from memory + */ +static int +hostkey_method_ssh_ed25519_initPEMFromMemory(LIBSSH2_SESSION * session, + const char *privkeyfiledata, + size_t privkeyfiledata_len, + unsigned const char *passphrase, + void **abstract) +{ + libssh2_ed25519_ctx *ed_ctx = NULL; + int ret; + + if(abstract != NULL && *abstract) { + hostkey_method_ssh_ed25519_dtor(session, abstract); + *abstract = NULL; + } + + ret = _libssh2_ed25519_new_private_frommemory(&ed_ctx, session, + privkeyfiledata, + privkeyfiledata_len, + passphrase); + if(ret) { + return -1; + } + + if(abstract != NULL) + *abstract = ed_ctx; + + return 0; +} + +/* + * hostkey_method_ssh_ed25519_sig_verify + * + * Verify signature created by remote + */ +static int +hostkey_method_ssh_ed25519_sig_verify(LIBSSH2_SESSION * session, + const unsigned char *sig, + size_t sig_len, + const unsigned char *m, + size_t m_len, void **abstract) +{ + libssh2_ed25519_ctx *ctx = (libssh2_ed25519_ctx *) (*abstract); + (void) session; + + if(sig_len < 19) + return -1; + + /* Skip past keyname_len(4) + keyname(11){"ssh-ed25519"} + + signature_len(4) */ + sig += 19; + sig_len -= 19; + + if(sig_len != LIBSSH2_ED25519_SIG_LEN) + return -1; + + return _libssh2_ed25519_verify(ctx, sig, sig_len, m, m_len); +} + +/* + * hostkey_method_ssh_ed25519_signv + * + * Construct a signature from an array of vectors + */ +static int +hostkey_method_ssh_ed25519_signv(LIBSSH2_SESSION * session, + unsigned char **signature, + size_t *signature_len, + int veccount, + const struct iovec datavec[], + void **abstract) +{ + libssh2_ed25519_ctx *ctx = (libssh2_ed25519_ctx *) (*abstract); + + if(veccount != 1) { + return -1; + } + + return _libssh2_ed25519_sign(ctx, session, signature, signature_len, + datavec[0].iov_base, datavec[0].iov_len); +} + + +/* + * hostkey_method_ssh_ed25519_dtor + * + * Shutdown the hostkey by freeing key context + */ +static int +hostkey_method_ssh_ed25519_dtor(LIBSSH2_SESSION * session, void **abstract) +{ + libssh2_ed25519_ctx *keyctx = (libssh2_ed25519_ctx*) (*abstract); + (void) session; + + if(keyctx) + _libssh2_ed25519_free(keyctx); + + *abstract = NULL; + + return 0; +} + +static const LIBSSH2_HOSTKEY_METHOD hostkey_method_ssh_ed25519 = { + "ssh-ed25519", + SHA256_DIGEST_LENGTH, + hostkey_method_ssh_ed25519_init, + hostkey_method_ssh_ed25519_initPEM, + hostkey_method_ssh_ed25519_initPEMFromMemory, + hostkey_method_ssh_ed25519_sig_verify, + hostkey_method_ssh_ed25519_signv, + NULL, /* encrypt */ + hostkey_method_ssh_ed25519_dtor, +}; + +#endif /*LIBSSH2_ED25519*/ + + static const LIBSSH2_HOSTKEY_METHOD *hostkey_methods[] = { +#if LIBSSH2_ECDSA + &hostkey_method_ecdsa_ssh_nistp256, + &hostkey_method_ecdsa_ssh_nistp384, + &hostkey_method_ecdsa_ssh_nistp521, +#endif +#if LIBSSH2_ED25519 + &hostkey_method_ssh_ed25519, +#endif #if LIBSSH2_RSA &hostkey_method_ssh_rsa, #endif /* LIBSSH2_RSA */ @@ -505,12 +1024,12 @@ 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) { - switch (hash_type) { + switch(hash_type) { #if LIBSSH2_MD5 case LIBSSH2_HOSTKEY_HASH_MD5: return (session->server_hostkey_md5_valid) @@ -523,6 +1042,11 @@ libssh2_hostkey_hash(LIBSSH2_SESSION * session, int hash_type) ? (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; } @@ -530,22 +1054,55 @@ libssh2_hostkey_hash(LIBSSH2_SESSION * session, int hash_type) static int hostkey_type(const unsigned char *hostkey, size_t len) { - const unsigned char rsa[] = { + static const unsigned char rsa[] = { 0, 0, 0, 0x07, 's', 's', 'h', '-', 'r', 's', 'a' }; - const unsigned char dss[] = { + static const unsigned char dss[] = { 0, 0, 0, 0x07, 's', 's', 'h', '-', 'd', 's', 's' }; + static const unsigned char ecdsa_256[] = { + 0, 0, 0, 0x13, 'e', 'c', 'd', 's', 'a', '-', 's', 'h', 'a', '2', '-', + 'n', 'i', 's', 't', 'p', '2', '5', '6' + }; + static const unsigned char ecdsa_384[] = { + 0, 0, 0, 0x13, 'e', 'c', 'd', 's', 'a', '-', 's', 'h', 'a', '2', '-', + 'n', 'i', 's', 't', 'p', '3', '8', '4' + }; + static const unsigned char ecdsa_521[] = { + 0, 0, 0, 0x13, 'e', 'c', 'd', 's', 'a', '-', 's', 'h', 'a', '2', '-', + 'n', 'i', 's', 't', 'p', '5', '2', '1' + }; + static const unsigned char ed25519[] = { + 0, 0, 0, 0x0b, 's', 's', 'h', '-', 'e', 'd', '2', '5', '5', '1', '9' + }; - if (len < 11) + if(len < 11) return LIBSSH2_HOSTKEY_TYPE_UNKNOWN; - if (!memcmp(rsa, hostkey, 11)) + if(!memcmp(rsa, hostkey, 11)) return LIBSSH2_HOSTKEY_TYPE_RSA; - if (!memcmp(dss, hostkey, 11)) + if(!memcmp(dss, hostkey, 11)) return LIBSSH2_HOSTKEY_TYPE_DSS; + if(len < 15) + return LIBSSH2_HOSTKEY_TYPE_UNKNOWN; + + if(!memcmp(ed25519, hostkey, 15)) + return LIBSSH2_HOSTKEY_TYPE_ED25519; + + if(len < 23) + return LIBSSH2_HOSTKEY_TYPE_UNKNOWN; + + if(!memcmp(ecdsa_256, hostkey, 23)) + return LIBSSH2_HOSTKEY_TYPE_ECDSA_256; + + if(!memcmp(ecdsa_384, hostkey, 23)) + return LIBSSH2_HOSTKEY_TYPE_ECDSA_384; + + if(!memcmp(ecdsa_521, hostkey, 23)) + return LIBSSH2_HOSTKEY_TYPE_ECDSA_521; + return LIBSSH2_HOSTKEY_TYPE_UNKNOWN; } @@ -561,7 +1118,7 @@ libssh2_session_hostkey(LIBSSH2_SESSION *session, size_t *len, int *type) if(session->server_hostkey_len) { if(len) *len = session->server_hostkey_len; - if (type) + if(type) *type = hostkey_type(session->server_hostkey, session->server_hostkey_len); return (char *) session->server_hostkey; @@ -570,4 +1127,3 @@ libssh2_session_hostkey(LIBSSH2_SESSION *session, size_t *len, int *type) *len = 0; return NULL; } - |