mirror of
https://github.com/libssh2/libssh2.git
synced 2026-10-24 03:48:58 +03:00
src: disable SHA1-based hostkey methods and signatures by default, fix fallouts
They are `ssh-rsa` and `ssh-rsa-cert-v01@openssh.com`, and insecure due to their reliance on SHA1 hashes. Also: - hostkey: fix to accept all RSA hostkey methods in common `hostkey_method_ssh_rsa_init()`. - mbedtls: add missing RSA SHA1/SHA2 guards. - mbedtls: cleanup on error in `mbed_pub_priv_key()`. - os400qc3: add missing RSA SHA1/SHA2 guards. (untested) - wincng: add missing RSA SHA1/SHA2 guards. - crypto.h: add missing `#endif` comments. - GHA: move stray `-DLIBSSH2_DSA_ENABLE` to its place. Follow-up tob7ab0faa70#1435 - tests: fix to guard RSA tests with `LIBSSH2_RSA`, replacing `LIBSSH2_RSA_SHA1` to keep test coverage. Keep using the latter for testing SHA1-based signatures in `test_auth_pubkey_ok_rsa_signed`. Follow-up to3e14d67d26#2444 Follow-up to99f935358d#2443 Closes #2501
This commit is contained in:
6
.github/workflows/ci.yml
vendored
6
.github/workflows/ci.yml
vendored
@@ -506,7 +506,7 @@ jobs:
|
||||
cflags=''
|
||||
if [[ ( "${MATRIX_CRYPTO}" = 'Libgcrypt' && "${MATRIX_ZLIB}" = 'OFF' ) || "${MATRIX_TEST}" = 'legacy-options' ]]; then
|
||||
cflags+=' -DLIBSSH2_KEX_SHA1_ENABLE -DLIBSSH2_MD5_ENABLE -DLIBSSH2_MD5_PEM_ENABLE -DLIBSSH2_HMAC_SHA1_ENABLE -DLIBSSH2_HMAC_RIPEMD_ENABLE'
|
||||
cflags+=' -DLIBSSH2_BLOWFISH_ENABLE -DLIBSSH2_RC4_ENABLE -DLIBSSH2_CAST_ENABLE -DLIBSSH2_3DES_ENABLE'
|
||||
cflags+=' -DLIBSSH2_RSA_SHA1_ENABLE -DLIBSSH2_BLOWFISH_ENABLE -DLIBSSH2_RC4_ENABLE -DLIBSSH2_CAST_ENABLE -DLIBSSH2_3DES_ENABLE'
|
||||
fi
|
||||
if [ "${MATRIX_TARGET}" = 'distcheck' ]; then
|
||||
cflags+=' -DLIBSSH2_DSA_ENABLE' # build test only, it cannot pass test in CI
|
||||
@@ -874,7 +874,8 @@ jobs:
|
||||
cflags=''
|
||||
if [ "${MATRIX_TEST}" = 'legacy-options' ]; then
|
||||
cflags+=' -DLIBSSH2_KEX_SHA1_ENABLE -DLIBSSH2_MD5_ENABLE -DLIBSSH2_MD5_PEM_ENABLE -DLIBSSH2_HMAC_SHA1_ENABLE -DLIBSSH2_HMAC_RIPEMD_ENABLE'
|
||||
cflags+=' -DLIBSSH2_BLOWFISH_ENABLE -DLIBSSH2_RC4_ENABLE -DLIBSSH2_CAST_ENABLE -DLIBSSH2_3DES_ENABLE'
|
||||
cflags+=' -DLIBSSH2_RSA_SHA1_ENABLE -DLIBSSH2_BLOWFISH_ENABLE -DLIBSSH2_RC4_ENABLE -DLIBSSH2_CAST_ENABLE -DLIBSSH2_3DES_ENABLE'
|
||||
cflags+=' -DLIBSSH2_DSA_ENABLE'
|
||||
fi
|
||||
if [ "${MATRIX_BUILD}" = 'CM' ]; then
|
||||
if [[ "${MATRIX_ENV}" = 'clang'* ]]; then
|
||||
@@ -893,7 +894,6 @@ jobs:
|
||||
fi
|
||||
elif [ "${MATRIX_TEST}" = 'no-options' ]; then
|
||||
options+=' -DLIBSSH2_NO_DEPRECATED=ON'
|
||||
cflags+=' -DLIBSSH2_DSA_ENABLE'
|
||||
cflags+=' -DLIBSSH2_NO_AES_CBC -DLIBSSH2_NO_AES_CTR'
|
||||
fi
|
||||
if [[ "${MATRIX_TEST}" = *'unicode'* ]]; then
|
||||
|
||||
@@ -4,6 +4,10 @@ Deprecation notices:
|
||||
|
||||
- This release disables these options by default:
|
||||
|
||||
- SHA1-based hostkey methods and signatures: `ssh-rsa`,
|
||||
`ssh-rsa-cert-v01@openssh.com`
|
||||
You can enable them with `-DLIBSSH2_RSA_SHA1_ENABLE`.
|
||||
|
||||
- SHA1-based key-exchange methods:
|
||||
- `diffie-hellman-group1-sha1`
|
||||
- `diffie-hellman-group14-sha1`
|
||||
|
||||
@@ -157,7 +157,7 @@ int ssh2_rsa_sha2_verify(ssh2_rsa_ctx *rsa, size_t hash_len,
|
||||
#ifndef ssh2_rsa_free
|
||||
void ssh2_rsa_free(ssh2_rsa_ctx *rsa);
|
||||
#endif
|
||||
#endif
|
||||
#endif /* LIBSSH2_RSA */
|
||||
|
||||
#if LIBSSH2_DSA
|
||||
int ssh2_dsa_new(ssh2_dsa_ctx **dsa,
|
||||
@@ -180,7 +180,7 @@ int ssh2_dsa_sha1_verify(ssh2_dsa_ctx *dsa,
|
||||
#ifndef ssh2_dsa_free
|
||||
void ssh2_dsa_free(ssh2_dsa_ctx *dsa);
|
||||
#endif
|
||||
#endif
|
||||
#endif /* LIBSSH2_DSA */
|
||||
|
||||
#if LIBSSH2_ECDSA
|
||||
/* Maximum uncompressed EC point length for NIST P-521:
|
||||
|
||||
@@ -30,7 +30,7 @@
|
||||
#define LIBSSH2_RSA 0
|
||||
#endif
|
||||
|
||||
#ifdef LIBSSH2_NO_RSA_SHA1
|
||||
#ifndef LIBSSH2_RSA_SHA1_ENABLE
|
||||
#undef LIBSSH2_RSA_SHA1
|
||||
#define LIBSSH2_RSA_SHA1 0
|
||||
#endif
|
||||
|
||||
@@ -86,23 +86,10 @@ static int hostkey_method_ssh_rsa_init(LIBSSH2_SESSION *session,
|
||||
return -1;
|
||||
|
||||
/* we accept one of 3 header types */
|
||||
#if LIBSSH2_RSA_SHA1
|
||||
if(SSH2_IS_LITERAL(type, type_len, "ssh-rsa")) {
|
||||
/* ssh-rsa */
|
||||
}
|
||||
else
|
||||
#endif
|
||||
#if LIBSSH2_RSA_SHA2
|
||||
if(SSH2_IS_LITERAL(type, type_len, "rsa-sha2-256")) {
|
||||
/* rsa-sha2-256 */
|
||||
}
|
||||
else if(SSH2_IS_LITERAL(type, type_len, "rsa-sha2-512")) {
|
||||
/* rsa-sha2-512 */
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
ssh2_deb((session, LIBSSH2_TRACE_ERROR, "unexpected rsa type: %.*s",
|
||||
if(!SSH2_IS_LITERAL(type, type_len, "ssh-rsa") &&
|
||||
!SSH2_IS_LITERAL(type, type_len, "rsa-sha2-256") &&
|
||||
!SSH2_IS_LITERAL(type, type_len, "rsa-sha2-512")) {
|
||||
ssh2_deb((session, LIBSSH2_TRACE_ERROR, "unexpected RSA type: %.*s",
|
||||
(int)type_len, type));
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -297,6 +297,7 @@ static int mbed_bn_random(ssh2_bn *bn, int bits, int top, int bottom)
|
||||
* mbedTLS backend: RSA functions
|
||||
*/
|
||||
|
||||
#if LIBSSH2_RSA
|
||||
int ssh2_rsa_new(ssh2_rsa_ctx **rsa,
|
||||
const unsigned char *edata, size_t elen,
|
||||
const unsigned char *ndata, size_t nlen,
|
||||
@@ -416,6 +417,7 @@ int ssh2_rsa_new_priv(ssh2_rsa_ctx **rsa,
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if LIBSSH2_RSA_SHA2
|
||||
int ssh2_rsa_sha2_verify(ssh2_rsa_ctx *rsa, size_t hash_len,
|
||||
const unsigned char *sig, size_t sig_len,
|
||||
const unsigned char *m, size_t m_len)
|
||||
@@ -465,14 +467,6 @@ int ssh2_rsa_sha2_verify(ssh2_rsa_ctx *rsa, size_t hash_len,
|
||||
return ret == 0 ? 0 : -1;
|
||||
}
|
||||
|
||||
int ssh2_rsa_sha1_verify(ssh2_rsa_ctx *rsa,
|
||||
const unsigned char *sig, size_t sig_len,
|
||||
const unsigned char *m, size_t m_len)
|
||||
{
|
||||
return ssh2_rsa_sha2_verify(rsa, SSH2_SHA1_DIG_LEN,
|
||||
sig, sig_len, m, m_len);
|
||||
}
|
||||
|
||||
int ssh2_rsa_sha2_sign(ssh2_rsa_ctx *rsa, LIBSSH2_SESSION *session,
|
||||
const unsigned char *hash, size_t hash_len,
|
||||
unsigned char **signature, size_t *signature_len)
|
||||
@@ -515,6 +509,16 @@ int ssh2_rsa_sha2_sign(ssh2_rsa_ctx *rsa, LIBSSH2_SESSION *session,
|
||||
|
||||
return ret == 0 ? 0 : -1;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if LIBSSH2_RSA_SHA1
|
||||
int ssh2_rsa_sha1_verify(ssh2_rsa_ctx *rsa,
|
||||
const unsigned char *sig, size_t sig_len,
|
||||
const unsigned char *m, size_t m_len)
|
||||
{
|
||||
return ssh2_rsa_sha2_verify(rsa, SSH2_SHA1_DIG_LEN,
|
||||
sig, sig_len, m, m_len);
|
||||
}
|
||||
|
||||
int ssh2_rsa_sha1_sign(ssh2_rsa_ctx *rsa, LIBSSH2_SESSION *session,
|
||||
const unsigned char *hash, size_t hash_len,
|
||||
@@ -523,6 +527,7 @@ int ssh2_rsa_sha1_sign(ssh2_rsa_ctx *rsa, LIBSSH2_SESSION *session,
|
||||
return ssh2_rsa_sha2_sign(rsa, session, hash, hash_len,
|
||||
signature, signature_len);
|
||||
}
|
||||
#endif
|
||||
|
||||
void ssh2_rsa_free(ssh2_rsa_ctx *rsa)
|
||||
{
|
||||
@@ -571,6 +576,7 @@ static unsigned char *mbed_gen_publickey_from_rsa(LIBSSH2_SESSION *session,
|
||||
*keylen = (size_t)(p - key);
|
||||
return key;
|
||||
}
|
||||
#endif /* LIBSSH2_RSA */
|
||||
|
||||
static int mbed_pub_priv_key(LIBSSH2_SESSION *session, char **method,
|
||||
unsigned char **pubkeydata,
|
||||
@@ -580,26 +586,28 @@ static int mbed_pub_priv_key(LIBSSH2_SESSION *session, char **method,
|
||||
char *method_buf = NULL;
|
||||
unsigned char *key = NULL;
|
||||
size_t keylen = 0, method_buf_len = 0;
|
||||
int ret;
|
||||
mbedtls_rsa_context *rsa;
|
||||
int ret = 0;
|
||||
|
||||
if(mbedtls_pk_get_type(pkey) != MBEDTLS_PK_RSA)
|
||||
return ssh2_err(session, LIBSSH2_ERROR_FILE, "Key type not supported");
|
||||
#if LIBSSH2_RSA
|
||||
if(mbedtls_pk_get_type(pkey) == MBEDTLS_PK_RSA) {
|
||||
mbedtls_rsa_context *rsa;
|
||||
|
||||
ret = 0;
|
||||
/* write method */
|
||||
method_buf_len = sizeof("ssh-rsa") - 1;
|
||||
method_buf = SSH2_ALLOC(session, method_buf_len + 1);
|
||||
if(method_buf)
|
||||
memcpy(method_buf, "ssh-rsa", method_buf_len + 1);
|
||||
else
|
||||
ret = -1;
|
||||
|
||||
/* write method */
|
||||
method_buf_len = sizeof("ssh-rsa") - 1;
|
||||
method_buf = SSH2_ALLOC(session, method_buf_len + 1);
|
||||
if(method_buf)
|
||||
memcpy(method_buf, "ssh-rsa", method_buf_len + 1);
|
||||
rsa = mbedtls_pk_rsa(*pkey);
|
||||
key = mbed_gen_publickey_from_rsa(session, rsa, &keylen);
|
||||
if(!key)
|
||||
ret = -1;
|
||||
}
|
||||
else
|
||||
ret = -1;
|
||||
|
||||
rsa = mbedtls_pk_rsa(*pkey);
|
||||
key = mbed_gen_publickey_from_rsa(session, rsa, &keylen);
|
||||
if(!key)
|
||||
ret = -1;
|
||||
#endif
|
||||
ret = ssh2_err(session, LIBSSH2_ERROR_FILE, "Key type not supported");
|
||||
|
||||
/* write output */
|
||||
if(ret) {
|
||||
|
||||
@@ -94,7 +94,7 @@ static int sshrsapubkey(LIBSSH2_SESSION *session, char **sshpubkey,
|
||||
struct asn1Element *params, struct asn1Element *key,
|
||||
const char *method);
|
||||
|
||||
#if LIBSSH2_DSA != 0
|
||||
#if LIBSSH2_DSA
|
||||
/* dsaEncryption OID: 1.2.840.10040.4.1 */
|
||||
static unsigned char OID_dsaEncryption[] = {
|
||||
7, 40 + 2, 0x86, 0x48, 0xCE, 0x38, 4, 1
|
||||
@@ -294,10 +294,10 @@ static struct {
|
||||
struct asn1Element *key, const char *method);
|
||||
const char *method;
|
||||
} pka[] = {
|
||||
#if LIBSSH2_RSA != 0
|
||||
#if LIBSSH2_RSA
|
||||
{ OID_rsaEncryption, sshrsapubkey, "ssh-rsa" },
|
||||
#endif
|
||||
#if LIBSSH2_DSA != 0
|
||||
#if LIBSSH2_DSA
|
||||
{ OID_dsaEncryption, sshdsapubkey, "ssh-dss" },
|
||||
#endif
|
||||
{ NULL, NULL, NULL }
|
||||
@@ -1159,6 +1159,7 @@ int ssh2_cipher_crypt(ssh2_cipher_ctx *ctx, SSH2_CIPHER_T(algo),
|
||||
*
|
||||
*******************************************************************/
|
||||
|
||||
#if LIBSSH2_RSA
|
||||
int ssh2_rsa_new(ssh2_rsa_ctx **rsa,
|
||||
const unsigned char *edata, size_t elen,
|
||||
const unsigned char *ndata, size_t nlen,
|
||||
@@ -1255,6 +1256,7 @@ int ssh2_rsa_new(ssh2_rsa_ctx **rsa,
|
||||
*rsa = ctx;
|
||||
return ret;
|
||||
}
|
||||
#endif /* LIBSSH2_RSA */
|
||||
|
||||
/*******************************************************************
|
||||
*
|
||||
@@ -2288,6 +2290,7 @@ int ssh2_pub_privkey(LIBSSH2_SESSION *session, char **method,
|
||||
passphrase);
|
||||
}
|
||||
|
||||
#if LIBSSH2_RSA
|
||||
static int os400_rsa_new_priv_from_file(ssh2_rsa_ctx **rsa,
|
||||
LIBSSH2_SESSION *session,
|
||||
const char *filename,
|
||||
@@ -2394,6 +2397,7 @@ int ssh2_rsa_new_priv(ssh2_rsa_ctx **rsa,
|
||||
blob, blob_len, passphrase);
|
||||
}
|
||||
|
||||
#if LIBSSH2_RSA_SHA2
|
||||
int ssh2_rsa_sha2_verify(ssh2_rsa_ctx *rsa, size_t hash_len,
|
||||
const unsigned char *sig, size_t sig_len,
|
||||
const unsigned char *m, size_t m_len)
|
||||
@@ -2427,7 +2431,8 @@ int ssh2_rsa_sha2_verify(ssh2_rsa_ctx *rsa, size_t hash_len,
|
||||
NULL, (char *)&errcode);
|
||||
return errcode.Bytes_Available ? -1 : 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
#if LIBSSH2_RSA_SHA1
|
||||
int ssh2_rsa_sha1_verify(ssh2_rsa_ctx *rsa,
|
||||
const unsigned char *sig, size_t sig_len,
|
||||
const unsigned char *m, size_t m_len)
|
||||
@@ -2435,6 +2440,7 @@ int ssh2_rsa_sha1_verify(ssh2_rsa_ctx *rsa,
|
||||
return ssh2_rsa_sha2_verify(rsa, SSH2_SHA1_DIG_LEN,
|
||||
sig, sig_len, m, m_len);
|
||||
}
|
||||
#endif
|
||||
|
||||
int ssh2_os400qc3_rsa_signv(ssh2_rsa_ctx *rsa, LIBSSH2_SESSION *session,
|
||||
int algo,
|
||||
@@ -2468,6 +2474,7 @@ int ssh2_os400qc3_rsa_signv(ssh2_rsa_ctx *rsa, LIBSSH2_SESSION *session,
|
||||
*signature_len = siglen;
|
||||
return 0;
|
||||
}
|
||||
#endif /* LIBSSH2_RSA */
|
||||
|
||||
#endif /* LIBSSH2_OS400QC3 */
|
||||
|
||||
|
||||
@@ -258,22 +258,28 @@ struct os400qc3_dh_ctx { /* Diffie-Hellman context. */
|
||||
|
||||
#define ssh2_cipher_dtor(ctx) ssh2_os400qc3_crypto_dtor(ctx)
|
||||
|
||||
#if LIBSSH2_RSA
|
||||
#define ssh2_rsa_ctx struct os400qc3_crypto_ctx
|
||||
#define ssh2_rsa_free(rsa) \
|
||||
(ssh2_os400qc3_crypto_dtor(rsa), free((char *)rsa))
|
||||
#define ssh2_prepare_iovec(vec, len) \
|
||||
memset((char *)(vec), 0, (len) * sizeof(struct iovec))
|
||||
#if LIBSSH2_RSA_SHA1
|
||||
#define ssh2_rsa_sha1_signv(rsa, session, sig, siglen, count, vector) \
|
||||
ssh2_os400qc3_rsa_signv(rsa, session, Qc3_SHA1, sig, siglen, count, vector)
|
||||
#endif
|
||||
#if LIBSSH2_RSA_SHA2
|
||||
#define ssh2_rsa_sha2_256_signv(rsa, session, sig, siglen, cnt, vector) \
|
||||
ssh2_os400qc3_rsa_signv(rsa, session, Qc3_SHA256, sig, siglen, cnt, vector)
|
||||
#define ssh2_rsa_sha2_512_signv(rsa, session, sig, siglen, cnt, vector) \
|
||||
ssh2_os400qc3_rsa_signv(rsa, session, Qc3_SHA512, sig, siglen, cnt, vector)
|
||||
#endif
|
||||
|
||||
int ssh2_os400qc3_rsa_signv(ssh2_rsa_ctx *rsa, LIBSSH2_SESSION *session,
|
||||
int algo,
|
||||
unsigned char **signature, size_t *signature_len,
|
||||
int veccount, const struct iovec vector[]);
|
||||
#endif /* LIBSSH2_RSA */
|
||||
|
||||
#define ssh2_dh_ctx struct os400qc3_dh_ctx
|
||||
|
||||
|
||||
@@ -1307,7 +1307,6 @@ int ssh2_rsa_sha1_verify(ssh2_rsa_ctx *rsa,
|
||||
BCRYPT_PAD_PKCS1);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if LIBSSH2_RSA_SHA2
|
||||
int ssh2_rsa_sha2_verify(ssh2_rsa_ctx *rsa, size_t hash_len,
|
||||
const unsigned char *sig, size_t sig_len,
|
||||
@@ -1375,6 +1374,7 @@ static int wcng_rsa_sha_sign(ssh2_rsa_ctx *rsa, LIBSSH2_SESSION *session,
|
||||
return BCRYPT_SUCCESS(ret) ? 0 : -1;
|
||||
}
|
||||
|
||||
#if LIBSSH2_RSA_SHA1
|
||||
int ssh2_rsa_sha1_sign(ssh2_rsa_ctx *rsa, LIBSSH2_SESSION *session,
|
||||
const unsigned char *hash, size_t hash_len,
|
||||
unsigned char **signature, size_t *signature_len)
|
||||
@@ -1382,7 +1382,8 @@ int ssh2_rsa_sha1_sign(ssh2_rsa_ctx *rsa, LIBSSH2_SESSION *session,
|
||||
return wcng_rsa_sha_sign(rsa, session,
|
||||
hash, hash_len, signature, signature_len);
|
||||
}
|
||||
|
||||
#endif
|
||||
#if LIBSSH2_RSA_SHA2
|
||||
int ssh2_rsa_sha2_sign(ssh2_rsa_ctx *rsa, LIBSSH2_SESSION *session,
|
||||
const unsigned char *hash, size_t hash_len,
|
||||
unsigned char **signature, size_t *signature_len)
|
||||
@@ -1390,6 +1391,7 @@ int ssh2_rsa_sha2_sign(ssh2_rsa_ctx *rsa, LIBSSH2_SESSION *session,
|
||||
return wcng_rsa_sha_sign(rsa, session,
|
||||
hash, hash_len, signature, signature_len);
|
||||
}
|
||||
#endif
|
||||
|
||||
void ssh2_rsa_free(ssh2_rsa_ctx *rsa)
|
||||
{
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
|
||||
int test(LIBSSH2_SESSION *session)
|
||||
{
|
||||
#if LIBSSH2_RSA_SHA1
|
||||
#if LIBSSH2_RSA
|
||||
/* set in Dockerfile */
|
||||
return test_auth_pubkey(session, 0,
|
||||
"libssh2",
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
|
||||
int test(LIBSSH2_SESSION *session)
|
||||
{
|
||||
#if LIBSSH2_RSA_SHA1 && LIBSSH2_AES_GCM && \
|
||||
#if LIBSSH2_RSA && LIBSSH2_AES_GCM && \
|
||||
(defined(LIBSSH2_OPENSSL) || defined(LIBSSH2_WOLFSSL))
|
||||
/* set in Dockerfile */
|
||||
return test_auth_pubkey(session, 0,
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
|
||||
int test(LIBSSH2_SESSION *session)
|
||||
{
|
||||
#if LIBSSH2_RSA_SHA1 && LIBSSH2_MD5_PEM && LIBSSH2_AES_CBC
|
||||
#if LIBSSH2_RSA && LIBSSH2_MD5_PEM && LIBSSH2_AES_CBC
|
||||
/* set in Dockerfile */
|
||||
return test_auth_pubkey(session, 0,
|
||||
"libssh2",
|
||||
|
||||
@@ -7,8 +7,7 @@
|
||||
|
||||
int test(LIBSSH2_SESSION *session)
|
||||
{
|
||||
#if LIBSSH2_RSA_SHA1 && \
|
||||
(defined(LIBSSH2_OPENSSL) || defined(LIBSSH2_WOLFSSL))
|
||||
#if LIBSSH2_RSA && (defined(LIBSSH2_OPENSSL) || defined(LIBSSH2_WOLFSSL))
|
||||
/* set in Dockerfile */
|
||||
return test_auth_pubkey(session, 0,
|
||||
"libssh2",
|
||||
|
||||
Reference in New Issue
Block a user