diff --git a/.gitignore b/.gitignore index 7d6bdbf60..37c55e1b0 100644 --- a/.gitignore +++ b/.gitignore @@ -22,3 +22,4 @@ project.lock.json # Build outputs build/target/ +/.vs diff --git a/src/Renci.SshNet/Abstractions/CryptoAbstraction.cs b/src/Renci.SshNet/Abstractions/CryptoAbstraction.cs index ff9e50a52..1eb3ff78e 100644 --- a/src/Renci.SshNet/Abstractions/CryptoAbstraction.cs +++ b/src/Renci.SshNet/Abstractions/CryptoAbstraction.cs @@ -56,9 +56,12 @@ public static System.Security.Cryptography.RandomNumberGenerator CreateRandomNum #endif // FEATURE_RNG_CREATE || FEATURE_RNG_CSP #if FEATURE_HASH_MD5 - public static System.Security.Cryptography.MD5 CreateMD5() + public static System.Security.Cryptography.HashAlgorithm CreateMD5() { - return System.Security.Cryptography.MD5.Create(); + if (SftpClient.UseFIPS) + return new System.Security.Cryptography.SHA1CryptoServiceProvider(); + else + return System.Security.Cryptography.MD5.Create(); } #else public static global::SshNet.Security.Cryptography.MD5 CreateMD5() @@ -70,11 +73,18 @@ public static System.Security.Cryptography.MD5 CreateMD5() #if FEATURE_HASH_SHA1_CREATE || FEATURE_HASH_SHA1_MANAGED public static System.Security.Cryptography.SHA1 CreateSHA1() { + if (SftpClient.UseFIPS) + { + return new System.Security.Cryptography.SHA1CryptoServiceProvider(); + } + else + { #if FEATURE_HASH_SHA1_CREATE - return System.Security.Cryptography.SHA1.Create(); + return System.Security.Cryptography.SHA1.Create(); #elif FEATURE_HASH_SHA1_MANAGED return new System.Security.Cryptography.SHA1Managed(); #endif + } } #else public static global::SshNet.Security.Cryptography.SHA1 CreateSHA1() @@ -86,11 +96,18 @@ public static System.Security.Cryptography.SHA1 CreateSHA1() #if FEATURE_HASH_SHA256_CREATE || FEATURE_HASH_SHA256_MANAGED public static System.Security.Cryptography.SHA256 CreateSHA256() { + if (SftpClient.UseFIPS) + { + return new System.Security.Cryptography.SHA256CryptoServiceProvider(); + } + else + { #if FEATURE_HASH_SHA256_CREATE - return System.Security.Cryptography.SHA256.Create(); + return System.Security.Cryptography.SHA256.Create(); #elif FEATURE_HASH_SHA256_MANAGED return new System.Security.Cryptography.SHA256Managed(); #endif + } } #else public static global::SshNet.Security.Cryptography.SHA256 CreateSHA256() @@ -102,11 +119,18 @@ public static System.Security.Cryptography.SHA256 CreateSHA256() #if FEATURE_HASH_SHA384_CREATE || FEATURE_HASH_SHA384_MANAGED public static System.Security.Cryptography.SHA384 CreateSHA384() { + if (SftpClient.UseFIPS) + { + return new System.Security.Cryptography.SHA384CryptoServiceProvider(); + } + else + { #if FEATURE_HASH_SHA384_CREATE - return System.Security.Cryptography.SHA384.Create(); + return System.Security.Cryptography.SHA384.Create(); #elif FEATURE_HASH_SHA384_MANAGED return new System.Security.Cryptography.SHA384Managed(); #endif + } } #else public static global::SshNet.Security.Cryptography.SHA384 CreateSHA384() @@ -118,11 +142,18 @@ public static System.Security.Cryptography.SHA384 CreateSHA384() #if FEATURE_HASH_SHA512_CREATE || FEATURE_HASH_SHA512_MANAGED public static System.Security.Cryptography.SHA512 CreateSHA512() { + if (SftpClient.UseFIPS) + { + return new System.Security.Cryptography.SHA512CryptoServiceProvider(); + } + else + { #if FEATURE_HASH_SHA512_CREATE - return System.Security.Cryptography.SHA512.Create(); + return System.Security.Cryptography.SHA512.Create(); #elif FEATURE_HASH_SHA512_MANAGED return new System.Security.Cryptography.SHA512Managed(); #endif + } } #else public static global::SshNet.Security.Cryptography.SHA512 CreateSHA512() diff --git a/src/Renci.SshNet/BaseClient.cs b/src/Renci.SshNet/BaseClient.cs index 5b0e01c90..e4f188cd2 100644 --- a/src/Renci.SshNet/BaseClient.cs +++ b/src/Renci.SshNet/BaseClient.cs @@ -17,6 +17,9 @@ public abstract class BaseClient : IDisposable /// private readonly bool _ownsConnectionInfo; + + + private static bool _useFips = false; private readonly IServiceFactory _serviceFactory; private readonly object _keepAliveLock = new object(); private TimeSpan _keepAliveInterval; @@ -31,6 +34,11 @@ public abstract class BaseClient : IDisposable /// internal ISession Session { get; private set; } + /// + /// Requests FIPS Compliance on the SFTP client + /// + public static bool UseFIPS { get { return _useFips; } set { _useFips = value; } } + /// /// Gets the factory for creating new services. /// @@ -74,7 +82,6 @@ public bool IsConnected get { CheckDisposed(); - return IsSessionConnected(); } } diff --git a/src/Renci.SshNet/ConnectionInfo.cs b/src/Renci.SshNet/ConnectionInfo.cs index af8e1ca5c..6620394a7 100644 --- a/src/Renci.SshNet/ConnectionInfo.cs +++ b/src/Renci.SshNet/ConnectionInfo.cs @@ -323,7 +323,9 @@ public ConnectionInfo(string host, int port, string username, ProxyTypes proxyTy MaxSessions = 10; Encoding = Encoding.UTF8; - KeyExchangeAlgorithms = new Dictionary + if (SftpClient.UseFIPS) + { + KeyExchangeAlgorithms = new Dictionary { {"curve25519-sha256", typeof(KeyExchangeECCurve25519)}, {"curve25519-sha256@libssh.org", typeof(KeyExchangeECCurve25519)}, @@ -338,7 +340,68 @@ public ConnectionInfo(string host, int port, string username, ProxyTypes proxyTy {"diffie-hellman-group1-sha1", typeof (KeyExchangeDiffieHellmanGroup1Sha1)}, }; - Encryptions = new Dictionary + Encryptions = new Dictionary + { + {"aes256-ctr", new CipherInfo(256, (key, iv) => new AesCipher(key, new CtrCipherMode(iv), null))}, + {"3des-cbc", new CipherInfo(192, (key, iv) => new TripleDesCipher(key, new CbcCipherMode(iv), null))}, + {"aes128-cbc", new CipherInfo(128, (key, iv) => new AesCipher(key, new CbcCipherMode(iv), null))}, + {"aes192-cbc", new CipherInfo(192, (key, iv) => new AesCipher(key, new CbcCipherMode(iv), null))}, + {"aes256-cbc", new CipherInfo(256, (key, iv) => new AesCipher(key, new CbcCipherMode(iv), null))}, + {"blowfish-cbc", new CipherInfo(128, (key, iv) => new BlowfishCipher(key, new CbcCipherMode(iv), null))}, + {"twofish-cbc", new CipherInfo(256, (key, iv) => new TwofishCipher(key, new CbcCipherMode(iv), null))}, + {"twofish192-cbc", new CipherInfo(192, (key, iv) => new TwofishCipher(key, new CbcCipherMode(iv), null))}, + {"twofish128-cbc", new CipherInfo(128, (key, iv) => new TwofishCipher(key, new CbcCipherMode(iv), null))}, + {"twofish256-cbc", new CipherInfo(256, (key, iv) => new TwofishCipher(key, new CbcCipherMode(iv), null))}, + {"arcfour", new CipherInfo(128, (key, iv) => new Arc4Cipher(key, false))}, + {"arcfour128", new CipherInfo(128, (key, iv) => new Arc4Cipher(key, true))}, + {"arcfour256", new CipherInfo(256, (key, iv) => new Arc4Cipher(key, true))}, + {"cast128-cbc", new CipherInfo(128, (key, iv) => new CastCipher(key, new CbcCipherMode(iv), null))}, + {"aes128-ctr", new CipherInfo(128, (key, iv) => new AesCipher(key, new CtrCipherMode(iv), null))}, + {"aes192-ctr", new CipherInfo(192, (key, iv) => new AesCipher(key, new CtrCipherMode(iv), null))}, + }; + + HmacAlgorithms = new Dictionary + { + {"hmac-sha1", new HashInfo(20*8, CryptoAbstraction.CreateHMACSHA1)}, + {"hmac-sha1-96", new HashInfo(20*8, key => CryptoAbstraction.CreateHMACSHA1(key, 96))}, + {"hmac-sha2-256", new HashInfo(32*8, CryptoAbstraction.CreateHMACSHA256)}, + {"hmac-sha2-256-96", new HashInfo(32*8, key => CryptoAbstraction.CreateHMACSHA256(key, 96))}, + {"hmac-sha2-512", new HashInfo(64 * 8, CryptoAbstraction.CreateHMACSHA512)}, + {"hmac-sha2-512-96", new HashInfo(64 * 8, key => CryptoAbstraction.CreateHMACSHA512(key, 96))}, + {"hmac-ripemd160", new HashInfo(160, CryptoAbstraction.CreateHMACRIPEMD160)}, + {"hmac-ripemd160@openssh.com", new HashInfo(160, CryptoAbstraction.CreateHMACRIPEMD160)}, + }; + + HostKeyAlgorithms = new Dictionary> + { + {"ssh-ed25519", data => new KeyHostAlgorithm("ssh-ed25519", new ED25519Key(), data)}, +#if FEATURE_ECDSA + {"ecdsa-sha2-nistp256", data => new KeyHostAlgorithm("ecdsa-sha2-nistp256", new EcdsaKey(), data)}, + {"ecdsa-sha2-nistp384", data => new KeyHostAlgorithm("ecdsa-sha2-nistp384", new EcdsaKey(), data)}, + {"ecdsa-sha2-nistp521", data => new KeyHostAlgorithm("ecdsa-sha2-nistp521", new EcdsaKey(), data)}, +#endif + {"ssh-rsa", data => new KeyHostAlgorithm("ssh-rsa", new RsaKey(), data)}, + {"ssh-dss", data => new KeyHostAlgorithm("ssh-dss", new DsaKey(), data)}, + }; + } + else + { + KeyExchangeAlgorithms = new Dictionary + { + {"curve25519-sha256", typeof(KeyExchangeECCurve25519)}, + {"curve25519-sha256@libssh.org", typeof(KeyExchangeECCurve25519)}, + {"ecdh-sha2-nistp256", typeof(KeyExchangeECDH256)}, + {"ecdh-sha2-nistp384", typeof(KeyExchangeECDH384)}, + {"ecdh-sha2-nistp521", typeof(KeyExchangeECDH521)}, + {"diffie-hellman-group-exchange-sha256", typeof (KeyExchangeDiffieHellmanGroupExchangeSha256)}, + {"diffie-hellman-group-exchange-sha1", typeof (KeyExchangeDiffieHellmanGroupExchangeSha1)}, + {"diffie-hellman-group16-sha512", typeof(KeyExchangeDiffieHellmanGroup16Sha512)}, + {"diffie-hellman-group14-sha256", typeof (KeyExchangeDiffieHellmanGroup14Sha256)}, + {"diffie-hellman-group14-sha1", typeof (KeyExchangeDiffieHellmanGroup14Sha1)}, + {"diffie-hellman-group1-sha1", typeof (KeyExchangeDiffieHellmanGroup1Sha1)}, + }; + + Encryptions = new Dictionary { {"aes256-ctr", new CipherInfo(256, (key, iv) => new AesCipher(key, new CtrCipherMode(iv), null))}, {"3des-cbc", new CipherInfo(192, (key, iv) => new TripleDesCipher(key, new CbcCipherMode(iv), null))}, @@ -363,7 +426,7 @@ public ConnectionInfo(string host, int port, string username, ProxyTypes proxyTy {"aes192-ctr", new CipherInfo(192, (key, iv) => new AesCipher(key, new CtrCipherMode(iv), null))}, }; - HmacAlgorithms = new Dictionary + HmacAlgorithms = new Dictionary { {"hmac-md5", new HashInfo(16*8, CryptoAbstraction.CreateHMACMD5)}, {"hmac-md5-96", new HashInfo(16*8, key => CryptoAbstraction.CreateHMACMD5(key, 96))}, @@ -379,7 +442,7 @@ public ConnectionInfo(string host, int port, string username, ProxyTypes proxyTy //{"none", typeof(...)}, }; - HostKeyAlgorithms = new Dictionary> + HostKeyAlgorithms = new Dictionary> { {"ssh-ed25519", data => new KeyHostAlgorithm("ssh-ed25519", new ED25519Key(), data)}, #if FEATURE_ECDSA @@ -396,6 +459,8 @@ public ConnectionInfo(string host, int port, string username, ProxyTypes proxyTy //{"pgp-sign-rsa", () => { ... }, //{"pgp-sign-dss", () => { ... }, }; + } + CompressionAlgorithms = new Dictionary { diff --git a/src/Renci.SshNet/Renci.SshNet.csproj b/src/Renci.SshNet/Renci.SshNet.csproj index 124ce9d4b..8ccd05528 100644 --- a/src/Renci.SshNet/Renci.SshNet.csproj +++ b/src/Renci.SshNet/Renci.SshNet.csproj @@ -7,7 +7,7 @@ ../Renci.SshNet.snk 5 true - net35;net40;netstandard1.3;netstandard2.0 + net35;net40;netstandard2.0