mirror of
https://github.com/libssh2/libssh2.git
synced 2025-08-10 06:23:02 +03:00
Merge remote-tracking branch 'origin/sha2' into shellfish
This commit is contained in:
@@ -637,6 +637,32 @@ Note: this procedure is not used if macro _libssh2_rsa_sha1_signv() is defined.
|
||||
void _libssh2_rsa_free(libssh2_rsa_ctx *rsactx);
|
||||
Releases the RSA computation context at rsactx.
|
||||
|
||||
LIBSSH2_RSA_SHA2
|
||||
#define as 1 if the crypto library supports RSA SHA2 256/512, else 0.
|
||||
If defined as 0, the rest of this section can be omitted.
|
||||
|
||||
int _libssh2_rsa_sha2_sign(LIBSSH2_SESSION * session,
|
||||
libssh2_rsa_ctx * rsactx,
|
||||
const unsigned char *hash,
|
||||
size_t hash_len,
|
||||
unsigned char **signature,
|
||||
size_t *signature_len);
|
||||
RSA signs the (hash, hashlen) SHA-2 hash bytes based on hash length and stores
|
||||
the allocated signature at (signature, signature_len).
|
||||
Signature buffer must be allocated from the given session.
|
||||
Returns 0 if OK, else -1.
|
||||
This procedure is already prototyped in crypto.h.
|
||||
Note: this procedure is not used if macro _libssh2_rsa_sha1_signv() is defined.
|
||||
|
||||
int _libssh2_rsa_sha2_verify(libssh2_rsa_ctx * rsa,
|
||||
size_t hash_len,
|
||||
const unsigned char *sig,
|
||||
unsigned long sig_len,
|
||||
const unsigned char *m, unsigned long m_len);
|
||||
Verify (sig, sig_len) signature of (m, m_len) using an SHA-2 hash based on
|
||||
hash length and the RSA context.
|
||||
Return 0 if OK, else -1.
|
||||
This procedure is already prototyped in crypto.h.
|
||||
|
||||
7.2) DSA
|
||||
LIBSSH2_DSA
|
||||
|
13
src/crypto.h
13
src/crypto.h
@@ -93,6 +93,19 @@ int _libssh2_rsa_sha1_sign(LIBSSH2_SESSION * session,
|
||||
size_t hash_len,
|
||||
unsigned char **signature,
|
||||
size_t *signature_len);
|
||||
#if LIBSSH2_RSA_SHA2
|
||||
int _libssh2_rsa_sha2_sign(LIBSSH2_SESSION * session,
|
||||
libssh2_rsa_ctx * rsactx,
|
||||
const unsigned char *hash,
|
||||
size_t hash_len,
|
||||
unsigned char **signature,
|
||||
size_t *signature_len);
|
||||
int _libssh2_rsa_sha2_verify(libssh2_rsa_ctx * rsa,
|
||||
size_t hash_len,
|
||||
const unsigned char *sig,
|
||||
unsigned long sig_len,
|
||||
const unsigned char *m, unsigned long m_len);
|
||||
#endif
|
||||
int _libssh2_rsa_new_private_frommemory(libssh2_rsa_ctx ** rsa,
|
||||
LIBSSH2_SESSION * session,
|
||||
const char *filedata,
|
||||
|
173
src/hostkey.c
173
src/hostkey.c
@@ -227,6 +227,146 @@ hostkey_method_ssh_rsa_signv(LIBSSH2_SESSION * session,
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
* hostkey_method_ssh_rsa_sha2_256_sig_verify
|
||||
*
|
||||
* Verify signature created by remote
|
||||
*/
|
||||
#if LIBSSH2_RSA_SHA2
|
||||
|
||||
static int
|
||||
hostkey_method_ssh_rsa_sha2_256_sig_verify(LIBSSH2_SESSION * session,
|
||||
const unsigned char *sig,
|
||||
size_t sig_len,
|
||||
const unsigned char *m,
|
||||
size_t m_len, void **abstract)
|
||||
{
|
||||
libssh2_rsa_ctx *rsactx = (libssh2_rsa_ctx *) (*abstract);
|
||||
(void) session;
|
||||
|
||||
/* Skip past keyname_len(4) + keyname(12){"rsa-sha2-256"} +
|
||||
signature_len(4) */
|
||||
if(sig_len < 20)
|
||||
return -1;
|
||||
|
||||
sig += 20;
|
||||
sig_len -= 20;
|
||||
return _libssh2_rsa_sha2_verify(rsactx, SHA256_DIGEST_LENGTH, sig, sig_len,
|
||||
m, m_len);
|
||||
}
|
||||
|
||||
/*
|
||||
* hostkey_method_ssh_rsa_sha2_256_signv
|
||||
*
|
||||
* Construct a signature from an array of vectors
|
||||
*/
|
||||
|
||||
static int
|
||||
hostkey_method_ssh_rsa_sha2_256_signv(LIBSSH2_SESSION * session,
|
||||
unsigned char **signature,
|
||||
size_t *signature_len,
|
||||
int veccount,
|
||||
const struct iovec datavec[],
|
||||
void **abstract)
|
||||
{
|
||||
libssh2_rsa_ctx *rsactx = (libssh2_rsa_ctx *) (*abstract);
|
||||
|
||||
#ifdef _libssh2_rsa_sha2_256_signv
|
||||
return _libssh2_rsa_sha2_256_signv(session, signature, signature_len,
|
||||
veccount, datavec, rsactx);
|
||||
#else
|
||||
int ret;
|
||||
int i;
|
||||
unsigned char hash[SHA256_DIGEST_LENGTH];
|
||||
libssh2_sha256_ctx ctx;
|
||||
|
||||
libssh2_sha256_init(&ctx);
|
||||
for(i = 0; i < veccount; i++) {
|
||||
libssh2_sha256_update(ctx, datavec[i].iov_base, datavec[i].iov_len);
|
||||
}
|
||||
libssh2_sha256_final(ctx, hash);
|
||||
|
||||
ret = _libssh2_rsa_sha2_sign(session, rsactx, hash, SHA256_DIGEST_LENGTH,
|
||||
signature, signature_len);
|
||||
if(ret) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
* hostkey_method_ssh_rsa_sha2_512_sig_verify
|
||||
*
|
||||
* Verify signature created by remote
|
||||
*/
|
||||
|
||||
static int
|
||||
hostkey_method_ssh_rsa_sha2_512_sig_verify(LIBSSH2_SESSION * session,
|
||||
const unsigned char *sig,
|
||||
size_t sig_len,
|
||||
const unsigned char *m,
|
||||
size_t m_len, void **abstract)
|
||||
{
|
||||
libssh2_rsa_ctx *rsactx = (libssh2_rsa_ctx *) (*abstract);
|
||||
(void) session;
|
||||
|
||||
/* Skip past keyname_len(4) + keyname(12){"rsa-sha2-512"} +
|
||||
signature_len(4) */
|
||||
if(sig_len < 20)
|
||||
return -1;
|
||||
|
||||
sig += 20;
|
||||
sig_len -= 20;
|
||||
return _libssh2_rsa_sha2_verify(rsactx, SHA512_DIGEST_LENGTH, sig,
|
||||
sig_len, m, m_len);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* hostkey_method_ssh_rsa_sha2_512_signv
|
||||
*
|
||||
* Construct a signature from an array of vectors
|
||||
*/
|
||||
static int
|
||||
hostkey_method_ssh_rsa_sha2_512_signv(LIBSSH2_SESSION * session,
|
||||
unsigned char **signature,
|
||||
size_t *signature_len,
|
||||
int veccount,
|
||||
const struct iovec datavec[],
|
||||
void **abstract)
|
||||
{
|
||||
libssh2_rsa_ctx *rsactx = (libssh2_rsa_ctx *) (*abstract);
|
||||
|
||||
#ifdef _libssh2_rsa_sha2_512_signv
|
||||
return _libssh2_rsa_sha2_512_signv(session, signature, signature_len,
|
||||
veccount, datavec, rsactx);
|
||||
#else
|
||||
int ret;
|
||||
int i;
|
||||
unsigned char hash[SHA512_DIGEST_LENGTH];
|
||||
libssh2_sha512_ctx ctx;
|
||||
|
||||
libssh2_sha512_init(&ctx);
|
||||
for(i = 0; i < veccount; i++) {
|
||||
libssh2_sha512_update(ctx, datavec[i].iov_base, datavec[i].iov_len);
|
||||
}
|
||||
libssh2_sha512_final(ctx, hash);
|
||||
|
||||
ret = _libssh2_rsa_sha2_sign(session, rsactx, hash, SHA512_DIGEST_LENGTH,
|
||||
signature, signature_len);
|
||||
if(ret) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif /* LIBSSH2_RSA_SHA2 */
|
||||
|
||||
|
||||
/*
|
||||
* hostkey_method_ssh_rsa_dtor
|
||||
*
|
||||
@@ -260,6 +400,35 @@ static const LIBSSH2_HOSTKEY_METHOD hostkey_method_ssh_rsa = {
|
||||
NULL, /* encrypt */
|
||||
hostkey_method_ssh_rsa_dtor,
|
||||
};
|
||||
|
||||
#if LIBSSH2_RSA_SHA2
|
||||
|
||||
static const LIBSSH2_HOSTKEY_METHOD hostkey_method_ssh_rsa_sha2_256 = {
|
||||
"rsa-sha2-256",
|
||||
SHA256_DIGEST_LENGTH,
|
||||
hostkey_method_ssh_rsa_init,
|
||||
hostkey_method_ssh_rsa_initPEM,
|
||||
hostkey_method_ssh_rsa_initPEMFromMemory,
|
||||
hostkey_method_ssh_rsa_sha2_256_sig_verify,
|
||||
hostkey_method_ssh_rsa_sha2_256_signv,
|
||||
NULL, /* encrypt */
|
||||
hostkey_method_ssh_rsa_dtor,
|
||||
};
|
||||
|
||||
static const LIBSSH2_HOSTKEY_METHOD hostkey_method_ssh_rsa_sha2_512 = {
|
||||
"rsa-sha2-512",
|
||||
SHA512_DIGEST_LENGTH,
|
||||
hostkey_method_ssh_rsa_init,
|
||||
hostkey_method_ssh_rsa_initPEM,
|
||||
hostkey_method_ssh_rsa_initPEMFromMemory,
|
||||
hostkey_method_ssh_rsa_sha2_512_sig_verify,
|
||||
hostkey_method_ssh_rsa_sha2_512_signv,
|
||||
NULL, /* encrypt */
|
||||
hostkey_method_ssh_rsa_dtor,
|
||||
};
|
||||
|
||||
#endif /* LIBSSH2_RSA_SHA2 */
|
||||
|
||||
#endif /* LIBSSH2_RSA */
|
||||
|
||||
#if LIBSSH2_DSA
|
||||
@@ -1043,6 +1212,10 @@ static const LIBSSH2_HOSTKEY_METHOD *hostkey_methods[] = {
|
||||
&hostkey_method_ssh_ed25519,
|
||||
#endif
|
||||
#if LIBSSH2_RSA
|
||||
#if LIBSSH2_RSA_SHA2
|
||||
&hostkey_method_ssh_rsa_sha2_512,
|
||||
&hostkey_method_ssh_rsa_sha2_256,
|
||||
#endif /* LIBSSH2_RSA_SHA2 */
|
||||
&hostkey_method_ssh_rsa,
|
||||
#endif /* LIBSSH2_RSA */
|
||||
#if LIBSSH2_DSA
|
||||
|
@@ -55,6 +55,7 @@
|
||||
#define LIBSSH2_3DES 1
|
||||
|
||||
#define LIBSSH2_RSA 1
|
||||
#define LIBSSH2_RSA_SHA2 0
|
||||
#define LIBSSH2_DSA 1
|
||||
#define LIBSSH2_ECDSA 0
|
||||
#define LIBSSH2_ED25519 0
|
||||
|
@@ -71,6 +71,7 @@
|
||||
#define LIBSSH2_3DES 1
|
||||
|
||||
#define LIBSSH2_RSA 1
|
||||
#define LIBSSH2_RSA_SHA2 0
|
||||
#define LIBSSH2_DSA 0
|
||||
#ifdef MBEDTLS_ECDSA_C
|
||||
# define LIBSSH2_ECDSA 1
|
||||
|
@@ -153,20 +153,56 @@ _libssh2_rsa_new(libssh2_rsa_ctx ** rsa,
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
_libssh2_rsa_sha2_verify(libssh2_rsa_ctx * rsactx,
|
||||
size_t hash_len,
|
||||
const unsigned char *sig,
|
||||
unsigned long sig_len,
|
||||
const unsigned char *m, unsigned long m_len)
|
||||
{
|
||||
int ret;
|
||||
int nid_type;
|
||||
unsigned char *hash = malloc(hash_len);
|
||||
if(hash == NULL)
|
||||
return -1;
|
||||
|
||||
if(hash_len == SHA_DIGEST_LENGTH) {
|
||||
nid_type = NID_sha1;
|
||||
ret = _libssh2_sha1(m, m_len, hash);
|
||||
}
|
||||
else if(hash_len == SHA256_DIGEST_LENGTH) {
|
||||
nid_type = NID_sha256;
|
||||
ret = _libssh2_sha256(m, m_len, hash);
|
||||
|
||||
}
|
||||
else if(hash_len == SHA512_DIGEST_LENGTH) {
|
||||
nid_type = NID_sha512;
|
||||
ret = _libssh2_sha512(m, m_len, hash);
|
||||
}
|
||||
else
|
||||
ret = -1; /* unsupported digest */
|
||||
|
||||
if(ret != 0) {
|
||||
free(hash);
|
||||
return -1; /* failure */
|
||||
}
|
||||
|
||||
ret = RSA_verify(nid_type, hash, hash_len,
|
||||
(unsigned char *) sig, sig_len, rsactx);
|
||||
|
||||
free(hash);
|
||||
|
||||
return (ret == 1) ? 0 : -1;
|
||||
}
|
||||
|
||||
int
|
||||
_libssh2_rsa_sha1_verify(libssh2_rsa_ctx * rsactx,
|
||||
const unsigned char *sig,
|
||||
unsigned long sig_len,
|
||||
const unsigned char *m, unsigned long m_len)
|
||||
{
|
||||
unsigned char hash[SHA_DIGEST_LENGTH];
|
||||
int ret;
|
||||
|
||||
if(_libssh2_sha1(m, m_len, hash))
|
||||
return -1; /* failure */
|
||||
ret = RSA_verify(NID_sha1, hash, SHA_DIGEST_LENGTH,
|
||||
(unsigned char *) sig, sig_len, rsactx);
|
||||
return (ret == 1) ? 0 : -1;
|
||||
return _libssh2_rsa_sha2_verify(rsactx, SHA_DIGEST_LENGTH, sig, sig_len, m,
|
||||
m_len);
|
||||
}
|
||||
|
||||
#if LIBSSH2_DSA
|
||||
@@ -1876,7 +1912,7 @@ _libssh2_ed25519_new_public(libssh2_ed25519_ctx ** ed_ctx,
|
||||
|
||||
|
||||
int
|
||||
_libssh2_rsa_sha1_sign(LIBSSH2_SESSION * session,
|
||||
_libssh2_rsa_sha2_sign(LIBSSH2_SESSION * session,
|
||||
libssh2_rsa_ctx * rsactx,
|
||||
const unsigned char *hash,
|
||||
size_t hash_len,
|
||||
@@ -1893,7 +1929,17 @@ _libssh2_rsa_sha1_sign(LIBSSH2_SESSION * session,
|
||||
return -1;
|
||||
}
|
||||
|
||||
ret = RSA_sign(NID_sha1, hash, hash_len, sig, &sig_len, rsactx);
|
||||
if(hash_len == SHA_DIGEST_LENGTH)
|
||||
ret = RSA_sign(NID_sha1, hash, hash_len, sig, &sig_len, rsactx);
|
||||
else if(hash_len == SHA256_DIGEST_LENGTH)
|
||||
ret = RSA_sign(NID_sha256, hash, hash_len, sig, &sig_len, rsactx);
|
||||
else if(hash_len == SHA512_DIGEST_LENGTH)
|
||||
ret = RSA_sign(NID_sha512, hash, hash_len, sig, &sig_len, rsactx);
|
||||
else {
|
||||
_libssh2_error(session, LIBSSH2_ERROR_PROTO,
|
||||
"Unsupported hash digest length");
|
||||
ret = -1;
|
||||
}
|
||||
|
||||
if(!ret) {
|
||||
LIBSSH2_FREE(session, sig);
|
||||
@@ -1906,6 +1952,19 @@ _libssh2_rsa_sha1_sign(LIBSSH2_SESSION * session,
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
_libssh2_rsa_sha1_sign(LIBSSH2_SESSION * session,
|
||||
libssh2_rsa_ctx * rsactx,
|
||||
const unsigned char *hash,
|
||||
size_t hash_len,
|
||||
unsigned char **signature, size_t *signature_len)
|
||||
{
|
||||
return _libssh2_rsa_sha2_sign(session, rsactx, hash, hash_len,
|
||||
signature, signature_len);
|
||||
}
|
||||
|
||||
|
||||
#if LIBSSH2_DSA
|
||||
int
|
||||
_libssh2_dsa_sha1_sign(libssh2_dsa_ctx * dsactx,
|
||||
|
@@ -64,8 +64,10 @@
|
||||
|
||||
#ifdef OPENSSL_NO_RSA
|
||||
# define LIBSSH2_RSA 0
|
||||
# define LIBSSH2_RSA_SHA2 0
|
||||
#else
|
||||
# define LIBSSH2_RSA 1
|
||||
# define LIBSSH2_RSA_SHA2 1
|
||||
#endif
|
||||
|
||||
#ifdef OPENSSL_NO_DSA
|
||||
|
@@ -175,6 +175,7 @@
|
||||
#define LIBSSH2_3DES 1
|
||||
|
||||
#define LIBSSH2_RSA 1
|
||||
#define LIBSSH2_RSA_SHA2 0
|
||||
#define LIBSSH2_DSA 0
|
||||
#define LIBSSH2_ECDSA 0
|
||||
#define LIBSSH2_ED25519 0
|
||||
|
@@ -549,6 +549,24 @@ libssh2_userauth_password_ex(LIBSSH2_SESSION *session, const char *username,
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*
|
||||
* upgrade_publickey_method
|
||||
*
|
||||
* Change method from ssh-rsa to rsa-sha2-256 is RSA SHA2 is supported.
|
||||
*/
|
||||
static void upgrade_publickey_method(LIBSSH2_SESSION * session,
|
||||
unsigned char **method,
|
||||
size_t *method_len) {
|
||||
#if LIBSSH2_RSA_SHA2
|
||||
if(*method_len == 7 && memcmp(*method, "ssh-rsa", 7) == 0) {
|
||||
LIBSSH2_FREE(session, *method);
|
||||
*method_len = 12;
|
||||
*method = LIBSSH2_ALLOC(session, 12);
|
||||
memcpy(*method, "rsa-sha2-256", 12);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
static int
|
||||
memory_read_publickey(LIBSSH2_SESSION * session, unsigned char **method,
|
||||
size_t *method_len,
|
||||
@@ -615,6 +633,9 @@ memory_read_publickey(LIBSSH2_SESSION * session, unsigned char **method,
|
||||
*method = pubkey;
|
||||
*method_len = sp1 - pubkey - 1;
|
||||
|
||||
/* upgrade to sha2 for rsa keys when supported */
|
||||
upgrade_publickey_method(session, method, method_len);
|
||||
|
||||
*pubkeydata = tmp;
|
||||
*pubkeydata_len = tmp_len;
|
||||
|
||||
@@ -717,6 +738,9 @@ file_read_publickey(LIBSSH2_SESSION * session, unsigned char **method,
|
||||
* it a wash */
|
||||
*method = pubkey;
|
||||
*method_len = sp1 - pubkey - 1;
|
||||
|
||||
/* upgrade to sha2 for rsa keys when supported */
|
||||
upgrade_publickey_method(session, method, method_len);
|
||||
|
||||
*pubkeydata = tmp;
|
||||
*pubkeydata_len = tmp_len;
|
||||
@@ -1219,10 +1243,19 @@ _libssh2_userauth_publickey(LIBSSH2_SESSION *session,
|
||||
* TODO: The data should match too but we don't check that. Should we?
|
||||
*/
|
||||
else if(session->userauth_pblc_method_len !=
|
||||
_libssh2_ntohu32(pubkeydata))
|
||||
return _libssh2_error(session, LIBSSH2_ERROR_PUBLICKEY_UNVERIFIED,
|
||||
"Invalid public key");
|
||||
_libssh2_ntohu32(pubkeydata)) {
|
||||
|
||||
// we accept mismatch if public key is "ssh-rsa" and
|
||||
// method has prefix "rsa-sha2-" to satisfy RFC 8332
|
||||
if(session->userauth_pblc_method_len < 9 ||
|
||||
_libssh2_ntohu32(pubkeydata) != 7 ||
|
||||
memcmp(pubkeydata + 4, "ssh-rsa", 7) ||
|
||||
memcmp(session->userauth_pblc_method, "rsa-sha2-", 9)) {
|
||||
|
||||
return _libssh2_error(session, LIBSSH2_ERROR_PUBLICKEY_UNVERIFIED,
|
||||
"Invalid public key");
|
||||
}
|
||||
}
|
||||
/*
|
||||
* 45 = packet_type(1) + username_len(4) + servicename_len(4) +
|
||||
* service_name(14)"ssh-connection" + authmethod_len(4) +
|
||||
|
@@ -63,6 +63,7 @@
|
||||
#define LIBSSH2_3DES 1
|
||||
|
||||
#define LIBSSH2_RSA 1
|
||||
#define LIBSSH2_RSA_SHA2 0
|
||||
#define LIBSSH2_DSA 1
|
||||
#define LIBSSH2_ECDSA 0
|
||||
#define LIBSSH2_ED25519 0
|
||||
|
Reference in New Issue
Block a user