summary refs log tree commit diff
path: root/crypto/src/crypto/tls/TlsSrpKeyExchange.cs
diff options
context:
space:
mode:
authorPeter Dettman <peter.dettman@bouncycastle.org>2014-08-23 20:52:11 +0700
committerPeter Dettman <peter.dettman@bouncycastle.org>2014-08-23 20:52:11 +0700
commit5078f3e6611b98fe50abcd3df3c63fb8c206f6b6 (patch)
tree2e540875099f89de29996b8e3599c90a4990e6b7 /crypto/src/crypto/tls/TlsSrpKeyExchange.cs
parentMore TLS porting from Java API (diff)
downloadBouncyCastle.NET-ed25519-5078f3e6611b98fe50abcd3df3c63fb8c206f6b6.tar.xz
Port latest TLS key exchange stuff from Java API
Diffstat (limited to '')
-rw-r--r--crypto/src/crypto/tls/TlsSrpKeyExchange.cs173
1 files changed, 80 insertions, 93 deletions
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;