diff options
Diffstat (limited to 'crypto/src')
-rw-r--r-- | crypto/src/crypto/tls/AbstractTlsKeyExchange.cs | 166 | ||||
-rw-r--r-- | crypto/src/crypto/tls/DefaultTlsClient.cs | 378 | ||||
-rw-r--r-- | crypto/src/crypto/tls/PskTlsClient.cs | 226 | ||||
-rw-r--r-- | crypto/src/crypto/tls/SrpTlsClient.cs | 16 | ||||
-rw-r--r-- | crypto/src/crypto/tls/TlsDHKeyExchange.cs | 196 | ||||
-rw-r--r-- | crypto/src/crypto/tls/TlsDheKeyExchange.cs | 97 | ||||
-rw-r--r-- | crypto/src/crypto/tls/TlsECDHKeyExchange.cs | 243 | ||||
-rw-r--r-- | crypto/src/crypto/tls/TlsECDheKeyExchange.cs | 190 | ||||
-rw-r--r-- | crypto/src/crypto/tls/TlsKeyExchange.cs | 80 | ||||
-rw-r--r-- | crypto/src/crypto/tls/TlsProtocolHandler.cs | 4 | ||||
-rw-r--r-- | crypto/src/crypto/tls/TlsPskKeyExchange.cs | 224 | ||||
-rw-r--r-- | crypto/src/crypto/tls/TlsRsaKeyExchange.cs | 141 | ||||
-rw-r--r-- | crypto/src/crypto/tls/TlsSrpKeyExchange.cs | 173 |
13 files changed, 1432 insertions, 702 deletions
diff --git a/crypto/src/crypto/tls/AbstractTlsKeyExchange.cs b/crypto/src/crypto/tls/AbstractTlsKeyExchange.cs new file mode 100644 index 000000000..155ac94d8 --- /dev/null +++ b/crypto/src/crypto/tls/AbstractTlsKeyExchange.cs @@ -0,0 +1,166 @@ +using System; +using System.Collections; +using System.IO; + +namespace Org.BouncyCastle.Crypto.Tls +{ + public abstract class AbstractTlsKeyExchange + : TlsKeyExchange + { + protected readonly int mKeyExchange; + protected IList mSupportedSignatureAlgorithms; + + protected TlsContext context; + + protected AbstractTlsKeyExchange(int keyExchange, IList supportedSignatureAlgorithms) + { + this.mKeyExchange = keyExchange; + this.mSupportedSignatureAlgorithms = supportedSignatureAlgorithms; + } + + public virtual void Init(TlsContext context) + { + this.context = context; + + ProtocolVersion clientVersion = context.ClientVersion; + + if (TlsUtilities.IsSignatureAlgorithmsExtensionAllowed(clientVersion)) + { + /* + * RFC 5264 7.4.1.4.1. If the client does not send the signature_algorithms extension, + * the server MUST do the following: + * + * - If the negotiated key exchange algorithm is one of (RSA, DHE_RSA, DH_RSA, RSA_PSK, + * ECDH_RSA, ECDHE_RSA), behave as if client had sent the value {sha1,rsa}. + * + * - If the negotiated key exchange algorithm is one of (DHE_DSS, DH_DSS), behave as if + * the client had sent the value {sha1,dsa}. + * + * - If the negotiated key exchange algorithm is one of (ECDH_ECDSA, ECDHE_ECDSA), + * behave as if the client had sent value {sha1,ecdsa}. + */ + if (this.mSupportedSignatureAlgorithms == null) + { + switch (mKeyExchange) + { + case KeyExchangeAlgorithm.DH_DSS: + case KeyExchangeAlgorithm.DHE_DSS: + case KeyExchangeAlgorithm.SRP_DSS: + { + this.mSupportedSignatureAlgorithms = TlsUtilities.GetDefaultDssSignatureAlgorithms(); + break; + } + + case KeyExchangeAlgorithm.ECDH_ECDSA: + case KeyExchangeAlgorithm.ECDHE_ECDSA: + { + this.mSupportedSignatureAlgorithms = TlsUtilities.GetDefaultECDsaSignatureAlgorithms(); + break; + } + + case KeyExchangeAlgorithm.DH_RSA: + case KeyExchangeAlgorithm.DHE_RSA: + case KeyExchangeAlgorithm.ECDH_RSA: + case KeyExchangeAlgorithm.ECDHE_RSA: + case KeyExchangeAlgorithm.RSA: + case KeyExchangeAlgorithm.RSA_PSK: + case KeyExchangeAlgorithm.SRP_RSA: + { + this.mSupportedSignatureAlgorithms = TlsUtilities.GetDefaultRsaSignatureAlgorithms(); + break; + } + + case KeyExchangeAlgorithm.DHE_PSK: + case KeyExchangeAlgorithm.ECDHE_PSK: + case KeyExchangeAlgorithm.PSK: + case KeyExchangeAlgorithm.SRP: + break; + + default: + throw new InvalidOperationException("unsupported key exchange algorithm"); + } + } + + } + else if (this.mSupportedSignatureAlgorithms != null) + { + throw new InvalidOperationException("supported_signature_algorithms not allowed for " + clientVersion); + } + } + + public abstract void SkipServerCredentials(); + + public virtual void ProcessServerCertificate(Certificate serverCertificate) + { + if (mSupportedSignatureAlgorithms == null) + { + /* + * TODO RFC 2264 7.4.2. Unless otherwise specified, the signing algorithm for the + * certificate must be the same as the algorithm for the certificate key. + */ + } + else + { + /* + * TODO RFC 5264 7.4.2. If the client provided a "signature_algorithms" extension, then + * all certificates provided by the server MUST be signed by a hash/signature algorithm + * pair that appears in that extension. + */ + } + } + + public virtual void ProcessServerCredentials(TlsCredentials serverCredentials) + { + ProcessServerCertificate(serverCredentials.Certificate); + } + + public virtual bool RequiresServerKeyExchange + { + get { return false; } + } + + public virtual byte[] GenerateServerKeyExchange() + { + if (RequiresServerKeyExchange) + throw new TlsFatalAlert(AlertDescription.internal_error); + + return null; + } + + public virtual void SkipServerKeyExchange() + { + if (RequiresServerKeyExchange) + throw new TlsFatalAlert(AlertDescription.unexpected_message); + } + + public virtual void ProcessServerKeyExchange(Stream input) + { + if (!RequiresServerKeyExchange) + { + throw new TlsFatalAlert(AlertDescription.unexpected_message); + } + } + + public abstract void ValidateCertificateRequest(CertificateRequest certificateRequest); + + public virtual void SkipClientCredentials() + { + } + + public abstract void ProcessClientCredentials(TlsCredentials clientCredentials); + + public virtual void ProcessClientCertificate(Certificate clientCertificate) + { + } + + public abstract void GenerateClientKeyExchange(Stream output); + + public virtual void ProcessClientKeyExchange(Stream input) + { + // Key exchange implementation MUST support client key exchange + throw new TlsFatalAlert(AlertDescription.internal_error); + } + + public abstract byte[] GeneratePremasterSecret(); + } +} diff --git a/crypto/src/crypto/tls/DefaultTlsClient.cs b/crypto/src/crypto/tls/DefaultTlsClient.cs index 65106adef..a2a04a33c 100644 --- a/crypto/src/crypto/tls/DefaultTlsClient.cs +++ b/crypto/src/crypto/tls/DefaultTlsClient.cs @@ -26,17 +26,14 @@ namespace Org.BouncyCastle.Crypto.Tls public override int[] GetCipherSuites() { - return new int[] { - CipherSuite.TLS_DHE_RSA_WITH_AES_256_CBC_SHA, - CipherSuite.TLS_DHE_DSS_WITH_AES_256_CBC_SHA, - CipherSuite.TLS_DHE_RSA_WITH_AES_128_CBC_SHA, - CipherSuite.TLS_DHE_DSS_WITH_AES_128_CBC_SHA, - CipherSuite.TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA, - CipherSuite.TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA, - CipherSuite.TLS_RSA_WITH_AES_256_CBC_SHA, + return new int[] + { + CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, + CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256, + CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA, + CipherSuite.TLS_RSA_WITH_AES_128_GCM_SHA256, + CipherSuite.TLS_RSA_WITH_AES_128_CBC_SHA256, CipherSuite.TLS_RSA_WITH_AES_128_CBC_SHA, - CipherSuite.TLS_RSA_WITH_3DES_EDE_CBC_SHA, - CipherSuite.TLS_RSA_WITH_RC4_128_SHA, }; } @@ -44,62 +41,176 @@ namespace Org.BouncyCastle.Crypto.Tls { switch (mSelectedCipherSuite) { - case CipherSuite.TLS_RSA_WITH_3DES_EDE_CBC_SHA: - case CipherSuite.TLS_RSA_WITH_AES_128_CBC_SHA: - case CipherSuite.TLS_RSA_WITH_AES_256_CBC_SHA: - case CipherSuite.TLS_RSA_WITH_RC4_128_SHA: - return CreateRsaKeyExchange(); - case CipherSuite.TLS_DH_DSS_WITH_3DES_EDE_CBC_SHA: case CipherSuite.TLS_DH_DSS_WITH_AES_128_CBC_SHA: + case CipherSuite.TLS_DH_DSS_WITH_AES_128_CBC_SHA256: + case CipherSuite.TLS_DH_DSS_WITH_AES_128_GCM_SHA256: case CipherSuite.TLS_DH_DSS_WITH_AES_256_CBC_SHA: + case CipherSuite.TLS_DH_DSS_WITH_AES_256_CBC_SHA256: + case CipherSuite.TLS_DH_DSS_WITH_AES_256_GCM_SHA384: + case CipherSuite.TLS_DH_DSS_WITH_CAMELLIA_128_CBC_SHA: + case CipherSuite.TLS_DH_DSS_WITH_CAMELLIA_128_CBC_SHA256: + case CipherSuite.TLS_DH_DSS_WITH_CAMELLIA_128_GCM_SHA256: + case CipherSuite.TLS_DH_DSS_WITH_CAMELLIA_256_CBC_SHA: + case CipherSuite.TLS_DH_DSS_WITH_CAMELLIA_256_CBC_SHA256: + case CipherSuite.TLS_DH_DSS_WITH_CAMELLIA_256_GCM_SHA384: + case CipherSuite.TLS_DH_DSS_WITH_SEED_CBC_SHA: return CreateDHKeyExchange(KeyExchangeAlgorithm.DH_DSS); case CipherSuite.TLS_DH_RSA_WITH_3DES_EDE_CBC_SHA: case CipherSuite.TLS_DH_RSA_WITH_AES_128_CBC_SHA: + case CipherSuite.TLS_DH_RSA_WITH_AES_128_CBC_SHA256: + case CipherSuite.TLS_DH_RSA_WITH_AES_128_GCM_SHA256: case CipherSuite.TLS_DH_RSA_WITH_AES_256_CBC_SHA: + case CipherSuite.TLS_DH_RSA_WITH_AES_256_CBC_SHA256: + case CipherSuite.TLS_DH_RSA_WITH_AES_256_GCM_SHA384: + case CipherSuite.TLS_DH_RSA_WITH_CAMELLIA_128_CBC_SHA: + case CipherSuite.TLS_DH_RSA_WITH_CAMELLIA_128_CBC_SHA256: + case CipherSuite.TLS_DH_RSA_WITH_CAMELLIA_128_GCM_SHA256: + case CipherSuite.TLS_DH_RSA_WITH_CAMELLIA_256_CBC_SHA: + case CipherSuite.TLS_DH_RSA_WITH_CAMELLIA_256_CBC_SHA256: + case CipherSuite.TLS_DH_RSA_WITH_CAMELLIA_256_GCM_SHA384: + case CipherSuite.TLS_DH_RSA_WITH_SEED_CBC_SHA: return CreateDHKeyExchange(KeyExchangeAlgorithm.DH_RSA); case CipherSuite.TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA: case CipherSuite.TLS_DHE_DSS_WITH_AES_128_CBC_SHA: + case CipherSuite.TLS_DHE_DSS_WITH_AES_128_CBC_SHA256: + case CipherSuite.TLS_DHE_DSS_WITH_AES_128_GCM_SHA256: case CipherSuite.TLS_DHE_DSS_WITH_AES_256_CBC_SHA: + case CipherSuite.TLS_DHE_DSS_WITH_AES_256_CBC_SHA256: + case CipherSuite.TLS_DHE_DSS_WITH_AES_256_GCM_SHA384: + case CipherSuite.TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA: + case CipherSuite.TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA256: + case CipherSuite.TLS_DHE_DSS_WITH_CAMELLIA_128_GCM_SHA256: + case CipherSuite.TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA: + case CipherSuite.TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA256: + case CipherSuite.TLS_DHE_DSS_WITH_CAMELLIA_256_GCM_SHA384: + case CipherSuite.TLS_DHE_DSS_WITH_SEED_CBC_SHA: return CreateDheKeyExchange(KeyExchangeAlgorithm.DHE_DSS); case CipherSuite.TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA: case CipherSuite.TLS_DHE_RSA_WITH_AES_128_CBC_SHA: + case CipherSuite.TLS_DHE_RSA_WITH_AES_128_CBC_SHA256: + case CipherSuite.TLS_DHE_RSA_WITH_AES_128_CCM: + case CipherSuite.TLS_DHE_RSA_WITH_AES_128_CCM_8: + case CipherSuite.TLS_DHE_RSA_WITH_AES_128_GCM_SHA256: case CipherSuite.TLS_DHE_RSA_WITH_AES_256_CBC_SHA: + case CipherSuite.TLS_DHE_RSA_WITH_AES_256_CBC_SHA256: + case CipherSuite.TLS_DHE_RSA_WITH_AES_256_CCM: + case CipherSuite.TLS_DHE_RSA_WITH_AES_256_CCM_8: + case CipherSuite.TLS_DHE_RSA_WITH_AES_256_GCM_SHA384: + case CipherSuite.TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA: + case CipherSuite.TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256: + case CipherSuite.TLS_DHE_RSA_WITH_CAMELLIA_128_GCM_SHA256: + case CipherSuite.TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA: + case CipherSuite.TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256: + case CipherSuite.TLS_DHE_RSA_WITH_CAMELLIA_256_GCM_SHA384: + case CipherSuite.TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256: + case CipherSuite.TLS_DHE_RSA_WITH_ESTREAM_SALSA20_SHA1: + case CipherSuite.TLS_DHE_RSA_WITH_SALSA20_SHA1: + case CipherSuite.TLS_DHE_RSA_WITH_SEED_CBC_SHA: return CreateDheKeyExchange(KeyExchangeAlgorithm.DHE_RSA); case CipherSuite.TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA: case CipherSuite.TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA: + case CipherSuite.TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256: + case CipherSuite.TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256: case CipherSuite.TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA: + case CipherSuite.TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384: + case CipherSuite.TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384: + case CipherSuite.TLS_ECDH_ECDSA_WITH_CAMELLIA_128_CBC_SHA256: + case CipherSuite.TLS_ECDH_ECDSA_WITH_CAMELLIA_128_GCM_SHA256: + case CipherSuite.TLS_ECDH_ECDSA_WITH_CAMELLIA_256_CBC_SHA384: + case CipherSuite.TLS_ECDH_ECDSA_WITH_CAMELLIA_256_GCM_SHA384: + case CipherSuite.TLS_ECDH_ECDSA_WITH_NULL_SHA: case CipherSuite.TLS_ECDH_ECDSA_WITH_RC4_128_SHA: return CreateECDHKeyExchange(KeyExchangeAlgorithm.ECDH_ECDSA); - case CipherSuite.TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA: - case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA: - case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA: - case CipherSuite.TLS_ECDHE_ECDSA_WITH_RC4_128_SHA: - return CreateECDheKeyExchange(KeyExchangeAlgorithm.ECDHE_ECDSA); - case CipherSuite.TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA: case CipherSuite.TLS_ECDH_RSA_WITH_AES_128_CBC_SHA: + case CipherSuite.TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256: + case CipherSuite.TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256: case CipherSuite.TLS_ECDH_RSA_WITH_AES_256_CBC_SHA: + case CipherSuite.TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384: + case CipherSuite.TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384: + case CipherSuite.TLS_ECDH_RSA_WITH_CAMELLIA_128_CBC_SHA256: + case CipherSuite.TLS_ECDH_RSA_WITH_CAMELLIA_128_GCM_SHA256: + case CipherSuite.TLS_ECDH_RSA_WITH_CAMELLIA_256_CBC_SHA384: + case CipherSuite.TLS_ECDH_RSA_WITH_CAMELLIA_256_GCM_SHA384: + case CipherSuite.TLS_ECDH_RSA_WITH_NULL_SHA: case CipherSuite.TLS_ECDH_RSA_WITH_RC4_128_SHA: return CreateECDHKeyExchange(KeyExchangeAlgorithm.ECDH_RSA); + case CipherSuite.TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA: + case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA: + case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256: + case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256: + case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA: + case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384: + case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384: + case CipherSuite.TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_CBC_SHA256: + case CipherSuite.TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_GCM_SHA256: + case CipherSuite.TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_CBC_SHA384: + case CipherSuite.TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_GCM_SHA384: + case CipherSuite.TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256: + case CipherSuite.TLS_ECDHE_ECDSA_WITH_ESTREAM_SALSA20_SHA1: + case CipherSuite.TLS_ECDHE_ECDSA_WITH_NULL_SHA: + case CipherSuite.TLS_ECDHE_ECDSA_WITH_RC4_128_SHA: + case CipherSuite.TLS_ECDHE_ECDSA_WITH_SALSA20_SHA1: + return CreateECDheKeyExchange(KeyExchangeAlgorithm.ECDHE_ECDSA); + case CipherSuite.TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA: case CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA: + case CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256: + case CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256: case CipherSuite.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA: + case CipherSuite.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384: + case CipherSuite.TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384: + case CipherSuite.TLS_ECDHE_RSA_WITH_CAMELLIA_128_CBC_SHA256: + case CipherSuite.TLS_ECDHE_RSA_WITH_CAMELLIA_128_GCM_SHA256: + case CipherSuite.TLS_ECDHE_RSA_WITH_CAMELLIA_256_CBC_SHA384: + case CipherSuite.TLS_ECDHE_RSA_WITH_CAMELLIA_256_GCM_SHA384: + case CipherSuite.TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256: + case CipherSuite.TLS_ECDHE_RSA_WITH_ESTREAM_SALSA20_SHA1: + case CipherSuite.TLS_ECDHE_RSA_WITH_NULL_SHA: case CipherSuite.TLS_ECDHE_RSA_WITH_RC4_128_SHA: + case CipherSuite.TLS_ECDHE_RSA_WITH_SALSA20_SHA1: return CreateECDheKeyExchange(KeyExchangeAlgorithm.ECDHE_RSA); + case CipherSuite.TLS_RSA_WITH_3DES_EDE_CBC_SHA: + case CipherSuite.TLS_RSA_WITH_AES_128_CBC_SHA: + case CipherSuite.TLS_RSA_WITH_AES_128_CBC_SHA256: + case CipherSuite.TLS_RSA_WITH_AES_128_CCM: + case CipherSuite.TLS_RSA_WITH_AES_128_CCM_8: + case CipherSuite.TLS_RSA_WITH_AES_128_GCM_SHA256: + case CipherSuite.TLS_RSA_WITH_AES_256_CBC_SHA: + case CipherSuite.TLS_RSA_WITH_AES_256_CBC_SHA256: + case CipherSuite.TLS_RSA_WITH_AES_256_CCM: + case CipherSuite.TLS_RSA_WITH_AES_256_CCM_8: + case CipherSuite.TLS_RSA_WITH_AES_256_GCM_SHA384: + case CipherSuite.TLS_RSA_WITH_CAMELLIA_128_CBC_SHA: + case CipherSuite.TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256: + case CipherSuite.TLS_RSA_WITH_CAMELLIA_128_GCM_SHA256: + case CipherSuite.TLS_RSA_WITH_CAMELLIA_256_CBC_SHA: + case CipherSuite.TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256: + case CipherSuite.TLS_RSA_WITH_CAMELLIA_256_GCM_SHA384: + case CipherSuite.TLS_RSA_WITH_ESTREAM_SALSA20_SHA1: + case CipherSuite.TLS_RSA_WITH_NULL_MD5: + case CipherSuite.TLS_RSA_WITH_NULL_SHA: + case CipherSuite.TLS_RSA_WITH_NULL_SHA256: + case CipherSuite.TLS_RSA_WITH_RC4_128_MD5: + case CipherSuite.TLS_RSA_WITH_RC4_128_SHA: + case CipherSuite.TLS_RSA_WITH_SALSA20_SHA1: + case CipherSuite.TLS_RSA_WITH_SEED_CBC_SHA: + return CreateRsaKeyExchange(); + default: /* - * Note: internal error here; the TlsProtocol implementation verifies that the - * server-selected cipher suite was in the list of client-offered cipher suites, so if - * we now can't produce an implementation, we shouldn't have offered it! - */ + * Note: internal error here; the TlsProtocol implementation verifies that the + * server-selected cipher suite was in the list of client-offered cipher suites, so if + * we now can't produce an implementation, we shouldn't have offered it! + */ throw new TlsFatalAlert(AlertDescription.internal_error); } } @@ -108,82 +219,243 @@ namespace Org.BouncyCastle.Crypto.Tls { switch (mSelectedCipherSuite) { - case CipherSuite.TLS_RSA_WITH_3DES_EDE_CBC_SHA: case CipherSuite.TLS_DH_DSS_WITH_3DES_EDE_CBC_SHA: case CipherSuite.TLS_DH_RSA_WITH_3DES_EDE_CBC_SHA: case CipherSuite.TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA: case CipherSuite.TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA: case CipherSuite.TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA: - case CipherSuite.TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA: case CipherSuite.TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA: + case CipherSuite.TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA: case CipherSuite.TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA: - return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.cls_3DES_EDE_CBC, - MacAlgorithm.hmac_sha1); + case CipherSuite.TLS_RSA_WITH_3DES_EDE_CBC_SHA: + return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.cls_3DES_EDE_CBC, MacAlgorithm.hmac_sha1); - case CipherSuite.TLS_RSA_WITH_RC4_128_SHA: - case CipherSuite.TLS_ECDH_ECDSA_WITH_RC4_128_SHA: - case CipherSuite.TLS_ECDHE_ECDSA_WITH_RC4_128_SHA: - case CipherSuite.TLS_ECDH_RSA_WITH_RC4_128_SHA: - case CipherSuite.TLS_ECDHE_RSA_WITH_RC4_128_SHA: - return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.RC4_128, MacAlgorithm.hmac_sha1); + case CipherSuite.TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256: + case CipherSuite.TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256: + case CipherSuite.TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256: + return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.AEAD_CHACHA20_POLY1305, MacAlgorithm.cls_null); - case CipherSuite.TLS_RSA_WITH_AES_128_CBC_SHA: case CipherSuite.TLS_DH_DSS_WITH_AES_128_CBC_SHA: case CipherSuite.TLS_DH_RSA_WITH_AES_128_CBC_SHA: case CipherSuite.TLS_DHE_DSS_WITH_AES_128_CBC_SHA: case CipherSuite.TLS_DHE_RSA_WITH_AES_128_CBC_SHA: case CipherSuite.TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA: - case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA: case CipherSuite.TLS_ECDH_RSA_WITH_AES_128_CBC_SHA: + case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA: case CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA: - return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.AES_128_CBC, - MacAlgorithm.hmac_sha1); + case CipherSuite.TLS_RSA_WITH_AES_128_CBC_SHA: + return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.AES_128_CBC, MacAlgorithm.hmac_sha1); + + case CipherSuite.TLS_DH_DSS_WITH_AES_128_CBC_SHA256: + case CipherSuite.TLS_DH_RSA_WITH_AES_128_CBC_SHA256: + case CipherSuite.TLS_DHE_DSS_WITH_AES_128_CBC_SHA256: + case CipherSuite.TLS_DHE_RSA_WITH_AES_128_CBC_SHA256: + case CipherSuite.TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256: + case CipherSuite.TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256: + case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256: + case CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256: + case CipherSuite.TLS_RSA_WITH_AES_128_CBC_SHA256: + return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.AES_128_CBC, MacAlgorithm.hmac_sha256); + + case CipherSuite.TLS_DHE_RSA_WITH_AES_128_CCM: + case CipherSuite.TLS_RSA_WITH_AES_128_CCM: + return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.AES_128_CCM, MacAlgorithm.cls_null); + + case CipherSuite.TLS_DHE_RSA_WITH_AES_128_CCM_8: + case CipherSuite.TLS_RSA_WITH_AES_128_CCM_8: + return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.AES_128_CCM_8, MacAlgorithm.cls_null); + + case CipherSuite.TLS_DH_DSS_WITH_AES_128_GCM_SHA256: + case CipherSuite.TLS_DH_RSA_WITH_AES_128_GCM_SHA256: + case CipherSuite.TLS_DHE_DSS_WITH_AES_128_GCM_SHA256: + case CipherSuite.TLS_DHE_RSA_WITH_AES_128_GCM_SHA256: + case CipherSuite.TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256: + case CipherSuite.TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256: + case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256: + case CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256: + case CipherSuite.TLS_RSA_WITH_AES_128_GCM_SHA256: + return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.AES_128_GCM, MacAlgorithm.cls_null); - case CipherSuite.TLS_RSA_WITH_AES_256_CBC_SHA: case CipherSuite.TLS_DH_DSS_WITH_AES_256_CBC_SHA: case CipherSuite.TLS_DH_RSA_WITH_AES_256_CBC_SHA: case CipherSuite.TLS_DHE_DSS_WITH_AES_256_CBC_SHA: case CipherSuite.TLS_DHE_RSA_WITH_AES_256_CBC_SHA: case CipherSuite.TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA: - case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA: case CipherSuite.TLS_ECDH_RSA_WITH_AES_256_CBC_SHA: + case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA: case CipherSuite.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA: - return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.AES_256_CBC, - MacAlgorithm.hmac_sha1); + case CipherSuite.TLS_RSA_WITH_AES_256_CBC_SHA: + return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.AES_256_CBC, MacAlgorithm.hmac_sha1); + + case CipherSuite.TLS_DH_DSS_WITH_AES_256_CBC_SHA256: + case CipherSuite.TLS_DH_RSA_WITH_AES_256_CBC_SHA256: + case CipherSuite.TLS_DHE_DSS_WITH_AES_256_CBC_SHA256: + case CipherSuite.TLS_DHE_RSA_WITH_AES_256_CBC_SHA256: + case CipherSuite.TLS_RSA_WITH_AES_256_CBC_SHA256: + return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.AES_256_CBC, MacAlgorithm.hmac_sha256); + + case CipherSuite.TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384: + case CipherSuite.TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384: + case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384: + case CipherSuite.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384: + return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.AES_256_CBC, MacAlgorithm.hmac_sha384); + + case CipherSuite.TLS_DHE_RSA_WITH_AES_256_CCM: + case CipherSuite.TLS_RSA_WITH_AES_256_CCM: + return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.AES_256_CCM, MacAlgorithm.cls_null); + + case CipherSuite.TLS_DHE_RSA_WITH_AES_256_CCM_8: + case CipherSuite.TLS_RSA_WITH_AES_256_CCM_8: + return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.AES_256_CCM_8, MacAlgorithm.cls_null); + + case CipherSuite.TLS_DH_DSS_WITH_AES_256_GCM_SHA384: + case CipherSuite.TLS_DH_RSA_WITH_AES_256_GCM_SHA384: + case CipherSuite.TLS_DHE_DSS_WITH_AES_256_GCM_SHA384: + case CipherSuite.TLS_DHE_RSA_WITH_AES_256_GCM_SHA384: + case CipherSuite.TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384: + case CipherSuite.TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384: + case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384: + case CipherSuite.TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384: + case CipherSuite.TLS_RSA_WITH_AES_256_GCM_SHA384: + return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.AES_256_GCM, MacAlgorithm.cls_null); + + case CipherSuite.TLS_DH_DSS_WITH_CAMELLIA_128_CBC_SHA: + case CipherSuite.TLS_DH_RSA_WITH_CAMELLIA_128_CBC_SHA: + case CipherSuite.TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA: + case CipherSuite.TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA: + case CipherSuite.TLS_RSA_WITH_CAMELLIA_128_CBC_SHA: + return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.CAMELLIA_128_CBC, MacAlgorithm.hmac_sha1); + + case CipherSuite.TLS_DH_DSS_WITH_CAMELLIA_128_CBC_SHA256: + case CipherSuite.TLS_DH_RSA_WITH_CAMELLIA_128_CBC_SHA256: + case CipherSuite.TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA256: + case CipherSuite.TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256: + case CipherSuite.TLS_ECDH_ECDSA_WITH_CAMELLIA_128_CBC_SHA256: + case CipherSuite.TLS_ECDH_RSA_WITH_CAMELLIA_128_CBC_SHA256: + case CipherSuite.TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_CBC_SHA256: + case CipherSuite.TLS_ECDHE_RSA_WITH_CAMELLIA_128_CBC_SHA256: + case CipherSuite.TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256: + return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.CAMELLIA_128_CBC, MacAlgorithm.hmac_sha256); + + case CipherSuite.TLS_RSA_WITH_CAMELLIA_128_GCM_SHA256: + case CipherSuite.TLS_DHE_RSA_WITH_CAMELLIA_128_GCM_SHA256: + case CipherSuite.TLS_DH_RSA_WITH_CAMELLIA_128_GCM_SHA256: + case CipherSuite.TLS_DHE_DSS_WITH_CAMELLIA_128_GCM_SHA256: + case CipherSuite.TLS_DH_DSS_WITH_CAMELLIA_128_GCM_SHA256: + case CipherSuite.TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_GCM_SHA256: + case CipherSuite.TLS_ECDH_ECDSA_WITH_CAMELLIA_128_GCM_SHA256: + case CipherSuite.TLS_ECDHE_RSA_WITH_CAMELLIA_128_GCM_SHA256: + case CipherSuite.TLS_ECDH_RSA_WITH_CAMELLIA_128_GCM_SHA256: + return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.CAMELLIA_128_GCM, MacAlgorithm.cls_null); + + case CipherSuite.TLS_DH_DSS_WITH_CAMELLIA_256_CBC_SHA: + case CipherSuite.TLS_DH_RSA_WITH_CAMELLIA_256_CBC_SHA: + case CipherSuite.TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA: + case CipherSuite.TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA: + case CipherSuite.TLS_RSA_WITH_CAMELLIA_256_CBC_SHA: + return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.CAMELLIA_256_CBC, MacAlgorithm.hmac_sha1); + + case CipherSuite.TLS_DH_DSS_WITH_CAMELLIA_256_CBC_SHA256: + case CipherSuite.TLS_DH_RSA_WITH_CAMELLIA_256_CBC_SHA256: + case CipherSuite.TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA256: + case CipherSuite.TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256: + case CipherSuite.TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256: + return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.CAMELLIA_256_CBC, MacAlgorithm.hmac_sha256); + + case CipherSuite.TLS_RSA_WITH_CAMELLIA_256_GCM_SHA384: + case CipherSuite.TLS_DHE_RSA_WITH_CAMELLIA_256_GCM_SHA384: + case CipherSuite.TLS_DH_RSA_WITH_CAMELLIA_256_GCM_SHA384: + case CipherSuite.TLS_DHE_DSS_WITH_CAMELLIA_256_GCM_SHA384: + case CipherSuite.TLS_DH_DSS_WITH_CAMELLIA_256_GCM_SHA384: + case CipherSuite.TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_GCM_SHA384: + case CipherSuite.TLS_ECDH_ECDSA_WITH_CAMELLIA_256_GCM_SHA384: + case CipherSuite.TLS_ECDHE_RSA_WITH_CAMELLIA_256_GCM_SHA384: + case CipherSuite.TLS_ECDH_RSA_WITH_CAMELLIA_256_GCM_SHA384: + return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.CAMELLIA_256_GCM, MacAlgorithm.cls_null); + + case CipherSuite.TLS_ECDH_ECDSA_WITH_CAMELLIA_256_CBC_SHA384: + case CipherSuite.TLS_ECDH_RSA_WITH_CAMELLIA_256_CBC_SHA384: + case CipherSuite.TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_CBC_SHA384: + case CipherSuite.TLS_ECDHE_RSA_WITH_CAMELLIA_256_CBC_SHA384: + return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.CAMELLIA_256_CBC, MacAlgorithm.hmac_sha384); + + case CipherSuite.TLS_DHE_RSA_WITH_ESTREAM_SALSA20_SHA1: + case CipherSuite.TLS_ECDHE_ECDSA_WITH_ESTREAM_SALSA20_SHA1: + case CipherSuite.TLS_ECDHE_RSA_WITH_ESTREAM_SALSA20_SHA1: + case CipherSuite.TLS_RSA_WITH_ESTREAM_SALSA20_SHA1: + return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.ESTREAM_SALSA20, MacAlgorithm.hmac_sha1); + + case CipherSuite.TLS_RSA_WITH_NULL_MD5: + return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.NULL, MacAlgorithm.hmac_md5); + + case CipherSuite.TLS_ECDH_ECDSA_WITH_NULL_SHA: + case CipherSuite.TLS_ECDH_RSA_WITH_NULL_SHA: + case CipherSuite.TLS_ECDHE_ECDSA_WITH_NULL_SHA: + case CipherSuite.TLS_ECDHE_RSA_WITH_NULL_SHA: + case CipherSuite.TLS_RSA_WITH_NULL_SHA: + return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.NULL, MacAlgorithm.hmac_sha1); + + case CipherSuite.TLS_RSA_WITH_NULL_SHA256: + return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.NULL, MacAlgorithm.hmac_sha256); + + case CipherSuite.TLS_RSA_WITH_RC4_128_MD5: + return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.RC4_128, MacAlgorithm.hmac_md5); + + case CipherSuite.TLS_ECDH_ECDSA_WITH_RC4_128_SHA: + case CipherSuite.TLS_ECDH_RSA_WITH_RC4_128_SHA: + case CipherSuite.TLS_ECDHE_ECDSA_WITH_RC4_128_SHA: + case CipherSuite.TLS_ECDHE_RSA_WITH_RC4_128_SHA: + case CipherSuite.TLS_RSA_WITH_RC4_128_SHA: + return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.RC4_128, MacAlgorithm.hmac_sha1); + + case CipherSuite.TLS_DHE_RSA_WITH_SALSA20_SHA1: + case CipherSuite.TLS_ECDHE_ECDSA_WITH_SALSA20_SHA1: + case CipherSuite.TLS_ECDHE_RSA_WITH_SALSA20_SHA1: + case CipherSuite.TLS_RSA_WITH_SALSA20_SHA1: + return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.SALSA20, MacAlgorithm.hmac_sha1); + + case CipherSuite.TLS_DH_DSS_WITH_SEED_CBC_SHA: + case CipherSuite.TLS_DH_RSA_WITH_SEED_CBC_SHA: + case CipherSuite.TLS_DHE_DSS_WITH_SEED_CBC_SHA: + case CipherSuite.TLS_DHE_RSA_WITH_SEED_CBC_SHA: + case CipherSuite.TLS_RSA_WITH_SEED_CBC_SHA: + return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.SEED_CBC, MacAlgorithm.hmac_sha1); default: /* - * Note: internal error here; the TlsProtocol implementation verifies that the - * server-selected cipher suite was in the list of client-offered cipher suites, so if - * we now can't produce an implementation, we shouldn't have offered it! - */ + * Note: internal error here; the TlsProtocol implementation verifies that the + * server-selected cipher suite was in the list of client-offered cipher suites, so if + * we now can't produce an implementation, we shouldn't have offered it! + */ throw new TlsFatalAlert(AlertDescription.internal_error); } } protected virtual TlsKeyExchange CreateDHKeyExchange(int keyExchange) { - return new TlsDHKeyExchange(mContext, keyExchange); + return new TlsDHKeyExchange(keyExchange, mSupportedSignatureAlgorithms, null); } protected virtual TlsKeyExchange CreateDheKeyExchange(int keyExchange) { - return new TlsDheKeyExchange(mContext, keyExchange); + return new TlsDheKeyExchange(keyExchange, mSupportedSignatureAlgorithms, null); } protected virtual TlsKeyExchange CreateECDHKeyExchange(int keyExchange) { - return new TlsECDHKeyExchange(mContext, keyExchange); + return new TlsECDHKeyExchange(keyExchange, mSupportedSignatureAlgorithms, mNamedCurves, mClientECPointFormats, + mServerECPointFormats); } protected virtual TlsKeyExchange CreateECDheKeyExchange(int keyExchange) { - return new TlsECDheKeyExchange(mContext, keyExchange); + return new TlsECDheKeyExchange(keyExchange, mSupportedSignatureAlgorithms, mNamedCurves, mClientECPointFormats, + mServerECPointFormats); } protected virtual TlsKeyExchange CreateRsaKeyExchange() { - return new TlsRsaKeyExchange(mContext); + return new TlsRsaKeyExchange(mSupportedSignatureAlgorithms); } } } diff --git a/crypto/src/crypto/tls/PskTlsClient.cs b/crypto/src/crypto/tls/PskTlsClient.cs index 620a6d8f7..6063572a0 100644 --- a/crypto/src/crypto/tls/PskTlsClient.cs +++ b/crypto/src/crypto/tls/PskTlsClient.cs @@ -21,19 +21,12 @@ namespace Org.BouncyCastle.Crypto.Tls public override int[] GetCipherSuites() { - return new int[] { - CipherSuite.TLS_DHE_PSK_WITH_AES_256_CBC_SHA, - CipherSuite.TLS_DHE_PSK_WITH_AES_128_CBC_SHA, - CipherSuite.TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA, - CipherSuite.TLS_DHE_PSK_WITH_RC4_128_SHA, - CipherSuite.TLS_RSA_PSK_WITH_AES_256_CBC_SHA, - CipherSuite.TLS_RSA_PSK_WITH_AES_128_CBC_SHA, - CipherSuite.TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA, - CipherSuite.TLS_RSA_PSK_WITH_RC4_128_SHA, - CipherSuite.TLS_PSK_WITH_AES_256_CBC_SHA, - CipherSuite.TLS_PSK_WITH_AES_128_CBC_SHA, - CipherSuite.TLS_PSK_WITH_3DES_EDE_CBC_SHA, - CipherSuite.TLS_PSK_WITH_RC4_128_SHA, + return new int[] + { + CipherSuite.TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256, + CipherSuite.TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA, + CipherSuite.TLS_RSA_PSK_WITH_AES_128_CBC_SHA256, + CipherSuite.TLS_RSA_PSK_WITH_AES_128_CBC_SHA }; } @@ -41,30 +34,92 @@ namespace Org.BouncyCastle.Crypto.Tls { switch (mSelectedCipherSuite) { + case CipherSuite.TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA: + case CipherSuite.TLS_DHE_PSK_WITH_AES_128_CBC_SHA: + case CipherSuite.TLS_DHE_PSK_WITH_AES_128_CBC_SHA256: + case CipherSuite.TLS_DHE_PSK_WITH_AES_128_CCM: + case CipherSuite.TLS_DHE_PSK_WITH_AES_128_GCM_SHA256: + case CipherSuite.TLS_DHE_PSK_WITH_AES_256_CBC_SHA: + case CipherSuite.TLS_DHE_PSK_WITH_AES_256_CBC_SHA384: + case CipherSuite.TLS_DHE_PSK_WITH_AES_256_CCM: + case CipherSuite.TLS_DHE_PSK_WITH_AES_256_GCM_SHA384: + case CipherSuite.TLS_DHE_PSK_WITH_CAMELLIA_128_CBC_SHA256: + case CipherSuite.TLS_DHE_PSK_WITH_CAMELLIA_128_GCM_SHA256: + case CipherSuite.TLS_DHE_PSK_WITH_CAMELLIA_256_CBC_SHA384: + case CipherSuite.TLS_DHE_PSK_WITH_CAMELLIA_256_GCM_SHA384: + case CipherSuite.TLS_DHE_PSK_WITH_ESTREAM_SALSA20_SHA1: + case CipherSuite.TLS_DHE_PSK_WITH_NULL_SHA: + case CipherSuite.TLS_DHE_PSK_WITH_NULL_SHA256: + case CipherSuite.TLS_DHE_PSK_WITH_NULL_SHA384: + case CipherSuite.TLS_DHE_PSK_WITH_RC4_128_SHA: + case CipherSuite.TLS_DHE_PSK_WITH_SALSA20_SHA1: + case CipherSuite.TLS_PSK_DHE_WITH_AES_128_CCM_8: + case CipherSuite.TLS_PSK_DHE_WITH_AES_256_CCM_8: + return CreatePskKeyExchange(KeyExchangeAlgorithm.DHE_PSK); + + case CipherSuite.TLS_ECDHE_PSK_WITH_3DES_EDE_CBC_SHA: + case CipherSuite.TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA: + case CipherSuite.TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256: + case CipherSuite.TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA: + case CipherSuite.TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA384: + case CipherSuite.TLS_ECDHE_PSK_WITH_CAMELLIA_128_CBC_SHA256: + case CipherSuite.TLS_ECDHE_PSK_WITH_CAMELLIA_256_CBC_SHA384: + case CipherSuite.TLS_ECDHE_PSK_WITH_ESTREAM_SALSA20_SHA1: + case CipherSuite.TLS_ECDHE_PSK_WITH_NULL_SHA: + case CipherSuite.TLS_ECDHE_PSK_WITH_NULL_SHA256: + case CipherSuite.TLS_ECDHE_PSK_WITH_NULL_SHA384: + case CipherSuite.TLS_ECDHE_PSK_WITH_RC4_128_SHA: + case CipherSuite.TLS_ECDHE_PSK_WITH_SALSA20_SHA1: + return CreatePskKeyExchange(KeyExchangeAlgorithm.ECDHE_PSK); + case CipherSuite.TLS_PSK_WITH_3DES_EDE_CBC_SHA: case CipherSuite.TLS_PSK_WITH_AES_128_CBC_SHA: + case CipherSuite.TLS_PSK_WITH_AES_128_CBC_SHA256: + case CipherSuite.TLS_PSK_WITH_AES_128_CCM: + case CipherSuite.TLS_PSK_WITH_AES_128_CCM_8: + case CipherSuite.TLS_PSK_WITH_AES_128_GCM_SHA256: case CipherSuite.TLS_PSK_WITH_AES_256_CBC_SHA: + case CipherSuite.TLS_PSK_WITH_AES_256_CBC_SHA384: + case CipherSuite.TLS_PSK_WITH_AES_256_CCM: + case CipherSuite.TLS_PSK_WITH_AES_256_CCM_8: + case CipherSuite.TLS_PSK_WITH_AES_256_GCM_SHA384: + case CipherSuite.TLS_PSK_WITH_CAMELLIA_128_CBC_SHA256: + case CipherSuite.TLS_PSK_WITH_CAMELLIA_128_GCM_SHA256: + case CipherSuite.TLS_PSK_WITH_CAMELLIA_256_CBC_SHA384: + case CipherSuite.TLS_PSK_WITH_CAMELLIA_256_GCM_SHA384: + case CipherSuite.TLS_PSK_WITH_ESTREAM_SALSA20_SHA1: + case CipherSuite.TLS_PSK_WITH_NULL_SHA: + case CipherSuite.TLS_PSK_WITH_NULL_SHA256: + case CipherSuite.TLS_PSK_WITH_NULL_SHA384: case CipherSuite.TLS_PSK_WITH_RC4_128_SHA: + case CipherSuite.TLS_PSK_WITH_SALSA20_SHA1: return CreatePskKeyExchange(KeyExchangeAlgorithm.PSK); case CipherSuite.TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA: case CipherSuite.TLS_RSA_PSK_WITH_AES_128_CBC_SHA: + case CipherSuite.TLS_RSA_PSK_WITH_AES_128_CBC_SHA256: + case CipherSuite.TLS_RSA_PSK_WITH_AES_128_GCM_SHA256: case CipherSuite.TLS_RSA_PSK_WITH_AES_256_CBC_SHA: + case CipherSuite.TLS_RSA_PSK_WITH_AES_256_CBC_SHA384: + case CipherSuite.TLS_RSA_PSK_WITH_AES_256_GCM_SHA384: + case CipherSuite.TLS_RSA_PSK_WITH_CAMELLIA_128_CBC_SHA256: + case CipherSuite.TLS_RSA_PSK_WITH_CAMELLIA_128_GCM_SHA256: + case CipherSuite.TLS_RSA_PSK_WITH_CAMELLIA_256_CBC_SHA384: + case CipherSuite.TLS_RSA_PSK_WITH_CAMELLIA_256_GCM_SHA384: + case CipherSuite.TLS_RSA_PSK_WITH_ESTREAM_SALSA20_SHA1: + case CipherSuite.TLS_RSA_PSK_WITH_NULL_SHA: + case CipherSuite.TLS_RSA_PSK_WITH_NULL_SHA256: + case CipherSuite.TLS_RSA_PSK_WITH_NULL_SHA384: case CipherSuite.TLS_RSA_PSK_WITH_RC4_128_SHA: + case CipherSuite.TLS_RSA_PSK_WITH_SALSA20_SHA1: return CreatePskKeyExchange(KeyExchangeAlgorithm.RSA_PSK); - case CipherSuite.TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA: - case CipherSuite.TLS_DHE_PSK_WITH_AES_128_CBC_SHA: - case CipherSuite.TLS_DHE_PSK_WITH_AES_256_CBC_SHA: - case CipherSuite.TLS_DHE_PSK_WITH_RC4_128_SHA: - return CreatePskKeyExchange(KeyExchangeAlgorithm.DHE_PSK); - default: /* - * Note: internal error here; the TlsProtocol implementation verifies that the - * server-selected cipher suite was in the list of client-offered cipher suites, so if - * we now can't produce an implementation, we shouldn't have offered it! - */ + * Note: internal error here; the TlsProtocol implementation verifies that the + * server-selected cipher suite was in the list of client-offered cipher suites, so if + * we now can't produce an implementation, we shouldn't have offered it! + */ throw new TlsFatalAlert(AlertDescription.internal_error); } } @@ -73,43 +128,134 @@ namespace Org.BouncyCastle.Crypto.Tls { switch (mSelectedCipherSuite) { + case CipherSuite.TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA: + case CipherSuite.TLS_ECDHE_PSK_WITH_3DES_EDE_CBC_SHA: case CipherSuite.TLS_PSK_WITH_3DES_EDE_CBC_SHA: case CipherSuite.TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA: - case CipherSuite.TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA: - return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.cls_3DES_EDE_CBC, - MacAlgorithm.hmac_sha1); + return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.cls_3DES_EDE_CBC, MacAlgorithm.hmac_sha1); + case CipherSuite.TLS_DHE_PSK_WITH_AES_128_CBC_SHA: + case CipherSuite.TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA: case CipherSuite.TLS_PSK_WITH_AES_128_CBC_SHA: case CipherSuite.TLS_RSA_PSK_WITH_AES_128_CBC_SHA: - case CipherSuite.TLS_DHE_PSK_WITH_AES_128_CBC_SHA: - return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.AES_128_CBC, - MacAlgorithm.hmac_sha1); + return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.AES_128_CBC, MacAlgorithm.hmac_sha1); + + case CipherSuite.TLS_DHE_PSK_WITH_AES_128_CBC_SHA256: + case CipherSuite.TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256: + case CipherSuite.TLS_PSK_WITH_AES_128_CBC_SHA256: + case CipherSuite.TLS_RSA_PSK_WITH_AES_128_CBC_SHA256: + return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.AES_128_CBC, MacAlgorithm.hmac_sha256); + + case CipherSuite.TLS_DHE_PSK_WITH_AES_128_CCM: + case CipherSuite.TLS_PSK_WITH_AES_128_CCM: + return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.AES_128_CCM, MacAlgorithm.cls_null); + case CipherSuite.TLS_PSK_DHE_WITH_AES_128_CCM_8: + case CipherSuite.TLS_PSK_WITH_AES_128_CCM_8: + return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.AES_128_CCM_8, MacAlgorithm.cls_null); + + case CipherSuite.TLS_DHE_PSK_WITH_AES_128_GCM_SHA256: + case CipherSuite.TLS_PSK_WITH_AES_128_GCM_SHA256: + case CipherSuite.TLS_RSA_PSK_WITH_AES_128_GCM_SHA256: + return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.AES_128_GCM, MacAlgorithm.cls_null); + + case CipherSuite.TLS_DHE_PSK_WITH_AES_256_CBC_SHA: + case CipherSuite.TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA: case CipherSuite.TLS_PSK_WITH_AES_256_CBC_SHA: case CipherSuite.TLS_RSA_PSK_WITH_AES_256_CBC_SHA: - case CipherSuite.TLS_DHE_PSK_WITH_AES_256_CBC_SHA: - return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.AES_256_CBC, - MacAlgorithm.hmac_sha1); + return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.AES_256_CBC, MacAlgorithm.hmac_sha1); + + case CipherSuite.TLS_DHE_PSK_WITH_AES_256_CBC_SHA384: + case CipherSuite.TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA384: + case CipherSuite.TLS_PSK_WITH_AES_256_CBC_SHA384: + case CipherSuite.TLS_RSA_PSK_WITH_AES_256_CBC_SHA384: + return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.AES_256_CBC, MacAlgorithm.hmac_sha384); + + case CipherSuite.TLS_DHE_PSK_WITH_AES_256_CCM: + case CipherSuite.TLS_PSK_WITH_AES_256_CCM: + return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.AES_256_CCM, MacAlgorithm.cls_null); + + case CipherSuite.TLS_PSK_DHE_WITH_AES_256_CCM_8: + case CipherSuite.TLS_PSK_WITH_AES_256_CCM_8: + return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.AES_256_CCM_8, MacAlgorithm.cls_null); + + case CipherSuite.TLS_DHE_PSK_WITH_AES_256_GCM_SHA384: + case CipherSuite.TLS_PSK_WITH_AES_256_GCM_SHA384: + case CipherSuite.TLS_RSA_PSK_WITH_AES_256_GCM_SHA384: + return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.AES_256_GCM, MacAlgorithm.cls_null); + + case CipherSuite.TLS_DHE_PSK_WITH_CAMELLIA_128_CBC_SHA256: + case CipherSuite.TLS_ECDHE_PSK_WITH_CAMELLIA_128_CBC_SHA256: + case CipherSuite.TLS_PSK_WITH_CAMELLIA_128_CBC_SHA256: + case CipherSuite.TLS_RSA_PSK_WITH_CAMELLIA_128_CBC_SHA256: + return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.CAMELLIA_128_CBC, MacAlgorithm.hmac_sha256); + + case CipherSuite.TLS_DHE_PSK_WITH_CAMELLIA_128_GCM_SHA256: + case CipherSuite.TLS_PSK_WITH_CAMELLIA_128_GCM_SHA256: + case CipherSuite.TLS_RSA_PSK_WITH_CAMELLIA_128_GCM_SHA256: + return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.CAMELLIA_128_GCM, MacAlgorithm.cls_null); + case CipherSuite.TLS_DHE_PSK_WITH_CAMELLIA_256_CBC_SHA384: + case CipherSuite.TLS_ECDHE_PSK_WITH_CAMELLIA_256_CBC_SHA384: + case CipherSuite.TLS_PSK_WITH_CAMELLIA_256_CBC_SHA384: + case CipherSuite.TLS_RSA_PSK_WITH_CAMELLIA_256_CBC_SHA384: + return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.CAMELLIA_256_CBC, MacAlgorithm.hmac_sha384); + + case CipherSuite.TLS_DHE_PSK_WITH_CAMELLIA_256_GCM_SHA384: + case CipherSuite.TLS_PSK_WITH_CAMELLIA_256_GCM_SHA384: + case CipherSuite.TLS_RSA_PSK_WITH_CAMELLIA_256_GCM_SHA384: + return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.CAMELLIA_256_GCM, MacAlgorithm.cls_null); + + case CipherSuite.TLS_DHE_PSK_WITH_ESTREAM_SALSA20_SHA1: + case CipherSuite.TLS_ECDHE_PSK_WITH_ESTREAM_SALSA20_SHA1: + case CipherSuite.TLS_PSK_WITH_ESTREAM_SALSA20_SHA1: + case CipherSuite.TLS_RSA_PSK_WITH_ESTREAM_SALSA20_SHA1: + return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.ESTREAM_SALSA20, MacAlgorithm.hmac_sha1); + + case CipherSuite.TLS_DHE_PSK_WITH_NULL_SHA: + case CipherSuite.TLS_ECDHE_PSK_WITH_NULL_SHA: + case CipherSuite.TLS_PSK_WITH_NULL_SHA: + case CipherSuite.TLS_RSA_PSK_WITH_NULL_SHA: + return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.NULL, MacAlgorithm.hmac_sha1); + + case CipherSuite.TLS_DHE_PSK_WITH_NULL_SHA256: + case CipherSuite.TLS_ECDHE_PSK_WITH_NULL_SHA256: + case CipherSuite.TLS_PSK_WITH_NULL_SHA256: + case CipherSuite.TLS_RSA_PSK_WITH_NULL_SHA256: + return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.NULL, MacAlgorithm.hmac_sha256); + + case CipherSuite.TLS_DHE_PSK_WITH_NULL_SHA384: + case CipherSuite.TLS_ECDHE_PSK_WITH_NULL_SHA384: + case CipherSuite.TLS_PSK_WITH_NULL_SHA384: + case CipherSuite.TLS_RSA_PSK_WITH_NULL_SHA384: + return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.NULL, MacAlgorithm.hmac_sha384); + + case CipherSuite.TLS_DHE_PSK_WITH_RC4_128_SHA: + case CipherSuite.TLS_ECDHE_PSK_WITH_RC4_128_SHA: case CipherSuite.TLS_PSK_WITH_RC4_128_SHA: case CipherSuite.TLS_RSA_PSK_WITH_RC4_128_SHA: - case CipherSuite.TLS_DHE_PSK_WITH_RC4_128_SHA: - return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.RC4_128, - MacAlgorithm.hmac_sha1); + return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.RC4_128, MacAlgorithm.hmac_sha1); + + case CipherSuite.TLS_DHE_PSK_WITH_SALSA20_SHA1: + case CipherSuite.TLS_ECDHE_PSK_WITH_SALSA20_SHA1: + case CipherSuite.TLS_PSK_WITH_SALSA20_SHA1: + case CipherSuite.TLS_RSA_PSK_WITH_SALSA20_SHA1: + return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.SALSA20, MacAlgorithm.hmac_sha1); default: /* - * Note: internal error here; the TlsProtocol implementation verifies that the - * server-selected cipher suite was in the list of client-offered cipher suites, so if - * we now can't produce an implementation, we shouldn't have offered it! - */ + * Note: internal error here; the TlsProtocol implementation verifies that the + * server-selected cipher suite was in the list of client-offered cipher suites, so if + * we now can't produce an implementation, we shouldn't have offered it! + */ throw new TlsFatalAlert(AlertDescription.internal_error); } } protected virtual TlsKeyExchange CreatePskKeyExchange(int keyExchange) { - return new TlsPskKeyExchange(mContext, keyExchange, mPskIdentity); + return new TlsPskKeyExchange(keyExchange, mSupportedSignatureAlgorithms, mPskIdentity, null, mNamedCurves, + mClientECPointFormats, mServerECPointFormats); } } } diff --git a/crypto/src/crypto/tls/SrpTlsClient.cs b/crypto/src/crypto/tls/SrpTlsClient.cs index a7c72b862..5d82ed470 100644 --- a/crypto/src/crypto/tls/SrpTlsClient.cs +++ b/crypto/src/crypto/tls/SrpTlsClient.cs @@ -24,9 +24,18 @@ namespace Org.BouncyCastle.Crypto.Tls this.mPassword = Arrays.Clone(password); } + protected virtual bool RequireSrpServerExtension + { + // No explicit guidance in RFC 5054; by default an (empty) extension from server is optional + get { return false; } + } + public override int[] GetCipherSuites() { - return new int[] { CipherSuite.TLS_SRP_SHA_RSA_WITH_AES_128_CBC_SHA }; + return new int[] + { + CipherSuite.TLS_SRP_SHA_RSA_WITH_AES_128_CBC_SHA + }; } public override IDictionary GetClientExtensions() @@ -41,7 +50,8 @@ namespace Org.BouncyCastle.Crypto.Tls if (!TlsUtilities.HasExpectedEmptyExtensionData(serverExtensions, ExtensionType.srp, AlertDescription.illegal_parameter)) { - // No explicit guidance in RFC 5054 here; we allow an optional empty extension from server + if (RequireSrpServerExtension) + throw new TlsFatalAlert(AlertDescription.illegal_parameter); } base.ProcessServerExtensions(serverExtensions); @@ -107,7 +117,7 @@ namespace Org.BouncyCastle.Crypto.Tls protected virtual TlsKeyExchange CreateSrpKeyExchange(int keyExchange) { - return new TlsSrpKeyExchange(mContext, keyExchange, mIdentity, mPassword); + return new TlsSrpKeyExchange(keyExchange, mSupportedSignatureAlgorithms, mIdentity, mPassword); } } } diff --git a/crypto/src/crypto/tls/TlsDHKeyExchange.cs b/crypto/src/crypto/tls/TlsDHKeyExchange.cs index ddc6a4527..b831249a6 100644 --- a/crypto/src/crypto/tls/TlsDHKeyExchange.cs +++ b/crypto/src/crypto/tls/TlsDHKeyExchange.cs @@ -1,75 +1,87 @@ using System; +using System.Collections; using System.IO; -using Org.BouncyCastle.Asn1; using Org.BouncyCastle.Asn1.X509; -using Org.BouncyCastle.Crypto; using Org.BouncyCastle.Crypto.Parameters; using Org.BouncyCastle.Security; namespace Org.BouncyCastle.Crypto.Tls { - /// <summary> - /// TLS 1.0 DH key exchange. - /// </summary> - internal class TlsDHKeyExchange - : TlsKeyExchange + /// <summary>(D)TLS DH key exchange.</summary> + public class TlsDHKeyExchange + : AbstractTlsKeyExchange { - protected TlsContext context; - protected int keyExchange; - protected TlsSigner tlsSigner; + protected TlsSigner mTlsSigner; + protected DHParameters mDHParameters; - protected AsymmetricKeyParameter serverPublicKey = null; - protected DHPublicKeyParameters dhAgreeServerPublicKey = null; - protected TlsAgreementCredentials agreementCredentials; - protected DHPrivateKeyParameters dhAgreeClientPrivateKey = null; + protected AsymmetricKeyParameter mServerPublicKey; + protected DHPublicKeyParameters mDHAgreeServerPublicKey; + protected TlsAgreementCredentials mAgreementCredentials; + protected DHPrivateKeyParameters mDHAgreeClientPrivateKey; - internal TlsDHKeyExchange(TlsContext context, int keyExchange) + protected DHPrivateKeyParameters mDHAgreeServerPrivateKey; + protected DHPublicKeyParameters mDHAgreeClientPublicKey; + + public TlsDHKeyExchange(int keyExchange, IList supportedSignatureAlgorithms, DHParameters dhParameters) + : base(keyExchange, supportedSignatureAlgorithms) { switch (keyExchange) { - case KeyExchangeAlgorithm.DH_RSA: - case KeyExchangeAlgorithm.DH_DSS: - this.tlsSigner = null; - break; - case KeyExchangeAlgorithm.DHE_RSA: - this.tlsSigner = new TlsRsaSigner(); - break; - case KeyExchangeAlgorithm.DHE_DSS: - this.tlsSigner = new TlsDssSigner(); - break; - default: - throw new ArgumentException("unsupported key exchange algorithm", "keyExchange"); + case KeyExchangeAlgorithm.DH_RSA: + case KeyExchangeAlgorithm.DH_DSS: + this.mTlsSigner = null; + break; + case KeyExchangeAlgorithm.DHE_RSA: + this.mTlsSigner = new TlsRsaSigner(); + break; + case KeyExchangeAlgorithm.DHE_DSS: + this.mTlsSigner = new TlsDssSigner(); + break; + default: + throw new InvalidOperationException("unsupported key exchange algorithm"); } - this.context = context; - this.keyExchange = keyExchange; + this.mDHParameters = dhParameters; + } + + public override void Init(TlsContext context) + { + base.Init(context); + + if (this.mTlsSigner != null) + { + this.mTlsSigner.Init(context); + } } - public virtual void SkipServerCertificate() + public override void SkipServerCredentials() { throw new TlsFatalAlert(AlertDescription.unexpected_message); } - public virtual void ProcessServerCertificate(Certificate serverCertificate) + public override void ProcessServerCertificate(Certificate serverCertificate) { + if (serverCertificate.IsEmpty) + throw new TlsFatalAlert(AlertDescription.bad_certificate); + X509CertificateStructure x509Cert = serverCertificate.GetCertificateAt(0); - SubjectPublicKeyInfo keyInfo = x509Cert.SubjectPublicKeyInfo; + SubjectPublicKeyInfo keyInfo = x509Cert.SubjectPublicKeyInfo; try { - this.serverPublicKey = PublicKeyFactory.CreateKey(keyInfo); + this.mServerPublicKey = PublicKeyFactory.CreateKey(keyInfo); } catch (Exception e) { throw new TlsFatalAlert(AlertDescription.unsupported_certificate, e); } - if (tlsSigner == null) + if (mTlsSigner == null) { try { - this.dhAgreeServerPublicKey = ValidateDHPublicKey((DHPublicKeyParameters)this.serverPublicKey); + this.mDHAgreeServerPublicKey = TlsDHUtilities.ValidateDHPublicKey((DHPublicKeyParameters)this.mServerPublicKey); } catch (InvalidCastException e) { @@ -80,7 +92,7 @@ namespace Org.BouncyCastle.Crypto.Tls } else { - if (!tlsSigner.IsValidPublicKey(this.serverPublicKey)) + if (!mTlsSigner.IsValidPublicKey(this.mServerPublicKey)) { throw new TlsFatalAlert(AlertDescription.certificate_unknown); } @@ -88,55 +100,51 @@ namespace Org.BouncyCastle.Crypto.Tls TlsUtilities.ValidateKeyUsage(x509Cert, KeyUsage.DigitalSignature); } - // TODO - /* - * Perform various checks per RFC2246 7.4.2: "Unless otherwise specified, the - * signing algorithm for the certificate must be the same as the algorithm for the - * certificate key." - */ - } - - public virtual void SkipServerKeyExchange() - { - // OK + base.ProcessServerCertificate(serverCertificate); } - public virtual void ProcessServerKeyExchange(Stream input) + public override bool RequiresServerKeyExchange { - throw new TlsFatalAlert(AlertDescription.unexpected_message); + get + { + switch (mKeyExchange) + { + case KeyExchangeAlgorithm.DHE_DSS: + case KeyExchangeAlgorithm.DHE_RSA: + case KeyExchangeAlgorithm.DH_anon: + return true; + default: + return false; + } + } } - public virtual void ValidateCertificateRequest(CertificateRequest certificateRequest) + public override void ValidateCertificateRequest(CertificateRequest certificateRequest) { byte[] types = certificateRequest.CertificateTypes; - foreach (byte type in types) + for (int i = 0; i < types.Length; ++i) { - switch (type) + switch (types[i]) { - case ClientCertificateType.rsa_sign: - case ClientCertificateType.dss_sign: - case ClientCertificateType.rsa_fixed_dh: - case ClientCertificateType.dss_fixed_dh: - case ClientCertificateType.ecdsa_sign: - break; - default: - throw new TlsFatalAlert(AlertDescription.illegal_parameter); + case ClientCertificateType.rsa_sign: + case ClientCertificateType.dss_sign: + case ClientCertificateType.rsa_fixed_dh: + case ClientCertificateType.dss_fixed_dh: + case ClientCertificateType.ecdsa_sign: + break; + default: + throw new TlsFatalAlert(AlertDescription.illegal_parameter); } } } - public virtual void SkipClientCredentials() - { - this.agreementCredentials = null; - } - - public virtual void ProcessClientCredentials(TlsCredentials clientCredentials) + public override void ProcessClientCredentials(TlsCredentials clientCredentials) { if (clientCredentials is TlsAgreementCredentials) { // TODO Validate client cert has matching parameters (see 'areCompatibleParameters')? - this.agreementCredentials = (TlsAgreementCredentials)clientCredentials; + this.mAgreementCredentials = (TlsAgreementCredentials)clientCredentials; } else if (clientCredentials is TlsSignerCredentials) { @@ -148,54 +156,38 @@ namespace Org.BouncyCastle.Crypto.Tls } } - public virtual void GenerateClientKeyExchange(Stream output) + public override void GenerateClientKeyExchange(Stream output) { /* - * RFC 2246 7.4.7.2 If the client certificate already contains a suitable - * Diffie-Hellman key, then Yc is implicit and does not need to be sent again. In - * this case, the Client Key Exchange message will be sent, but will be empty. + * RFC 2246 7.4.7.2 If the client certificate already contains a suitable Diffie-Hellman + * key, then Yc is implicit and does not need to be sent again. In this case, the Client Key + * Exchange message will be sent, but will be empty. */ - if (agreementCredentials == null) + if (mAgreementCredentials == null) { - GenerateEphemeralClientKeyExchange(dhAgreeServerPublicKey.Parameters, output); + this.mDHAgreeClientPrivateKey = TlsDHUtilities.GenerateEphemeralClientKeyExchange(context.SecureRandom, + mDHAgreeServerPublicKey.Parameters, output); } } - public virtual byte[] GeneratePremasterSecret() + public override byte[] GeneratePremasterSecret() { - if (agreementCredentials != null) + if (mAgreementCredentials != null) { - return agreementCredentials.GenerateAgreement(dhAgreeServerPublicKey); + return mAgreementCredentials.GenerateAgreement(mDHAgreeServerPublicKey); } - return CalculateDHBasicAgreement(dhAgreeServerPublicKey, dhAgreeClientPrivateKey); - } - - protected virtual bool AreCompatibleParameters(DHParameters a, DHParameters b) - { - return a.P.Equals(b.P) && a.G.Equals(b.G); - } - - protected virtual byte[] CalculateDHBasicAgreement(DHPublicKeyParameters publicKey, - DHPrivateKeyParameters privateKey) - { - return TlsDHUtilities.CalculateDHBasicAgreement(publicKey, privateKey); - } - - protected virtual AsymmetricCipherKeyPair GenerateDHKeyPair(DHParameters dhParams) - { - return TlsDHUtilities.GenerateDHKeyPair(context.SecureRandom, dhParams); - } + if (mDHAgreeServerPrivateKey != null) + { + return TlsDHUtilities.CalculateDHBasicAgreement(mDHAgreeClientPublicKey, mDHAgreeServerPrivateKey); + } - protected virtual void GenerateEphemeralClientKeyExchange(DHParameters dhParams, Stream output) - { - this.dhAgreeClientPrivateKey = TlsDHUtilities.GenerateEphemeralClientKeyExchange( - context.SecureRandom, dhParams, output); - } + if (mDHAgreeClientPrivateKey != null) + { + return TlsDHUtilities.CalculateDHBasicAgreement(mDHAgreeServerPublicKey, mDHAgreeClientPrivateKey); + } - protected virtual DHPublicKeyParameters ValidateDHPublicKey(DHPublicKeyParameters key) - { - return TlsDHUtilities.ValidateDHPublicKey(key); + throw new TlsFatalAlert(AlertDescription.internal_error); } } } diff --git a/crypto/src/crypto/tls/TlsDheKeyExchange.cs b/crypto/src/crypto/tls/TlsDheKeyExchange.cs index a9e9a394c..3c05bb6f0 100644 --- a/crypto/src/crypto/tls/TlsDheKeyExchange.cs +++ b/crypto/src/crypto/tls/TlsDheKeyExchange.cs @@ -1,53 +1,102 @@ using System; +using System.Collections; using System.IO; -using Org.BouncyCastle.Crypto.IO; using Org.BouncyCastle.Crypto.Parameters; using Org.BouncyCastle.Math; +using Org.BouncyCastle.Security; +using Org.BouncyCastle.Utilities.IO; namespace Org.BouncyCastle.Crypto.Tls { - internal class TlsDheKeyExchange - : TlsDHKeyExchange + public class TlsDheKeyExchange + : TlsDHKeyExchange { - internal TlsDheKeyExchange(TlsContext context, int keyExchange) - : base(context, keyExchange) + protected TlsSignerCredentials mServerCredentials = null; + + public TlsDheKeyExchange(int keyExchange, IList supportedSignatureAlgorithms, DHParameters dhParameters) + : base(keyExchange, supportedSignatureAlgorithms, dhParameters) { } - public override void SkipServerKeyExchange() + public override void ProcessServerCredentials(TlsCredentials serverCredentials) { - throw new TlsFatalAlert(AlertDescription.unexpected_message); + if (!(serverCredentials is TlsSignerCredentials)) + throw new TlsFatalAlert(AlertDescription.internal_error); + + ProcessServerCertificate(serverCredentials.Certificate); + + this.mServerCredentials = (TlsSignerCredentials)serverCredentials; } - public override void ProcessServerKeyExchange(Stream input) + public override byte[] GenerateServerKeyExchange() { - SecurityParameters securityParameters = context.SecurityParameters; + if (this.mDHParameters == null) + throw new TlsFatalAlert(AlertDescription.internal_error); + + DigestInputBuffer buf = new DigestInputBuffer(); - ISigner signer = InitSigner(tlsSigner, securityParameters); - Stream sigIn = new SignerStream(input, signer, null); + this.mDHAgreeServerPrivateKey = TlsDHUtilities.GenerateEphemeralServerKeyExchange(context.SecureRandom, + this.mDHParameters, buf); - byte[] pBytes = TlsUtilities.ReadOpaque16(sigIn); - byte[] gBytes = TlsUtilities.ReadOpaque16(sigIn); - byte[] YsBytes = TlsUtilities.ReadOpaque16(sigIn); + /* + * RFC 5246 4.7. digitally-signed element needs SignatureAndHashAlgorithm from TLS 1.2 + */ + SignatureAndHashAlgorithm signatureAndHashAlgorithm; + IDigest d; - byte[] sigByte = TlsUtilities.ReadOpaque16(input); - if (!signer.VerifySignature(sigByte)) + if (TlsUtilities.IsTlsV12(context)) { - throw new TlsFatalAlert(AlertDescription.decrypt_error); + signatureAndHashAlgorithm = mServerCredentials.SignatureAndHashAlgorithm; + if (signatureAndHashAlgorithm == null) + throw new TlsFatalAlert(AlertDescription.internal_error); + + d = TlsUtilities.CreateHash(signatureAndHashAlgorithm.Hash); + } + else + { + signatureAndHashAlgorithm = null; + d = new CombinedHash(); } - BigInteger p = new BigInteger(1, pBytes); - BigInteger g = new BigInteger(1, gBytes); - BigInteger Ys = new BigInteger(1, YsBytes); + SecurityParameters securityParameters = context.SecurityParameters; + d.BlockUpdate(securityParameters.clientRandom, 0, securityParameters.clientRandom.Length); + d.BlockUpdate(securityParameters.serverRandom, 0, securityParameters.serverRandom.Length); + buf.UpdateDigest(d); + + byte[] hash = DigestUtilities.DoFinal(d); + + byte[] signature = mServerCredentials.GenerateCertificateSignature(hash); + + DigitallySigned signed_params = new DigitallySigned(signatureAndHashAlgorithm, signature); + signed_params.Encode(buf); + + return buf.ToArray(); + } + + public override void ProcessServerKeyExchange(Stream input) + { + SecurityParameters securityParameters = context.SecurityParameters; + + SignerInputBuffer buf = new SignerInputBuffer(); + Stream teeIn = new TeeInputStream(input, buf); + + ServerDHParams dhParams = ServerDHParams.Parse(teeIn); + + DigitallySigned signed_params = DigitallySigned.Parse(context, input); + + ISigner signer = InitVerifyer(mTlsSigner, signed_params.Algorithm, securityParameters); + buf.UpdateSigner(signer); + if (!signer.VerifySignature(signed_params.Signature)) + throw new TlsFatalAlert(AlertDescription.decrypt_error); - this.dhAgreeServerPublicKey = ValidateDHPublicKey( - new DHPublicKeyParameters(Ys, new DHParameters(p, g))); + this.mDHAgreeServerPublicKey = TlsDHUtilities.ValidateDHPublicKey(dhParams.PublicKey); } - protected virtual ISigner InitSigner(TlsSigner tlsSigner, SecurityParameters securityParameters) + protected virtual ISigner InitVerifyer(TlsSigner tlsSigner, SignatureAndHashAlgorithm algorithm, + SecurityParameters securityParameters) { - ISigner signer = tlsSigner.CreateVerifyer(this.serverPublicKey); + ISigner signer = tlsSigner.CreateVerifyer(algorithm, this.mServerPublicKey); signer.BlockUpdate(securityParameters.clientRandom, 0, securityParameters.clientRandom.Length); signer.BlockUpdate(securityParameters.serverRandom, 0, securityParameters.serverRandom.Length); return signer; diff --git a/crypto/src/crypto/tls/TlsECDHKeyExchange.cs b/crypto/src/crypto/tls/TlsECDHKeyExchange.cs index c4780eaaa..42dc2f2ef 100644 --- a/crypto/src/crypto/tls/TlsECDHKeyExchange.cs +++ b/crypto/src/crypto/tls/TlsECDHKeyExchange.cs @@ -3,76 +3,87 @@ using System.Collections; using System.IO; using Org.BouncyCastle.Asn1.X509; -using Org.BouncyCastle.Crypto.Agreement; -using Org.BouncyCastle.Crypto.Generators; using Org.BouncyCastle.Crypto.Parameters; -using Org.BouncyCastle.Math; using Org.BouncyCastle.Security; -using Org.BouncyCastle.Utilities; namespace Org.BouncyCastle.Crypto.Tls { - /** - * ECDH key exchange (see RFC 4492) - */ - internal class TlsECDHKeyExchange - : TlsKeyExchange + /// <summary>(D)TLS ECDH key exchange (see RFC 4492).</summary> + public class TlsECDHKeyExchange + : AbstractTlsKeyExchange { - protected TlsContext context; - protected int keyExchange; - protected TlsSigner tlsSigner; + protected TlsSigner mTlsSigner; + protected int[] mNamedCurves; + protected byte[] mClientECPointFormats, mServerECPointFormats; - protected AsymmetricKeyParameter serverPublicKey; - protected ECPublicKeyParameters ecAgreeServerPublicKey; - protected TlsAgreementCredentials agreementCredentials; - protected ECPrivateKeyParameters ecAgreeClientPrivateKey = null; + protected AsymmetricKeyParameter mServerPublicKey; + protected TlsAgreementCredentials mAgreementCredentials; - internal TlsECDHKeyExchange(TlsContext context, int keyExchange) + protected ECPrivateKeyParameters mECAgreePrivateKey; + protected ECPublicKeyParameters mECAgreePublicKey; + + public TlsECDHKeyExchange(int keyExchange, IList supportedSignatureAlgorithms, int[] namedCurves, + byte[] clientECPointFormats, byte[] serverECPointFormats) + : base(keyExchange, supportedSignatureAlgorithms) { switch (keyExchange) { - case KeyExchangeAlgorithm.ECDHE_RSA: - this.tlsSigner = new TlsRsaSigner(); - break; - case KeyExchangeAlgorithm.ECDHE_ECDSA: - this.tlsSigner = new TlsECDsaSigner(); - break; - case KeyExchangeAlgorithm.ECDH_RSA: - case KeyExchangeAlgorithm.ECDH_ECDSA: - this.tlsSigner = null; - break; - default: - throw new ArgumentException("unsupported key exchange algorithm", "keyExchange"); + case KeyExchangeAlgorithm.ECDHE_RSA: + this.mTlsSigner = new TlsRsaSigner(); + break; + case KeyExchangeAlgorithm.ECDHE_ECDSA: + this.mTlsSigner = new TlsECDsaSigner(); + break; + case KeyExchangeAlgorithm.ECDH_RSA: + case KeyExchangeAlgorithm.ECDH_ECDSA: + this.mTlsSigner = null; + break; + default: + throw new InvalidOperationException("unsupported key exchange algorithm"); } - this.context = context; - this.keyExchange = keyExchange; + this.mNamedCurves = namedCurves; + this.mClientECPointFormats = clientECPointFormats; + this.mServerECPointFormats = serverECPointFormats; } - public virtual void SkipServerCertificate() + public override void Init(TlsContext context) + { + base.Init(context); + + if (this.mTlsSigner != null) + { + this.mTlsSigner.Init(context); + } + } + + public override void SkipServerCredentials() { throw new TlsFatalAlert(AlertDescription.unexpected_message); } - public virtual void ProcessServerCertificate(Certificate serverCertificate) + public override void ProcessServerCertificate(Certificate serverCertificate) { + if (serverCertificate.IsEmpty) + throw new TlsFatalAlert(AlertDescription.bad_certificate); + X509CertificateStructure x509Cert = serverCertificate.GetCertificateAt(0); - SubjectPublicKeyInfo keyInfo = x509Cert.SubjectPublicKeyInfo; + SubjectPublicKeyInfo keyInfo = x509Cert.SubjectPublicKeyInfo; try { - this.serverPublicKey = PublicKeyFactory.CreateKey(keyInfo); + this.mServerPublicKey = PublicKeyFactory.CreateKey(keyInfo); } catch (Exception e) { throw new TlsFatalAlert(AlertDescription.unsupported_certificate, e); } - if (tlsSigner == null) + if (mTlsSigner == null) { try { - this.ecAgreeServerPublicKey = ValidateECPublicKey((ECPublicKeyParameters)this.serverPublicKey); + this.mECAgreePublicKey = TlsEccUtilities.ValidateECPublicKey((ECPublicKeyParameters) this.mServerPublicKey); } catch (InvalidCastException e) { @@ -83,69 +94,63 @@ namespace Org.BouncyCastle.Crypto.Tls } else { - if (!tlsSigner.IsValidPublicKey(this.serverPublicKey)) - { + if (!mTlsSigner.IsValidPublicKey(this.mServerPublicKey)) throw new TlsFatalAlert(AlertDescription.certificate_unknown); - } TlsUtilities.ValidateKeyUsage(x509Cert, KeyUsage.DigitalSignature); } - - // TODO - /* - * Perform various checks per RFC2246 7.4.2: "Unless otherwise specified, the - * signing algorithm for the certificate must be the same as the algorithm for the - * certificate key." - */ - } - - public virtual void SkipServerKeyExchange() - { - // do nothing + + base.ProcessServerCertificate(serverCertificate); } - public virtual void ProcessServerKeyExchange(Stream input) + public override bool RequiresServerKeyExchange { - throw new TlsFatalAlert(AlertDescription.unexpected_message); + get + { + switch (mKeyExchange) + { + case KeyExchangeAlgorithm.ECDHE_ECDSA: + case KeyExchangeAlgorithm.ECDHE_RSA: + case KeyExchangeAlgorithm.ECDH_anon: + return true; + default: + return false; + } + } } - public virtual void ValidateCertificateRequest(CertificateRequest certificateRequest) + public override void ValidateCertificateRequest(CertificateRequest certificateRequest) { /* - * RFC 4492 3. [...] The ECDSA_fixed_ECDH and RSA_fixed_ECDH mechanisms are usable - * with ECDH_ECDSA and ECDH_RSA. Their use with ECDHE_ECDSA and ECDHE_RSA is - * prohibited because the use of a long-term ECDH client key would jeopardize the - * forward secrecy property of these algorithms. + * RFC 4492 3. [...] The ECDSA_fixed_ECDH and RSA_fixed_ECDH mechanisms are usable with + * ECDH_ECDSA and ECDH_RSA. Their use with ECDHE_ECDSA and ECDHE_RSA is prohibited because + * the use of a long-term ECDH client key would jeopardize the forward secrecy property of + * these algorithms. */ byte[] types = certificateRequest.CertificateTypes; - foreach (byte type in types) + for (int i = 0; i < types.Length; ++i) { - switch (type) + switch (types[i]) { - case ClientCertificateType.rsa_sign: - case ClientCertificateType.dss_sign: - case ClientCertificateType.ecdsa_sign: - case ClientCertificateType.rsa_fixed_ecdh: - case ClientCertificateType.ecdsa_fixed_ecdh: - break; - default: - throw new TlsFatalAlert(AlertDescription.illegal_parameter); + case ClientCertificateType.rsa_sign: + case ClientCertificateType.dss_sign: + case ClientCertificateType.ecdsa_sign: + case ClientCertificateType.rsa_fixed_ecdh: + case ClientCertificateType.ecdsa_fixed_ecdh: + break; + default: + throw new TlsFatalAlert(AlertDescription.illegal_parameter); } } } - public virtual void SkipClientCredentials() - { - this.agreementCredentials = null; - } - - public virtual void ProcessClientCredentials(TlsCredentials clientCredentials) + public override void ProcessClientCredentials(TlsCredentials clientCredentials) { if (clientCredentials is TlsAgreementCredentials) { - // TODO Validate client cert has matching parameters (see 'AreOnSameCurve')? + // TODO Validate client cert has matching parameters (see 'TlsEccUtilities.AreOnSameCurve')? - this.agreementCredentials = (TlsAgreementCredentials)clientCredentials; + this.mAgreementCredentials = (TlsAgreementCredentials)clientCredentials; } else if (clientCredentials is TlsSignerCredentials) { @@ -157,80 +162,50 @@ namespace Org.BouncyCastle.Crypto.Tls } } - public virtual void GenerateClientKeyExchange(Stream output) + public override void GenerateClientKeyExchange(Stream output) { - if (agreementCredentials == null) + if (mAgreementCredentials == null) { - GenerateEphemeralClientKeyExchange(ecAgreeServerPublicKey.Parameters, output); + this.mECAgreePrivateKey = TlsEccUtilities.GenerateEphemeralClientKeyExchange(context.SecureRandom, + mServerECPointFormats, mECAgreePublicKey.Parameters, output); } } - public virtual byte[] GeneratePremasterSecret() + public override void ProcessClientCertificate(Certificate clientCertificate) { - if (agreementCredentials != null) - { - return agreementCredentials.GenerateAgreement(ecAgreeServerPublicKey); - } - - return CalculateECDHBasicAgreement(ecAgreeServerPublicKey, ecAgreeClientPrivateKey); - } - - protected virtual bool AreOnSameCurve(ECDomainParameters a, ECDomainParameters b) - { - // TODO Move to ECDomainParameters.Equals() or other utility method? - return a.Curve.Equals(b.Curve) && a.G.Equals(b.G) && a.N.Equals(b.N) && a.H.Equals(b.H); + // TODO Extract the public key + // TODO If the certificate is 'fixed', take the public key as mECAgreeClientPublicKey } - protected virtual byte[] ExternalizeKey(ECPublicKeyParameters keyParameters) + public override void ProcessClientKeyExchange(Stream input) { - // TODO Add support for compressed encoding and SPF extension - - /* - * RFC 4492 5.7. ...an elliptic curve point in uncompressed or compressed format. - * Here, the format MUST conform to what the server has requested through a - * Supported Point Formats Extension if this extension was used, and MUST be - * uncompressed if this extension was not used. - */ - return keyParameters.Q.GetEncoded(); - } + if (mECAgreePublicKey != null) + { + // For ecdsa_fixed_ecdh and rsa_fixed_ecdh, the key arrived in the client certificate + return; + } - protected virtual AsymmetricCipherKeyPair GenerateECKeyPair(ECDomainParameters ecParams) - { - ECKeyPairGenerator keyPairGenerator = new ECKeyPairGenerator(); - ECKeyGenerationParameters keyGenerationParameters = new ECKeyGenerationParameters(ecParams, - context.SecureRandom); - keyPairGenerator.Init(keyGenerationParameters); - return keyPairGenerator.GenerateKeyPair(); - } + byte[] point = TlsUtilities.ReadOpaque8(input); - protected virtual void GenerateEphemeralClientKeyExchange(ECDomainParameters ecParams, Stream output) - { - AsymmetricCipherKeyPair ecAgreeClientKeyPair = GenerateECKeyPair(ecParams); - this.ecAgreeClientPrivateKey = (ECPrivateKeyParameters)ecAgreeClientKeyPair.Private; + ECDomainParameters curve_params = this.mECAgreePrivateKey.Parameters; - byte[] keData = ExternalizeKey((ECPublicKeyParameters)ecAgreeClientKeyPair.Public); - TlsUtilities.WriteOpaque8(keData, output); + this.mECAgreePublicKey = TlsEccUtilities.ValidateECPublicKey(TlsEccUtilities.DeserializeECPublicKey( + mServerECPointFormats, curve_params, point)); } - protected virtual byte[] CalculateECDHBasicAgreement(ECPublicKeyParameters publicKey, - ECPrivateKeyParameters privateKey) + public override byte[] GeneratePremasterSecret() { - ECDHBasicAgreement basicAgreement = new ECDHBasicAgreement(); - basicAgreement.Init(privateKey); - BigInteger agreementValue = basicAgreement.CalculateAgreement(publicKey); + if (mAgreementCredentials != null) + { + return mAgreementCredentials.GenerateAgreement(mECAgreePublicKey); + } - /* - * RFC 4492 5.10. Note that this octet string (Z in IEEE 1363 terminology) as output by - * FE2OSP, the Field Element to Octet String Conversion Primitive, has constant length for - * any given field; leading zeros found in this octet string MUST NOT be truncated. - */ - return BigIntegers.AsUnsignedByteArray(basicAgreement.GetFieldSize(), agreementValue); - } + if (mECAgreePrivateKey != null) + { + return TlsEccUtilities.CalculateECDHBasicAgreement(mECAgreePublicKey, mECAgreePrivateKey); + } - protected virtual ECPublicKeyParameters ValidateECPublicKey(ECPublicKeyParameters key) - { - // TODO Check RFC 4492 for validation - return key; + throw new TlsFatalAlert(AlertDescription.internal_error); } } } diff --git a/crypto/src/crypto/tls/TlsECDheKeyExchange.cs b/crypto/src/crypto/tls/TlsECDheKeyExchange.cs index 5f66dbf59..0644bd44d 100644 --- a/crypto/src/crypto/tls/TlsECDheKeyExchange.cs +++ b/crypto/src/crypto/tls/TlsECDheKeyExchange.cs @@ -2,91 +2,186 @@ using System; using System.Collections; using System.IO; -using Org.BouncyCastle.Crypto.IO; using Org.BouncyCastle.Crypto.Parameters; using Org.BouncyCastle.Math.EC; +using Org.BouncyCastle.Security; +using Org.BouncyCastle.Utilities; +using Org.BouncyCastle.Utilities.IO; namespace Org.BouncyCastle.Crypto.Tls { - /** - * ECDHE key exchange (see RFC 4492) - */ - internal class TlsECDheKeyExchange : TlsECDHKeyExchange + /// <summary>(D)TLS ECDHE key exchange (see RFC 4492).</summary> + public class TlsECDheKeyExchange + : TlsECDHKeyExchange { - internal TlsECDheKeyExchange(TlsContext context, int keyExchange) - : base(context, keyExchange) - { - } + protected TlsSignerCredentials mServerCredentials = null; - public override void SkipServerKeyExchange() + public TlsECDheKeyExchange(int keyExchange, IList supportedSignatureAlgorithms, int[] namedCurves, + byte[] clientECPointFormats, byte[] serverECPointFormats) + : base(keyExchange, supportedSignatureAlgorithms, namedCurves, clientECPointFormats, serverECPointFormats) { - throw new TlsFatalAlert(AlertDescription.unexpected_message); } - public override void ProcessServerKeyExchange(Stream input) + public override void ProcessServerCredentials(TlsCredentials serverCredentials) { - SecurityParameters securityParameters = context.SecurityParameters; + if (!(serverCredentials is TlsSignerCredentials)) + throw new TlsFatalAlert(AlertDescription.internal_error); - ISigner signer = InitSigner(tlsSigner, securityParameters); - Stream sigIn = new SignerStream(input, signer, null); + ProcessServerCertificate(serverCredentials.Certificate); - byte curveType = TlsUtilities.ReadUint8(sigIn); - ECDomainParameters curve_params; + this.mServerCredentials = (TlsSignerCredentials)serverCredentials; + } - // Currently, we only support named curves - if (curveType == ECCurveType.named_curve) + public override byte[] GenerateServerKeyExchange() + { + /* + * First we try to find a supported named curve from the client's list. + */ + int namedCurve = -1; + if (mNamedCurves == null) { - int namedCurve = TlsUtilities.ReadUint16(sigIn); - - // TODO Check namedCurve is one we offered? + // TODO Let the peer choose the default named curve + namedCurve = NamedCurve.secp256r1; + } + else + { + for (int i = 0; i < mNamedCurves.Length; ++i) + { + int entry = mNamedCurves[i]; + if (NamedCurve.IsValid(entry) && TlsEccUtilities.IsSupportedNamedCurve(entry)) + { + namedCurve = entry; + break; + } + } + } + ECDomainParameters curve_params = null; + if (namedCurve >= 0) + { curve_params = TlsEccUtilities.GetParametersForNamedCurve(namedCurve); } else { - // TODO Add support for explicit curve parameters (read from sigIn) + /* + * If no named curves are suitable, check if the client supports explicit curves. + */ + if (Arrays.Contains(mNamedCurves, NamedCurve.arbitrary_explicit_prime_curves)) + { + curve_params = TlsEccUtilities.GetParametersForNamedCurve(NamedCurve.secp256r1); + } + else if (Arrays.Contains(mNamedCurves, NamedCurve.arbitrary_explicit_char2_curves)) + { + curve_params = TlsEccUtilities.GetParametersForNamedCurve(NamedCurve.sect283r1); + } + } - throw new TlsFatalAlert(AlertDescription.handshake_failure); + if (curve_params == null) + { + /* + * NOTE: We shouldn't have negotiated ECDHE key exchange since we apparently can't find + * a suitable curve. + */ + throw new TlsFatalAlert(AlertDescription.internal_error); } - byte[] publicBytes = TlsUtilities.ReadOpaque8(sigIn); + AsymmetricCipherKeyPair kp = TlsEccUtilities.GenerateECKeyPair(context.SecureRandom, curve_params); + this.mECAgreePrivateKey = (ECPrivateKeyParameters)kp.Private; - byte[] sigByte = TlsUtilities.ReadOpaque16(input); - if (!signer.VerifySignature(sigByte)) + DigestInputBuffer buf = new DigestInputBuffer(); + + if (namedCurve < 0) { - throw new TlsFatalAlert(AlertDescription.decrypt_error); + TlsEccUtilities.WriteExplicitECParameters(mClientECPointFormats, curve_params, buf); + } + else + { + TlsEccUtilities.WriteNamedECParameters(namedCurve, buf); } - // TODO Check curve_params not null + ECPublicKeyParameters ecPublicKey = (ECPublicKeyParameters)kp.Public; + TlsEccUtilities.WriteECPoint(mClientECPointFormats, ecPublicKey.Q, buf); - ECPoint Q = curve_params.Curve.DecodePoint(publicBytes); + /* + * RFC 5246 4.7. digitally-signed element needs SignatureAndHashAlgorithm from TLS 1.2 + */ + SignatureAndHashAlgorithm signatureAndHashAlgorithm; + IDigest d; + + if (TlsUtilities.IsTlsV12(context)) + { + signatureAndHashAlgorithm = mServerCredentials.SignatureAndHashAlgorithm; + if (signatureAndHashAlgorithm == null) + throw new TlsFatalAlert(AlertDescription.internal_error); - this.ecAgreeServerPublicKey = ValidateECPublicKey(new ECPublicKeyParameters(Q, curve_params)); + d = TlsUtilities.CreateHash(signatureAndHashAlgorithm.Hash); + } + else + { + signatureAndHashAlgorithm = null; + d = new CombinedHash(); + } + + SecurityParameters securityParameters = context.SecurityParameters; + d.BlockUpdate(securityParameters.clientRandom, 0, securityParameters.clientRandom.Length); + d.BlockUpdate(securityParameters.serverRandom, 0, securityParameters.serverRandom.Length); + buf.UpdateDigest(d); + + byte[] hash = DigestUtilities.DoFinal(d); + + byte[] signature = mServerCredentials.GenerateCertificateSignature(hash); + + DigitallySigned signed_params = new DigitallySigned(signatureAndHashAlgorithm, signature); + signed_params.Encode(buf); + + return buf.ToArray(); } - + + public override void ProcessServerKeyExchange(Stream input) + { + SecurityParameters securityParameters = context.SecurityParameters; + + SignerInputBuffer buf = new SignerInputBuffer(); + Stream teeIn = new TeeInputStream(input, buf); + + ECDomainParameters curve_params = TlsEccUtilities.ReadECParameters(mNamedCurves, mClientECPointFormats, teeIn); + + byte[] point = TlsUtilities.ReadOpaque8(teeIn); + + DigitallySigned signed_params = DigitallySigned.Parse(context, input); + + ISigner signer = InitVerifyer(mTlsSigner, signed_params.Algorithm, securityParameters); + buf.UpdateSigner(signer); + if (!signer.VerifySignature(signed_params.Signature)) + throw new TlsFatalAlert(AlertDescription.decrypt_error); + + this.mECAgreePublicKey = TlsEccUtilities.ValidateECPublicKey(TlsEccUtilities.DeserializeECPublicKey( + mClientECPointFormats, curve_params, point)); + } + public override void ValidateCertificateRequest(CertificateRequest certificateRequest) { /* - * RFC 4492 3. [...] The ECDSA_fixed_ECDH and RSA_fixed_ECDH mechanisms are usable - * with ECDH_ECDSA and ECDH_RSA. Their use with ECDHE_ECDSA and ECDHE_RSA is - * prohibited because the use of a long-term ECDH client key would jeopardize the - * forward secrecy property of these algorithms. + * RFC 4492 3. [...] The ECDSA_fixed_ECDH and RSA_fixed_ECDH mechanisms are usable with + * ECDH_ECDSA and ECDH_RSA. Their use with ECDHE_ECDSA and ECDHE_RSA is prohibited because + * the use of a long-term ECDH client key would jeopardize the forward secrecy property of + * these algorithms. */ byte[] types = certificateRequest.CertificateTypes; - foreach (byte type in types) + for (int i = 0; i < types.Length; ++i) { - switch (type) + switch (types[i]) { - case ClientCertificateType.rsa_sign: - case ClientCertificateType.dss_sign: - case ClientCertificateType.ecdsa_sign: - break; - default: - throw new TlsFatalAlert(AlertDescription.illegal_parameter); + case ClientCertificateType.rsa_sign: + case ClientCertificateType.dss_sign: + case ClientCertificateType.ecdsa_sign: + break; + default: + throw new TlsFatalAlert(AlertDescription.illegal_parameter); } } } - + public override void ProcessClientCredentials(TlsCredentials clientCredentials) { if (clientCredentials is TlsSignerCredentials) @@ -99,9 +194,10 @@ namespace Org.BouncyCastle.Crypto.Tls } } - protected virtual ISigner InitSigner(TlsSigner tlsSigner, SecurityParameters securityParameters) + protected virtual ISigner InitVerifyer(TlsSigner tlsSigner, SignatureAndHashAlgorithm algorithm, + SecurityParameters securityParameters) { - ISigner signer = tlsSigner.CreateVerifyer(this.serverPublicKey); + ISigner signer = tlsSigner.CreateVerifyer(algorithm, this.mServerPublicKey); signer.BlockUpdate(securityParameters.clientRandom, 0, securityParameters.clientRandom.Length); signer.BlockUpdate(securityParameters.serverRandom, 0, securityParameters.serverRandom.Length); return signer; diff --git a/crypto/src/crypto/tls/TlsKeyExchange.cs b/crypto/src/crypto/tls/TlsKeyExchange.cs index 5102edbec..6731f6f63 100644 --- a/crypto/src/crypto/tls/TlsKeyExchange.cs +++ b/crypto/src/crypto/tls/TlsKeyExchange.cs @@ -3,36 +3,52 @@ using System.IO; namespace Org.BouncyCastle.Crypto.Tls { - /// <summary> - /// A generic interface for key exchange implementations in TLS 1.0. - /// </summary> - public interface TlsKeyExchange - { - /// <exception cref="IOException"/> - void SkipServerCertificate(); - - /// <exception cref="IOException"/> - void ProcessServerCertificate(Certificate serverCertificate); - - /// <exception cref="IOException"/> - void SkipServerKeyExchange(); - - /// <exception cref="IOException"/> - void ProcessServerKeyExchange(Stream input); - - /// <exception cref="IOException"/> - void ValidateCertificateRequest(CertificateRequest certificateRequest); - - /// <exception cref="IOException"/> - void SkipClientCredentials(); - - /// <exception cref="IOException"/> - void ProcessClientCredentials(TlsCredentials clientCredentials); - - /// <exception cref="IOException"/> - void GenerateClientKeyExchange(Stream output); - - /// <exception cref="IOException"/> - byte[] GeneratePremasterSecret(); - } + /// <summary> + /// A generic interface for key exchange implementations in (D)TLS. + /// </summary> + public interface TlsKeyExchange + { + void Init(TlsContext context); + + /// <exception cref="IOException"/> + void SkipServerCredentials(); + + /// <exception cref="IOException"/> + void ProcessServerCredentials(TlsCredentials serverCredentials); + + /// <exception cref="IOException"/> + void ProcessServerCertificate(Certificate serverCertificate); + + bool RequiresServerKeyExchange { get; } + + /// <exception cref="IOException"/> + byte[] GenerateServerKeyExchange(); + + /// <exception cref="IOException"/> + void SkipServerKeyExchange(); + + /// <exception cref="IOException"/> + void ProcessServerKeyExchange(Stream input); + + /// <exception cref="IOException"/> + void ValidateCertificateRequest(CertificateRequest certificateRequest); + + /// <exception cref="IOException"/> + void SkipClientCredentials(); + + /// <exception cref="IOException"/> + void ProcessClientCredentials(TlsCredentials clientCredentials); + + /// <exception cref="IOException"/> + void ProcessClientCertificate(Certificate clientCertificate); + + /// <exception cref="IOException"/> + void GenerateClientKeyExchange(Stream output); + + /// <exception cref="IOException"/> + void ProcessClientKeyExchange(Stream input); + + /// <exception cref="IOException"/> + byte[] GeneratePremasterSecret(); + } } diff --git a/crypto/src/crypto/tls/TlsProtocolHandler.cs b/crypto/src/crypto/tls/TlsProtocolHandler.cs index 3dec5ade0..21b3c8d47 100644 --- a/crypto/src/crypto/tls/TlsProtocolHandler.cs +++ b/crypto/src/crypto/tls/TlsProtocolHandler.cs @@ -486,7 +486,7 @@ namespace Org.BouncyCastle.Crypto.Tls if (connection_state == CS_SERVER_HELLO_RECEIVED) { // There was no server certificate message; check it's OK - this.keyExchange.SkipServerCertificate(); + this.keyExchange.SkipServerCredentials(); this.authentication = null; // There was no server key exchange message; check it's OK @@ -605,7 +605,7 @@ namespace Org.BouncyCastle.Crypto.Tls if (connection_state == CS_SERVER_HELLO_RECEIVED) { // There was no server certificate message; check it's OK - this.keyExchange.SkipServerCertificate(); + this.keyExchange.SkipServerCredentials(); this.authentication = null; } diff --git a/crypto/src/crypto/tls/TlsPskKeyExchange.cs b/crypto/src/crypto/tls/TlsPskKeyExchange.cs index 24bf433dd..cd13e3438 100644 --- a/crypto/src/crypto/tls/TlsPskKeyExchange.cs +++ b/crypto/src/crypto/tls/TlsPskKeyExchange.cs @@ -1,68 +1,118 @@ using System; +using System.Collections; using System.IO; using Org.BouncyCastle.Asn1.X509; using Org.BouncyCastle.Crypto.Parameters; -using Org.BouncyCastle.Math; using Org.BouncyCastle.Security; namespace Org.BouncyCastle.Crypto.Tls { - internal class TlsPskKeyExchange - : TlsKeyExchange + /// <summary>(D)TLS PSK key exchange (RFC 4279).</summary> + public class TlsPskKeyExchange + : AbstractTlsKeyExchange { - protected TlsContext context; - protected int keyExchange; - protected TlsPskIdentity pskIdentity; + protected TlsPskIdentity mPskIdentity; + protected DHParameters mDHParameters; + protected int[] mNamedCurves; + protected byte[] mClientECPointFormats, mServerECPointFormats; - protected byte[] psk_identity_hint = null; + protected byte[] mPskIdentityHint = null; - protected DHPublicKeyParameters dhAgreeServerPublicKey = null; - protected DHPrivateKeyParameters dhAgreeClientPrivateKey = null; + protected DHPrivateKeyParameters mDHAgreePrivateKey = null; + protected DHPublicKeyParameters mDHAgreePublicKey = null; - protected AsymmetricKeyParameter serverPublicKey = null; - protected RsaKeyParameters rsaServerPublicKey = null; - protected byte[] premasterSecret; + protected AsymmetricKeyParameter mServerPublicKey = null; + protected RsaKeyParameters mRsaServerPublicKey = null; + protected TlsEncryptionCredentials mServerCredentials = null; + protected byte[] mPremasterSecret; - internal TlsPskKeyExchange(TlsContext context, int keyExchange, - TlsPskIdentity pskIdentity) + public TlsPskKeyExchange(int keyExchange, IList supportedSignatureAlgorithms, TlsPskIdentity pskIdentity, + DHParameters dhParameters, int[] namedCurves, byte[] clientECPointFormats, byte[] serverECPointFormats) + : base(keyExchange, supportedSignatureAlgorithms) { switch (keyExchange) { - case KeyExchangeAlgorithm.PSK: - case KeyExchangeAlgorithm.RSA_PSK: - case KeyExchangeAlgorithm.DHE_PSK: - break; - default: - throw new ArgumentException("unsupported key exchange algorithm", "keyExchange"); + case KeyExchangeAlgorithm.DHE_PSK: + case KeyExchangeAlgorithm.ECDHE_PSK: + case KeyExchangeAlgorithm.PSK: + case KeyExchangeAlgorithm.RSA_PSK: + break; + default: + throw new InvalidOperationException("unsupported key exchange algorithm"); } - this.context = context; - this.keyExchange = keyExchange; - this.pskIdentity = pskIdentity; + this.mPskIdentity = pskIdentity; + this.mDHParameters = dhParameters; + this.mNamedCurves = namedCurves; + this.mClientECPointFormats = clientECPointFormats; + this.mServerECPointFormats = serverECPointFormats; } - public virtual void SkipServerCertificate() + public override void SkipServerCredentials() { - if (keyExchange == KeyExchangeAlgorithm.RSA_PSK) - { + if (mKeyExchange == KeyExchangeAlgorithm.RSA_PSK) throw new TlsFatalAlert(AlertDescription.unexpected_message); - } } - public virtual void ProcessServerCertificate(Certificate serverCertificate) + public override void ProcessServerCredentials(TlsCredentials serverCredentials) { - if (keyExchange != KeyExchangeAlgorithm.RSA_PSK) + if (!(serverCredentials is TlsEncryptionCredentials)) + throw new TlsFatalAlert(AlertDescription.internal_error); + + ProcessServerCertificate(serverCredentials.Certificate); + + this.mServerCredentials = (TlsEncryptionCredentials)serverCredentials; + } + + public override byte[] GenerateServerKeyExchange() + { + // TODO[RFC 4279] Need a server-side PSK API to determine hint and resolve identities to keys + this.mPskIdentityHint = null; + + if (this.mPskIdentityHint == null && !RequiresServerKeyExchange) + return null; + + MemoryStream buf = new MemoryStream(); + + if (this.mPskIdentityHint == null) { - throw new TlsFatalAlert(AlertDescription.unexpected_message); + TlsUtilities.WriteOpaque16(TlsUtilities.EmptyBytes, buf); + } + else + { + TlsUtilities.WriteOpaque16(this.mPskIdentityHint, buf); } + if (this.mKeyExchange == KeyExchangeAlgorithm.DHE_PSK) + { + if (this.mDHParameters == null) + throw new TlsFatalAlert(AlertDescription.internal_error); + + this.mDHAgreePrivateKey = TlsDHUtilities.GenerateEphemeralServerKeyExchange(context.SecureRandom, + this.mDHParameters, buf); + } + else if (this.mKeyExchange == KeyExchangeAlgorithm.ECDHE_PSK) + { + // TODO[RFC 5489] + } + + return buf.ToArray(); + } + + public override void ProcessServerCertificate(Certificate serverCertificate) + { + if (mKeyExchange != KeyExchangeAlgorithm.RSA_PSK) + throw new TlsFatalAlert(AlertDescription.unexpected_message); + if (serverCertificate.IsEmpty) + throw new TlsFatalAlert(AlertDescription.bad_certificate); + X509CertificateStructure x509Cert = serverCertificate.GetCertificateAt(0); - SubjectPublicKeyInfo keyInfo = x509Cert.SubjectPublicKeyInfo; + SubjectPublicKeyInfo keyInfo = x509Cert.SubjectPublicKeyInfo; try { - this.serverPublicKey = PublicKeyFactory.CreateKey(keyInfo); + this.mServerPublicKey = PublicKeyFactory.CreateKey(keyInfo); } catch (Exception e) { @@ -70,107 +120,92 @@ namespace Org.BouncyCastle.Crypto.Tls } // Sanity check the PublicKeyFactory - if (this.serverPublicKey.IsPrivate) - { + if (this.mServerPublicKey.IsPrivate) throw new TlsFatalAlert(AlertDescription.internal_error); - } - this.rsaServerPublicKey = ValidateRsaPublicKey((RsaKeyParameters)this.serverPublicKey); + this.mRsaServerPublicKey = ValidateRsaPublicKey((RsaKeyParameters)this.mServerPublicKey); TlsUtilities.ValidateKeyUsage(x509Cert, KeyUsage.KeyEncipherment); - // TODO - /* - * Perform various checks per RFC2246 7.4.2: "Unless otherwise specified, the - * signing algorithm for the certificate must be the same as the algorithm for the - * certificate key." - */ + base.ProcessServerCertificate(serverCertificate); } - public virtual void SkipServerKeyExchange() + public override bool RequiresServerKeyExchange { - if (keyExchange == KeyExchangeAlgorithm.DHE_PSK) + get { - throw new TlsFatalAlert(AlertDescription.unexpected_message); + switch (mKeyExchange) + { + case KeyExchangeAlgorithm.DHE_PSK: + case KeyExchangeAlgorithm.ECDHE_PSK: + return true; + default: + return false; + } } - - this.psk_identity_hint = TlsUtilities.EmptyBytes; } - public virtual void ProcessServerKeyExchange(Stream input) + public override void ProcessServerKeyExchange(Stream input) { - this.psk_identity_hint = TlsUtilities.ReadOpaque16(input); + this.mPskIdentityHint = TlsUtilities.ReadOpaque16(input); - if (this.keyExchange == KeyExchangeAlgorithm.DHE_PSK) + if (this.mKeyExchange == KeyExchangeAlgorithm.DHE_PSK) { - byte[] pBytes = TlsUtilities.ReadOpaque16(input); - byte[] gBytes = TlsUtilities.ReadOpaque16(input); - byte[] YsBytes = TlsUtilities.ReadOpaque16(input); + ServerDHParams serverDHParams = ServerDHParams.Parse(input); - BigInteger p = new BigInteger(1, pBytes); - BigInteger g = new BigInteger(1, gBytes); - BigInteger Ys = new BigInteger(1, YsBytes); - - this.dhAgreeServerPublicKey = TlsDHUtilities.ValidateDHPublicKey( - new DHPublicKeyParameters(Ys, new DHParameters(p, g))); + this.mDHAgreePublicKey = TlsDHUtilities.ValidateDHPublicKey(serverDHParams.PublicKey); } - else if (this.psk_identity_hint.Length == 0) + else if (this.mKeyExchange == KeyExchangeAlgorithm.ECDHE_PSK) { - // TODO Should we enforce that this message should have been skipped if hint is empty? - //throw new TlsFatalAlert(AlertDescription.unexpected_message); + // TODO[RFC 5489] } } - public virtual void ValidateCertificateRequest(CertificateRequest certificateRequest) + public override void ValidateCertificateRequest(CertificateRequest certificateRequest) { throw new TlsFatalAlert(AlertDescription.unexpected_message); } - public virtual void SkipClientCredentials() - { - // OK - } - - public virtual void ProcessClientCredentials(TlsCredentials clientCredentials) + public override void ProcessClientCredentials(TlsCredentials clientCredentials) { throw new TlsFatalAlert(AlertDescription.internal_error); } - public virtual void GenerateClientKeyExchange(Stream output) + public override void GenerateClientKeyExchange(Stream output) { - if (psk_identity_hint == null) + if (mPskIdentityHint == null) { - pskIdentity.SkipIdentityHint(); + mPskIdentity.SkipIdentityHint(); } else { - pskIdentity.NotifyIdentityHint(psk_identity_hint); + mPskIdentity.NotifyIdentityHint(mPskIdentityHint); } - byte[] psk_identity = pskIdentity.GetPskIdentity(); + byte[] psk_identity = mPskIdentity.GetPskIdentity(); TlsUtilities.WriteOpaque16(psk_identity, output); - if (this.keyExchange == KeyExchangeAlgorithm.DHE_PSK) + if (this.mKeyExchange == KeyExchangeAlgorithm.DHE_PSK) { - this.dhAgreeClientPrivateKey = TlsDHUtilities.GenerateEphemeralClientKeyExchange( - context.SecureRandom, this.dhAgreeServerPublicKey.Parameters, output); + this.mDHAgreePrivateKey = TlsDHUtilities.GenerateEphemeralClientKeyExchange(context.SecureRandom, + mDHAgreePublicKey.Parameters, output); } - else if (this.keyExchange == KeyExchangeAlgorithm.ECDHE_PSK) + else if (this.mKeyExchange == KeyExchangeAlgorithm.ECDHE_PSK) { // TODO[RFC 5489] throw new TlsFatalAlert(AlertDescription.internal_error); } - else if (this.keyExchange == KeyExchangeAlgorithm.RSA_PSK) + else if (this.mKeyExchange == KeyExchangeAlgorithm.RSA_PSK) { - this.premasterSecret = TlsRsaUtilities.GenerateEncryptedPreMasterSecret( - context, this.rsaServerPublicKey, output); + this.mPremasterSecret = TlsRsaUtilities.GenerateEncryptedPreMasterSecret(context, + this.mRsaServerPublicKey, output); } } - public virtual byte[] GeneratePremasterSecret() + public override byte[] GeneratePremasterSecret() { - byte[] psk = pskIdentity.GetPsk(); + byte[] psk = mPskIdentity.GetPsk(); byte[] other_secret = GenerateOtherSecret(psk.Length); MemoryStream buf = new MemoryStream(4 + other_secret.Length + psk.Length); @@ -181,14 +216,25 @@ namespace Org.BouncyCastle.Crypto.Tls protected virtual byte[] GenerateOtherSecret(int pskLength) { - if (this.keyExchange == KeyExchangeAlgorithm.DHE_PSK) + if (this.mKeyExchange == KeyExchangeAlgorithm.DHE_PSK) + { + if (mDHAgreePrivateKey != null) + { + return TlsDHUtilities.CalculateDHBasicAgreement(mDHAgreePublicKey, mDHAgreePrivateKey); + } + + throw new TlsFatalAlert(AlertDescription.internal_error); + } + + if (this.mKeyExchange == KeyExchangeAlgorithm.ECDHE_PSK) { - return TlsDHUtilities.CalculateDHBasicAgreement(dhAgreeServerPublicKey, dhAgreeClientPrivateKey); + // TODO[RFC 5489] + throw new TlsFatalAlert(AlertDescription.internal_error); } - if (this.keyExchange == KeyExchangeAlgorithm.RSA_PSK) + if (this.mKeyExchange == KeyExchangeAlgorithm.RSA_PSK) { - return this.premasterSecret; + return this.mPremasterSecret; } return new byte[pskLength]; @@ -197,12 +243,10 @@ namespace Org.BouncyCastle.Crypto.Tls protected virtual RsaKeyParameters ValidateRsaPublicKey(RsaKeyParameters key) { // TODO What is the minimum bit length required? - // key.Modulus.BitLength; + // key.Modulus.BitLength; if (!key.Exponent.IsProbablePrime(2)) - { throw new TlsFatalAlert(AlertDescription.illegal_parameter); - } return key; } diff --git a/crypto/src/crypto/tls/TlsRsaKeyExchange.cs b/crypto/src/crypto/tls/TlsRsaKeyExchange.cs index 160afa5c9..3a0a49154 100644 --- a/crypto/src/crypto/tls/TlsRsaKeyExchange.cs +++ b/crypto/src/crypto/tls/TlsRsaKeyExchange.cs @@ -1,45 +1,57 @@ using System; +using System.Collections; using System.IO; using Org.BouncyCastle.Asn1; using Org.BouncyCastle.Asn1.X509; -using Org.BouncyCastle.Crypto; using Org.BouncyCastle.Crypto.Encodings; using Org.BouncyCastle.Crypto.Engines; using Org.BouncyCastle.Crypto.Parameters; using Org.BouncyCastle.Security; +using Org.BouncyCastle.Utilities.IO; namespace Org.BouncyCastle.Crypto.Tls { - /// <summary> - /// TLS 1.0 RSA key exchange. - /// </summary> - internal class TlsRsaKeyExchange - : TlsKeyExchange + /// <summary>(D)TLS and SSLv3 RSA key exchange.</summary> + public class TlsRsaKeyExchange + : AbstractTlsKeyExchange { - protected TlsContext context; - protected AsymmetricKeyParameter serverPublicKey = null; protected RsaKeyParameters rsaServerPublicKey = null; + protected TlsEncryptionCredentials serverCredentials = null; + protected byte[] premasterSecret; - internal TlsRsaKeyExchange(TlsContext context) + public TlsRsaKeyExchange(IList supportedSignatureAlgorithms) + : base(KeyExchangeAlgorithm.RSA, supportedSignatureAlgorithms) { - this.context = context; } - public virtual void SkipServerCertificate() + public override void SkipServerCredentials() { throw new TlsFatalAlert(AlertDescription.unexpected_message); } - public virtual void ProcessServerCertificate(Certificate serverCertificate) + public override void ProcessServerCredentials(TlsCredentials serverCredentials) + { + if (!(serverCredentials is TlsEncryptionCredentials)) + throw new TlsFatalAlert(AlertDescription.internal_error); + + ProcessServerCertificate(serverCredentials.Certificate); + + this.serverCredentials = (TlsEncryptionCredentials)serverCredentials; + } + + public override void ProcessServerCertificate(Certificate serverCertificate) { + if (serverCertificate.IsEmpty) + throw new TlsFatalAlert(AlertDescription.bad_certificate); + X509CertificateStructure x509Cert = serverCertificate.GetCertificateAt(0); - SubjectPublicKeyInfo keyInfo = x509Cert.SubjectPublicKeyInfo; + SubjectPublicKeyInfo keyInfo = x509Cert.SubjectPublicKeyInfo; try { this.serverPublicKey = PublicKeyFactory.CreateKey(keyInfo); @@ -51,111 +63,76 @@ namespace Org.BouncyCastle.Crypto.Tls // Sanity check the PublicKeyFactory if (this.serverPublicKey.IsPrivate) - { throw new TlsFatalAlert(AlertDescription.internal_error); - } this.rsaServerPublicKey = ValidateRsaPublicKey((RsaKeyParameters)this.serverPublicKey); TlsUtilities.ValidateKeyUsage(x509Cert, KeyUsage.KeyEncipherment); - // TODO - /* - * Perform various checks per RFC2246 7.4.2: "Unless otherwise specified, the - * signing algorithm for the certificate must be the same as the algorithm for the - * certificate key." - */ + base.ProcessServerCertificate(serverCertificate); } - public virtual void SkipServerKeyExchange() - { - // OK - } - - public virtual void ProcessServerKeyExchange(Stream input) - { - throw new TlsFatalAlert(AlertDescription.unexpected_message); - } - - public virtual void ValidateCertificateRequest(CertificateRequest certificateRequest) + public override void ValidateCertificateRequest(CertificateRequest certificateRequest) { byte[] types = certificateRequest.CertificateTypes; - foreach (byte type in types) + for (int i = 0; i < types.Length; ++i) { - switch (type) + switch (types[i]) { - case ClientCertificateType.rsa_sign: - case ClientCertificateType.dss_sign: - case ClientCertificateType.ecdsa_sign: - break; - default: - throw new TlsFatalAlert(AlertDescription.illegal_parameter); + case ClientCertificateType.rsa_sign: + case ClientCertificateType.dss_sign: + case ClientCertificateType.ecdsa_sign: + break; + default: + throw new TlsFatalAlert(AlertDescription.illegal_parameter); } } } - public virtual void SkipClientCredentials() + public override void ProcessClientCredentials(TlsCredentials clientCredentials) { - // OK + if (!(clientCredentials is TlsSignerCredentials)) + throw new TlsFatalAlert(AlertDescription.internal_error); } - public virtual void ProcessClientCredentials(TlsCredentials clientCredentials) + public override void GenerateClientKeyExchange(Stream output) { - if (!(clientCredentials is TlsSignerCredentials)) - { - throw new TlsFatalAlert(AlertDescription.internal_error); - } + this.premasterSecret = TlsRsaUtilities.GenerateEncryptedPreMasterSecret(context, rsaServerPublicKey, output); } - - public virtual void GenerateClientKeyExchange(Stream output) + + public override void ProcessClientKeyExchange(Stream input) { - this.premasterSecret = TlsRsaUtilities.GenerateEncryptedPreMasterSecret(context, this.rsaServerPublicKey, output); + byte[] encryptedPreMasterSecret; + if (TlsUtilities.IsSsl(context)) + { + // TODO Do any SSLv3 clients actually include the length? + encryptedPreMasterSecret = Streams.ReadAll(input); + } + else + { + encryptedPreMasterSecret = TlsUtilities.ReadOpaque16(input); + } + + this.premasterSecret = serverCredentials.DecryptPreMasterSecret(encryptedPreMasterSecret); } - public virtual byte[] GeneratePremasterSecret() + public override byte[] GeneratePremasterSecret() { + if (this.premasterSecret == null) + throw new TlsFatalAlert(AlertDescription.internal_error); + byte[] tmp = this.premasterSecret; this.premasterSecret = null; return tmp; } - // Would be needed to process RSA_EXPORT server key exchange -// protected virtual void ProcessRsaServerKeyExchange(Stream input, ISigner signer) -// { -// Stream sigIn = input; -// if (signer != null) -// { -// sigIn = new SignerStream(input, signer, null); -// } -// -// byte[] modulusBytes = TlsUtilities.ReadOpaque16(sigIn); -// byte[] exponentBytes = TlsUtilities.ReadOpaque16(sigIn); -// -// if (signer != null) -// { -// byte[] sigByte = TlsUtilities.ReadOpaque16(input); -// -// if (!signer.VerifySignature(sigByte)) -// { -// handler.FailWithError(AlertLevel.fatal, AlertDescription.decrypt_error); -// } -// } -// -// BigInteger modulus = new BigInteger(1, modulusBytes); -// BigInteger exponent = new BigInteger(1, exponentBytes); -// -// this.rsaServerPublicKey = ValidateRSAPublicKey(new RsaKeyParameters(false, modulus, exponent)); -// } - protected virtual RsaKeyParameters ValidateRsaPublicKey(RsaKeyParameters key) { // TODO What is the minimum bit length required? -// key.Modulus.BitLength; + // key.Modulus.BitLength; if (!key.Exponent.IsProbablePrime(2)) - { throw new TlsFatalAlert(AlertDescription.illegal_parameter); - } return key; } diff --git a/crypto/src/crypto/tls/TlsSrpKeyExchange.cs b/crypto/src/crypto/tls/TlsSrpKeyExchange.cs index ff1bdac86..f42f7456d 100644 --- a/crypto/src/crypto/tls/TlsSrpKeyExchange.cs +++ b/crypto/src/crypto/tls/TlsSrpKeyExchange.cs @@ -1,189 +1,175 @@ using System; +using System.Collections; using System.IO; -using Org.BouncyCastle.Asn1; using Org.BouncyCastle.Asn1.X509; -using Org.BouncyCastle.Crypto; -using Org.BouncyCastle.Crypto.Agreement; using Org.BouncyCastle.Crypto.Agreement.Srp; -using Org.BouncyCastle.Crypto.Digests; -using Org.BouncyCastle.Crypto.IO; using Org.BouncyCastle.Crypto.Parameters; using Org.BouncyCastle.Math; using Org.BouncyCastle.Security; using Org.BouncyCastle.Utilities; +using Org.BouncyCastle.Utilities.IO; namespace Org.BouncyCastle.Crypto.Tls { - /// <summary> - /// TLS 1.1 SRP key exchange. - /// </summary> - internal class TlsSrpKeyExchange - : TlsKeyExchange + /// <summary>(D)TLS SRP key exchange (RFC 5054).</summary> + public class TlsSrpKeyExchange + : AbstractTlsKeyExchange { - protected TlsContext context; - protected int keyExchange; - protected TlsSigner tlsSigner; - protected byte[] identity; - protected byte[] password; + protected TlsSigner mTlsSigner; + protected byte[] mIdentity; + protected byte[] mPassword; - protected AsymmetricKeyParameter serverPublicKey = null; + protected AsymmetricKeyParameter mServerPublicKey = null; - protected byte[] s = null; - protected BigInteger B = null; - protected Srp6Client srpClient = new Srp6Client(); + protected byte[] mS = null; + protected BigInteger mB = null; + protected Srp6Client mSrpClient = new Srp6Client(); - internal TlsSrpKeyExchange(TlsContext context, int keyExchange, - byte[] identity, byte[] password) + public TlsSrpKeyExchange(int keyExchange, IList supportedSignatureAlgorithms, byte[] identity, byte[] password) + : base(keyExchange, supportedSignatureAlgorithms) { switch (keyExchange) { - case KeyExchangeAlgorithm.SRP: - this.tlsSigner = null; - break; - case KeyExchangeAlgorithm.SRP_RSA: - this.tlsSigner = new TlsRsaSigner(); - break; - case KeyExchangeAlgorithm.SRP_DSS: - this.tlsSigner = new TlsDssSigner(); - break; - default: - throw new ArgumentException("unsupported key exchange algorithm", "keyExchange"); + case KeyExchangeAlgorithm.SRP: + this.mTlsSigner = null; + break; + case KeyExchangeAlgorithm.SRP_RSA: + this.mTlsSigner = new TlsRsaSigner(); + break; + case KeyExchangeAlgorithm.SRP_DSS: + this.mTlsSigner = new TlsDssSigner(); + break; + default: + throw new InvalidOperationException("unsupported key exchange algorithm"); } - this.context = context; - this.keyExchange = keyExchange; - this.identity = identity; - this.password = password; + this.mIdentity = identity; + this.mPassword = password; } - public virtual void SkipServerCertificate() + public override void Init(TlsContext context) { - if (tlsSigner != null) + base.Init(context); + + if (this.mTlsSigner != null) { - throw new TlsFatalAlert(AlertDescription.unexpected_message); + this.mTlsSigner.Init(context); } } - public virtual void ProcessServerCertificate(Certificate serverCertificate) + public override void SkipServerCredentials() { - if (tlsSigner == null) - { + if (mTlsSigner != null) throw new TlsFatalAlert(AlertDescription.unexpected_message); - } + } + + public override void ProcessServerCertificate(Certificate serverCertificate) + { + if (mTlsSigner == null) + throw new TlsFatalAlert(AlertDescription.unexpected_message); + if (serverCertificate.IsEmpty) + throw new TlsFatalAlert(AlertDescription.bad_certificate); X509CertificateStructure x509Cert = serverCertificate.GetCertificateAt(0); - SubjectPublicKeyInfo keyInfo = x509Cert.SubjectPublicKeyInfo; + SubjectPublicKeyInfo keyInfo = x509Cert.SubjectPublicKeyInfo; try { - this.serverPublicKey = PublicKeyFactory.CreateKey(keyInfo); + this.mServerPublicKey = PublicKeyFactory.CreateKey(keyInfo); } catch (Exception e) { throw new TlsFatalAlert(AlertDescription.unsupported_certificate, e); } - if (!tlsSigner.IsValidPublicKey(this.serverPublicKey)) - { + if (!mTlsSigner.IsValidPublicKey(this.mServerPublicKey)) throw new TlsFatalAlert(AlertDescription.certificate_unknown); - } TlsUtilities.ValidateKeyUsage(x509Cert, KeyUsage.DigitalSignature); - // TODO - /* - * Perform various checks per RFC2246 7.4.2: "Unless otherwise specified, the - * signing algorithm for the certificate must be the same as the algorithm for the - * certificate key." - */ + base.ProcessServerCertificate(serverCertificate); } - public virtual void SkipServerKeyExchange() + public override bool RequiresServerKeyExchange { - throw new TlsFatalAlert(AlertDescription.unexpected_message); + get { return true; } } - public virtual void ProcessServerKeyExchange(Stream input) + public override void ProcessServerKeyExchange(Stream input) { SecurityParameters securityParameters = context.SecurityParameters; - Stream sigIn = input; - ISigner signer = null; + SignerInputBuffer buf = null; + Stream teeIn = input; - if (tlsSigner != null) + if (mTlsSigner != null) { - signer = InitSigner(tlsSigner, securityParameters); - sigIn = new SignerStream(input, signer, null); + buf = new SignerInputBuffer(); + teeIn = new TeeInputStream(input, buf); } - byte[] NBytes = TlsUtilities.ReadOpaque16(sigIn); - byte[] gBytes = TlsUtilities.ReadOpaque16(sigIn); - byte[] sBytes = TlsUtilities.ReadOpaque8(sigIn); - byte[] BBytes = TlsUtilities.ReadOpaque16(sigIn); + byte[] NBytes = TlsUtilities.ReadOpaque16(teeIn); + byte[] gBytes = TlsUtilities.ReadOpaque16(teeIn); + byte[] sBytes = TlsUtilities.ReadOpaque8(teeIn); + byte[] BBytes = TlsUtilities.ReadOpaque16(teeIn); - if (signer != null) + if (buf != null) { - byte[] sigByte = TlsUtilities.ReadOpaque16(input); + DigitallySigned signed_params = DigitallySigned.Parse(context, input); - if (!signer.VerifySignature(sigByte)) - { + ISigner signer = InitVerifyer(mTlsSigner, signed_params.Algorithm, securityParameters); + buf.UpdateSigner(signer); + if (!signer.VerifySignature(signed_params.Signature)) throw new TlsFatalAlert(AlertDescription.decrypt_error); - } } BigInteger N = new BigInteger(1, NBytes); BigInteger g = new BigInteger(1, gBytes); // TODO Validate group parameters (see RFC 5054) - //throw new TlsFatalAlert(AlertDescription.insufficient_security); + // throw new TlsFatalAlert(AlertDescription.insufficient_security); - this.s = sBytes; + this.mS = sBytes; /* - * RFC 5054 2.5.3: The client MUST abort the handshake with an "illegal_parameter" - * alert if B % N = 0. - */ + * RFC 5054 2.5.3: The client MUST abort the handshake with an "illegal_parameter" alert if + * B % N = 0. + */ try { - this.B = Srp6Utilities.ValidatePublicValue(N, new BigInteger(1, BBytes)); + this.mB = Srp6Utilities.ValidatePublicValue(N, new BigInteger(1, BBytes)); } catch (CryptoException e) { throw new TlsFatalAlert(AlertDescription.illegal_parameter, e); } - this.srpClient.Init(N, g, new Sha1Digest(), context.SecureRandom); + this.mSrpClient.Init(N, g, TlsUtilities.CreateHash(HashAlgorithm.sha1), context.SecureRandom); } - public virtual void ValidateCertificateRequest(CertificateRequest certificateRequest) + public override void ValidateCertificateRequest(CertificateRequest certificateRequest) { throw new TlsFatalAlert(AlertDescription.unexpected_message); } - public virtual void SkipClientCredentials() - { - // OK - } - - public virtual void ProcessClientCredentials(TlsCredentials clientCredentials) + public override void ProcessClientCredentials(TlsCredentials clientCredentials) { throw new TlsFatalAlert(AlertDescription.internal_error); } - public virtual void GenerateClientKeyExchange(Stream output) + public override void GenerateClientKeyExchange(Stream output) { - byte[] keData = BigIntegers.AsUnsignedByteArray(srpClient.GenerateClientCredentials(s, - this.identity, this.password)); - TlsUtilities.WriteOpaque16(keData, output); + BigInteger A = mSrpClient.GenerateClientCredentials(mS, this.mIdentity, this.mPassword); + TlsUtilities.WriteOpaque16(BigIntegers.AsUnsignedByteArray(A), output); } - public virtual byte[] GeneratePremasterSecret() + public override byte[] GeneratePremasterSecret() { try { // TODO Check if this needs to be a fixed size - return BigIntegers.AsUnsignedByteArray(srpClient.CalculateSecret(B)); + return BigIntegers.AsUnsignedByteArray(mSrpClient.CalculateSecret(mB)); } catch (CryptoException e) { @@ -191,9 +177,10 @@ namespace Org.BouncyCastle.Crypto.Tls } } - protected virtual ISigner InitSigner(TlsSigner tlsSigner, SecurityParameters securityParameters) + protected virtual ISigner InitVerifyer(TlsSigner tlsSigner, SignatureAndHashAlgorithm algorithm, + SecurityParameters securityParameters) { - ISigner signer = tlsSigner.CreateVerifyer(this.serverPublicKey); + ISigner signer = tlsSigner.CreateVerifyer(algorithm, this.mServerPublicKey); signer.BlockUpdate(securityParameters.clientRandom, 0, securityParameters.clientRandom.Length); signer.BlockUpdate(securityParameters.serverRandom, 0, securityParameters.serverRandom.Length); return signer; |