summary refs log tree commit diff
path: root/crypto/src
diff options
context:
space:
mode:
authorPeter Dettman <peter.dettman@bouncycastle.org>2016-01-17 15:07:27 +0700
committerPeter Dettman <peter.dettman@bouncycastle.org>2016-01-17 15:07:27 +0700
commitcbe36e32b83408ebdb649677dc8cf29ac1e8cf63 (patch)
treeb0145a697b7467cf9783160ed34a66d3fa1e398a /crypto/src
parentSupport for re-init in Salsa family (diff)
downloadBouncyCastle.NET-ed25519-cbe36e32b83408ebdb649677dc8cf29ac1e8cf63.tar.xz
Implement updated draft-ietf-tls-chacha20-poly1305-04
Diffstat (limited to 'crypto/src')
-rw-r--r--crypto/src/crypto/engines/ChaCha7539Engine.cs65
-rw-r--r--crypto/src/crypto/generators/Poly1305KeyGenerator.cs24
-rw-r--r--crypto/src/crypto/tls/Chacha20Poly1305.cs113
-rw-r--r--crypto/src/crypto/tls/CipherSuite.cs12
-rw-r--r--crypto/src/crypto/tls/DefaultTlsCipherFactory.cs6
-rw-r--r--crypto/src/crypto/tls/EncryptionAlgorithm.cs5
-rw-r--r--crypto/src/crypto/tls/HashAlgorithm.cs5
-rw-r--r--crypto/src/crypto/tls/TlsDHUtilities.cs5
-rw-r--r--crypto/src/crypto/tls/TlsEccUtilities.cs7
-rw-r--r--crypto/src/crypto/tls/TlsProtocol.cs10
-rw-r--r--crypto/src/crypto/tls/TlsUtilities.cs55
11 files changed, 241 insertions, 66 deletions
diff --git a/crypto/src/crypto/engines/ChaCha7539Engine.cs b/crypto/src/crypto/engines/ChaCha7539Engine.cs
new file mode 100644
index 000000000..5a12be016
--- /dev/null
+++ b/crypto/src/crypto/engines/ChaCha7539Engine.cs
@@ -0,0 +1,65 @@
+using System;
+
+using Org.BouncyCastle.Crypto.Utilities;
+
+namespace Org.BouncyCastle.Crypto.Engines
+{
+    /// <summary>
+    /// Implementation of Daniel J. Bernstein's ChaCha stream cipher.
+    /// </summary>
+    public class ChaCha7539Engine
+        : Salsa20Engine
+    {
+        /// <summary>
+        /// Creates a 20 rounds ChaCha engine.
+        /// </summary>
+        public ChaCha7539Engine()
+        {
+        }
+
+        public override string AlgorithmName
+        {
+            get { return "ChaCha" + rounds; }
+        }
+
+        protected override int NonceSize
+        {
+            get { return 12; }
+        }
+
+        protected override void AdvanceCounter()
+        {
+            if (++engineState[12] == 0)
+                throw new InvalidOperationException("attempt to increase counter past 2^32.");
+        }
+
+        protected override void ResetCounter()
+        {
+            engineState[12] = 0;
+        }
+
+        protected override void SetKey(byte[] keyBytes, byte[] ivBytes)
+        {
+            if (keyBytes != null)
+            {
+                if (keyBytes.Length != 32)
+                    throw new ArgumentException(AlgorithmName + " requires 256 bit key");
+
+                PackTauOrSigma(keyBytes.Length, engineState, 0);
+
+                // Key
+                Pack.LE_To_UInt32(keyBytes, 0, engineState, 4, 8);
+            }
+
+            // IV
+            Pack.LE_To_UInt32(ivBytes, 0, engineState, 13, 3);
+        }
+
+        protected override void GenerateKeyStream(byte[] output)
+        {
+            ChaChaEngine.ChachaCore(rounds, engineState, x);
+            Pack.UInt32_To_LE(x, output, 0);
+        }
+    }
+}
+
diff --git a/crypto/src/crypto/generators/Poly1305KeyGenerator.cs b/crypto/src/crypto/generators/Poly1305KeyGenerator.cs
index 5deb50f07..d05af0add 100644
--- a/crypto/src/crypto/generators/Poly1305KeyGenerator.cs
+++ b/crypto/src/crypto/generators/Poly1305KeyGenerator.cs
@@ -86,6 +86,30 @@ namespace Org.BouncyCastle.Crypto.Generators
 			key[28] &= R_MASK_LOW_2;
 		}
 
+        internal static void Clamp(byte[] key, int keyOff)
+        {
+            /*
+             * Key is k[0] ... k[15], r[0] ... r[15] as per poly1305_aes_clamp in ref impl.
+             */
+            if (key.Length - 32 < keyOff)
+                throw new ArgumentException("Poly1305 key must be 256 bits.");
+
+            /*
+             * r[3], r[7], r[11], r[15] have top four bits clear (i.e., are {0, 1, . . . , 15})
+             */
+            key[keyOff + 19] &= R_MASK_HIGH_4;
+            key[keyOff + 23] &= R_MASK_HIGH_4;
+            key[keyOff + 27] &= R_MASK_HIGH_4;
+            key[keyOff + 31] &= R_MASK_HIGH_4;
+
+            /*
+             * r[4], r[8], r[12] have bottom two bits clear (i.e., are in {0, 4, 8, . . . , 252}).
+             */
+            key[keyOff + 20] &= R_MASK_LOW_2;
+            key[keyOff + 24] &= R_MASK_LOW_2;
+            key[keyOff + 28] &= R_MASK_LOW_2;
+        }
+
 		/// <summary>
 		/// Checks a 32 byte key for compliance with the Poly1305 key requirements, e.g.
 		/// <code>k[0] ... k[15], r[0] ... r[15]</code> with the required bits in <code>r</code> cleared
diff --git a/crypto/src/crypto/tls/Chacha20Poly1305.cs b/crypto/src/crypto/tls/Chacha20Poly1305.cs
index e4e4c7ee2..817e64b25 100644
--- a/crypto/src/crypto/tls/Chacha20Poly1305.cs
+++ b/crypto/src/crypto/tls/Chacha20Poly1305.cs
@@ -11,13 +11,18 @@ using Org.BouncyCastle.Utilities;
 
 namespace Org.BouncyCastle.Crypto.Tls
 {
+    /**
+     * draft-ietf-tls-chacha20-poly1305-04
+     */
     public class Chacha20Poly1305
         :   TlsCipher
     {
+        private static readonly byte[] Zeroes = new byte[15];
+
         protected readonly TlsContext context;
 
-        protected readonly ChaChaEngine encryptCipher;
-        protected readonly ChaChaEngine decryptCipher;
+        protected readonly ChaCha7539Engine encryptCipher, decryptCipher;
+        protected readonly byte[] encryptIV, decryptIV;
 
         /// <exception cref="IOException"></exception>
         public Chacha20Poly1305(TlsContext context)
@@ -27,30 +32,50 @@ namespace Org.BouncyCastle.Crypto.Tls
 
             this.context = context;
 
-            byte[] key_block = TlsUtilities.CalculateKeyBlock(context, 64);
+            int cipherKeySize = 32;
+            // TODO SecurityParameters.fixed_iv_length
+            int fixed_iv_length = 12;
+            // TODO SecurityParameters.record_iv_length = 0
+
+            int key_block_size = (2 * cipherKeySize) + (2 * fixed_iv_length);
+
+            byte[] key_block = TlsUtilities.CalculateKeyBlock(context, key_block_size);
+
+            int offset = 0;
 
-            KeyParameter client_write_key = new KeyParameter(key_block, 0, 32);
-            KeyParameter server_write_key = new KeyParameter(key_block, 32, 32);
+            KeyParameter client_write_key = new KeyParameter(key_block, offset, cipherKeySize);
+            offset += cipherKeySize;
+            KeyParameter server_write_key = new KeyParameter(key_block, offset, cipherKeySize);
+            offset += cipherKeySize;
+            byte[] client_write_IV = Arrays.CopyOfRange(key_block, offset, offset + fixed_iv_length);
+            offset += fixed_iv_length;
+            byte[] server_write_IV = Arrays.CopyOfRange(key_block, offset, offset + fixed_iv_length);
+            offset += fixed_iv_length;
 
-            this.encryptCipher = new ChaChaEngine(20);
-            this.decryptCipher = new ChaChaEngine(20);
+            if (offset != key_block_size)
+                throw new TlsFatalAlert(AlertDescription.internal_error);
+
+            this.encryptCipher = new ChaCha7539Engine();
+            this.decryptCipher = new ChaCha7539Engine();
 
             KeyParameter encryptKey, decryptKey;
             if (context.IsServer)
             {
                 encryptKey = server_write_key;
                 decryptKey = client_write_key;
+                this.encryptIV = server_write_IV;
+                this.decryptIV = client_write_IV;
             }
             else
             {
                 encryptKey = client_write_key;
                 decryptKey = server_write_key;
+                this.encryptIV = client_write_IV;
+                this.decryptIV = server_write_IV;
             }
 
-            byte[] dummyNonce = new byte[8];
-
-            this.encryptCipher.Init(true, new ParametersWithIV(encryptKey, dummyNonce));
-            this.decryptCipher.Init(false, new ParametersWithIV(decryptKey, dummyNonce));
+            this.encryptCipher.Init(true, new ParametersWithIV(encryptKey, encryptIV));
+            this.decryptCipher.Init(false, new ParametersWithIV(decryptKey, decryptIV));
         }
 
         public virtual int GetPlaintextLimit(int ciphertextLimit)
@@ -61,11 +86,9 @@ namespace Org.BouncyCastle.Crypto.Tls
         /// <exception cref="IOException"></exception>
         public virtual byte[] EncodePlaintext(long seqNo, byte type, byte[] plaintext, int offset, int len)
         {
-            int ciphertextLength = len + 16;
-
-            KeyParameter macKey = InitRecordMac(encryptCipher, true, seqNo);
+            KeyParameter macKey = InitRecord(encryptCipher, true, seqNo, encryptIV);
 
-            byte[] output = new byte[ciphertextLength];
+            byte[] output = new byte[len + 16];
             encryptCipher.ProcessBytes(plaintext, offset, len, output, 0);
 
             byte[] additionalData = GetAdditionalData(seqNo, type, len);
@@ -81,38 +104,52 @@ namespace Org.BouncyCastle.Crypto.Tls
             if (GetPlaintextLimit(len) < 0)
                 throw new TlsFatalAlert(AlertDescription.decode_error);
 
-            int plaintextLength = len - 16;
-
-            byte[] receivedMAC = Arrays.CopyOfRange(ciphertext, offset + plaintextLength, offset + len);
+            KeyParameter macKey = InitRecord(decryptCipher, false, seqNo, decryptIV);
 
-            KeyParameter macKey = InitRecordMac(decryptCipher, false, seqNo);
+            int plaintextLength = len - 16;
 
             byte[] additionalData = GetAdditionalData(seqNo, type, plaintextLength);
-            byte[] calculatedMAC = CalculateRecordMac(macKey, additionalData, ciphertext, offset, plaintextLength);
+            byte[] calculatedMac = CalculateRecordMac(macKey, additionalData, ciphertext, offset, plaintextLength);
+            byte[] receivedMac = Arrays.CopyOfRange(ciphertext, offset + plaintextLength, offset + len);
 
-            if (!Arrays.ConstantTimeAreEqual(calculatedMAC, receivedMAC))
+            if (!Arrays.ConstantTimeAreEqual(calculatedMac, receivedMac))
                 throw new TlsFatalAlert(AlertDescription.bad_record_mac);
 
             byte[] output = new byte[plaintextLength];
             decryptCipher.ProcessBytes(ciphertext, offset, plaintextLength, output, 0);
-
             return output;
         }
 
-        protected virtual KeyParameter InitRecordMac(ChaChaEngine cipher, bool forEncryption, long seqNo)
+        protected virtual KeyParameter InitRecord(IStreamCipher cipher, bool forEncryption, long seqNo, byte[] iv)
         {
-            byte[] nonce = new byte[8];
-            TlsUtilities.WriteUint64(seqNo, nonce, 0);
-
+            byte[] nonce = CalculateNonce(seqNo, iv);
             cipher.Init(forEncryption, new ParametersWithIV(null, nonce));
+            return GenerateRecordMacKey(cipher);
+        }
+
+        protected virtual byte[] CalculateNonce(long seqNo, byte[] iv)
+        {
+            byte[] nonce = new byte[12];
+            TlsUtilities.WriteUint64(seqNo, nonce, 4);
 
+            for (int i = 0; i < 12; ++i)
+            {
+                nonce[i] ^= iv[i];
+            }
+
+            return nonce;
+        }
+
+        protected virtual KeyParameter GenerateRecordMacKey(IStreamCipher cipher)
+        {
             byte[] firstBlock = new byte[64];
             cipher.ProcessBytes(firstBlock, 0, firstBlock.Length, firstBlock, 0);
 
             // NOTE: The BC implementation puts 'r' after 'k'
             Array.Copy(firstBlock, 0, firstBlock, 32, 16);
+            Poly1305KeyGenerator.Clamp(firstBlock, 16);
             KeyParameter macKey = new KeyParameter(firstBlock, 16, 32);
-            Poly1305KeyGenerator.Clamp(macKey.GetKey());
+            Arrays.Fill(firstBlock, (byte)0);
             return macKey;
         }
 
@@ -121,19 +158,31 @@ namespace Org.BouncyCastle.Crypto.Tls
             IMac mac = new Poly1305();
             mac.Init(macKey);
 
-            UpdateRecordMac(mac, additionalData, 0, additionalData.Length);
-            UpdateRecordMac(mac, buf, off, len);
+            UpdateRecordMacText(mac, additionalData, 0, additionalData.Length);
+            UpdateRecordMacText(mac, buf, off, len);
+            UpdateRecordMacLength(mac, additionalData.Length);
+            UpdateRecordMacLength(mac, len);
+
             return MacUtilities.DoFinal(mac);
         }
 
-        protected virtual void UpdateRecordMac(IMac mac, byte[] buf, int off, int len)
+        protected virtual void UpdateRecordMacLength(IMac mac, int len)
         {
-            mac.BlockUpdate(buf, off, len);
-
             byte[] longLen = Pack.UInt64_To_LE((ulong)len);
             mac.BlockUpdate(longLen, 0, longLen.Length);
         }
 
+        protected virtual void UpdateRecordMacText(IMac mac, byte[] buf, int off, int len)
+        {
+            mac.BlockUpdate(buf, off, len);
+
+            int partial = len % 16;
+            if (partial != 0)
+            {
+                mac.BlockUpdate(Zeroes, 0, 16 - partial);
+            }
+        }
+
         /// <exception cref="IOException"></exception>
         protected virtual byte[] GetAdditionalData(long seqNo, byte type, int len)
         {
diff --git a/crypto/src/crypto/tls/CipherSuite.cs b/crypto/src/crypto/tls/CipherSuite.cs
index e285643d4..1ed0a5ef3 100644
--- a/crypto/src/crypto/tls/CipherSuite.cs
+++ b/crypto/src/crypto/tls/CipherSuite.cs
@@ -331,11 +331,15 @@ namespace Org.BouncyCastle.Crypto.Tls
         public const int TLS_ECDHE_ECDSA_WITH_AES_256_CCM_8 = 0xC0AF;
 
         /*
-         * draft-agl-tls-chacha20poly1305-04
+         * draft-ietf-tls-chacha20-poly1305-04
          */
-        public const int TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256 = 0xCC13;
-        public const int TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256 = 0xCC14;
-        public const int TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256 = 0xCC15;
+        public const int DRAFT_TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256 = 0xCCA8;
+        public const int DRAFT_TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256 = 0xCCA9;
+        public const int DRAFT_TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256 = 0xCCAA;
+        public const int DRAFT_TLS_PSK_WITH_CHACHA20_POLY1305_SHA256 = 0xCCAB;
+        public const int DRAFT_TLS_ECDHE_PSK_WITH_CHACHA20_POLY1305_SHA256 = 0xCCAC;
+        public const int DRAFT_TLS_DHE_PSK_WITH_CHACHA20_POLY1305_SHA256 = 0xCCAD;
+        public const int DRAFT_TLS_RSA_PSK_WITH_CHACHA20_POLY1305_SHA256 = 0xCCAE;
 
         /*
          * draft-ietf-tls-downgrade-scsv-00
diff --git a/crypto/src/crypto/tls/DefaultTlsCipherFactory.cs b/crypto/src/crypto/tls/DefaultTlsCipherFactory.cs
index f8222ea9f..a38205bf9 100644
--- a/crypto/src/crypto/tls/DefaultTlsCipherFactory.cs
+++ b/crypto/src/crypto/tls/DefaultTlsCipherFactory.cs
@@ -16,9 +16,6 @@ namespace Org.BouncyCastle.Crypto.Tls
             {
             case EncryptionAlgorithm.cls_3DES_EDE_CBC:
                 return CreateDesEdeCipher(context, macAlgorithm);
-            case EncryptionAlgorithm.AEAD_CHACHA20_POLY1305:
-                // NOTE: Ignores macAlgorithm
-                return CreateChaCha20Poly1305(context);
             case EncryptionAlgorithm.AES_128_CBC:
                 return CreateAESCipher(context, 16, macAlgorithm);
             case EncryptionAlgorithm.AES_128_CCM:
@@ -51,6 +48,9 @@ namespace Org.BouncyCastle.Crypto.Tls
             case EncryptionAlgorithm.CAMELLIA_256_GCM:
                 // NOTE: Ignores macAlgorithm
                 return CreateCipher_Camellia_Gcm(context, 32, 16);
+            case EncryptionAlgorithm.CHACHA20_POLY1305:
+                // NOTE: Ignores macAlgorithm
+                return CreateChaCha20Poly1305(context);
             case EncryptionAlgorithm.NULL:
                 return CreateNullCipher(context, macAlgorithm);
             case EncryptionAlgorithm.RC4_128:
diff --git a/crypto/src/crypto/tls/EncryptionAlgorithm.cs b/crypto/src/crypto/tls/EncryptionAlgorithm.cs
index 35650927c..3ef5274e1 100644
--- a/crypto/src/crypto/tls/EncryptionAlgorithm.cs
+++ b/crypto/src/crypto/tls/EncryptionAlgorithm.cs
@@ -56,8 +56,9 @@ namespace Org.BouncyCastle.Crypto.Tls
         public const int CAMELLIA_256_GCM = 20;
 
         /*
-         * draft-agl-tls-chacha20poly1305-04
+         * draft-ietf-tls-chacha20-poly1305-04
          */
-        public const int AEAD_CHACHA20_POLY1305 = 102;
+        public const int CHACHA20_POLY1305 = 102;
+        [Obsolete] public const int AEAD_CHACHA20_POLY1305 = CHACHA20_POLY1305;
     }
 }
diff --git a/crypto/src/crypto/tls/HashAlgorithm.cs b/crypto/src/crypto/tls/HashAlgorithm.cs
index ff540d2e0..0f38e2d7c 100644
--- a/crypto/src/crypto/tls/HashAlgorithm.cs
+++ b/crypto/src/crypto/tls/HashAlgorithm.cs
@@ -40,5 +40,10 @@ namespace Org.BouncyCastle.Crypto.Tls
         {
             return GetName(hashAlgorithm) + "(" + hashAlgorithm + ")";
         }
+
+        public static bool IsPrivate(byte hashAlgorithm)
+        {
+            return 224 <= hashAlgorithm && hashAlgorithm <= 255;
+        }
     }
 }
diff --git a/crypto/src/crypto/tls/TlsDHUtilities.cs b/crypto/src/crypto/tls/TlsDHUtilities.cs
index 3d0dea99c..c4380ed5c 100644
--- a/crypto/src/crypto/tls/TlsDHUtilities.cs
+++ b/crypto/src/crypto/tls/TlsDHUtilities.cs
@@ -369,9 +369,10 @@ namespace Org.BouncyCastle.Crypto.Tls
             case CipherSuite.TLS_PSK_DHE_WITH_AES_256_CCM_8:
 
             /*
-             * draft-agl-tls-chacha20poly1305-04
+             * draft-ietf-tls-chacha20-poly1305-04
              */
-            case CipherSuite.TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256:
+            case CipherSuite.DRAFT_TLS_DHE_PSK_WITH_CHACHA20_POLY1305_SHA256:
+            case CipherSuite.DRAFT_TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256:
 
                 return true;
 
diff --git a/crypto/src/crypto/tls/TlsEccUtilities.cs b/crypto/src/crypto/tls/TlsEccUtilities.cs
index 49e868ab9..5760566f5 100644
--- a/crypto/src/crypto/tls/TlsEccUtilities.cs
+++ b/crypto/src/crypto/tls/TlsEccUtilities.cs
@@ -254,10 +254,11 @@ namespace Org.BouncyCastle.Crypto.Tls
             case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_256_CCM_8:
 
             /*
-             * draft-agl-tls-chacha20poly1305-04
+             * draft-ietf-tls-chacha20-poly1305-04
              */
-            case CipherSuite.TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256:
-            case CipherSuite.TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256:
+            case CipherSuite.DRAFT_TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256:
+            case CipherSuite.DRAFT_TLS_ECDHE_PSK_WITH_CHACHA20_POLY1305_SHA256:
+            case CipherSuite.DRAFT_TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256:
 
                 return true;
 
diff --git a/crypto/src/crypto/tls/TlsProtocol.cs b/crypto/src/crypto/tls/TlsProtocol.cs
index 99168b883..d6e2ce701 100644
--- a/crypto/src/crypto/tls/TlsProtocol.cs
+++ b/crypto/src/crypto/tls/TlsProtocol.cs
@@ -1148,6 +1148,7 @@ namespace Org.BouncyCastle.Crypto.Tls
             case CipherSuite.TLS_DHE_PSK_WITH_AES_128_GCM_SHA256:
             case CipherSuite.TLS_DHE_PSK_WITH_AES_256_CCM:
             case CipherSuite.TLS_DHE_PSK_WITH_CAMELLIA_128_GCM_SHA256:
+            case CipherSuite.DRAFT_TLS_DHE_PSK_WITH_CHACHA20_POLY1305_SHA256:
             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:
@@ -1158,7 +1159,7 @@ namespace Org.BouncyCastle.Crypto.Tls
             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_SHA256:
-            case CipherSuite.TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256:
+            case CipherSuite.DRAFT_TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256:
             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_CAMELLIA_128_CBC_SHA256:
@@ -1175,12 +1176,13 @@ namespace Org.BouncyCastle.Crypto.Tls
             case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_256_CCM_8:
             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_CHACHA20_POLY1305_SHA256:
+            case CipherSuite.DRAFT_TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256:
+            case CipherSuite.DRAFT_TLS_ECDHE_PSK_WITH_CHACHA20_POLY1305_SHA256:
             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_CAMELLIA_128_CBC_SHA256:
             case CipherSuite.TLS_ECDHE_RSA_WITH_CAMELLIA_128_GCM_SHA256:
-            case CipherSuite.TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256:
+            case CipherSuite.DRAFT_TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256:
             case CipherSuite.TLS_PSK_DHE_WITH_AES_128_CCM_8:
             case CipherSuite.TLS_PSK_DHE_WITH_AES_256_CCM_8:
             case CipherSuite.TLS_PSK_WITH_AES_128_CCM:
@@ -1189,8 +1191,10 @@ namespace Org.BouncyCastle.Crypto.Tls
             case CipherSuite.TLS_PSK_WITH_AES_256_CCM:
             case CipherSuite.TLS_PSK_WITH_AES_256_CCM_8:
             case CipherSuite.TLS_PSK_WITH_CAMELLIA_128_GCM_SHA256:
+            case CipherSuite.DRAFT_TLS_PSK_WITH_CHACHA20_POLY1305_SHA256:
             case CipherSuite.TLS_RSA_PSK_WITH_AES_128_GCM_SHA256:
             case CipherSuite.TLS_RSA_PSK_WITH_CAMELLIA_128_GCM_SHA256:
+            case CipherSuite.DRAFT_TLS_RSA_PSK_WITH_CHACHA20_POLY1305_SHA256:
             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:
diff --git a/crypto/src/crypto/tls/TlsUtilities.cs b/crypto/src/crypto/tls/TlsUtilities.cs
index 7ed66d9a4..e4f1101a8 100644
--- a/crypto/src/crypto/tls/TlsUtilities.cs
+++ b/crypto/src/crypto/tls/TlsUtilities.cs
@@ -1165,7 +1165,12 @@ namespace Org.BouncyCastle.Crypto.Tls
                 foreach (SignatureAndHashAlgorithm signatureAndHashAlgorithm in supportedSignatureAlgorithms)
                 {
                     byte hashAlgorithm = signatureAndHashAlgorithm.Hash;
-                    handshakeHash.TrackHashAlgorithm(hashAlgorithm);
+
+                    // TODO Support values in the "Reserved for Private Use" range
+                    if (!HashAlgorithm.IsPrivate(hashAlgorithm))
+                    {
+                        handshakeHash.TrackHashAlgorithm(hashAlgorithm);
+                    }
                 }
             }
         }
@@ -1236,7 +1241,7 @@ namespace Org.BouncyCastle.Crypto.Tls
             case EncryptionAlgorithm.AES_256_CCM_8:
             case EncryptionAlgorithm.CAMELLIA_128_GCM:
             case EncryptionAlgorithm.CAMELLIA_256_GCM:
-            case EncryptionAlgorithm.AEAD_CHACHA20_POLY1305:
+            case EncryptionAlgorithm.CHACHA20_POLY1305:
                 return CipherType.aead;
 
             case EncryptionAlgorithm.RC2_CBC_40:
@@ -1282,11 +1287,6 @@ namespace Org.BouncyCastle.Crypto.Tls
             case CipherSuite.TLS_SRP_SHA_WITH_3DES_EDE_CBC_SHA:
                 return EncryptionAlgorithm.cls_3DES_EDE_CBC;
 
-            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 EncryptionAlgorithm.AEAD_CHACHA20_POLY1305;
-
             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:
@@ -1485,7 +1485,16 @@ namespace Org.BouncyCastle.Crypto.Tls
             case CipherSuite.TLS_RSA_WITH_CAMELLIA_256_GCM_SHA384:
                 return EncryptionAlgorithm.CAMELLIA_256_GCM;
 
-                case CipherSuite.TLS_RSA_WITH_NULL_MD5:
+            case CipherSuite.DRAFT_TLS_DHE_PSK_WITH_CHACHA20_POLY1305_SHA256:
+            case CipherSuite.DRAFT_TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256:
+            case CipherSuite.DRAFT_TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256:
+            case CipherSuite.DRAFT_TLS_ECDHE_PSK_WITH_CHACHA20_POLY1305_SHA256:
+            case CipherSuite.DRAFT_TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256:
+            case CipherSuite.DRAFT_TLS_PSK_WITH_CHACHA20_POLY1305_SHA256:
+            case CipherSuite.DRAFT_TLS_RSA_PSK_WITH_CHACHA20_POLY1305_SHA256:
+                return EncryptionAlgorithm.CHACHA20_POLY1305;
+
+            case CipherSuite.TLS_RSA_WITH_NULL_MD5:
                 return EncryptionAlgorithm.NULL;
 
             case CipherSuite.TLS_DHE_PSK_WITH_NULL_SHA:
@@ -1605,6 +1614,7 @@ namespace Org.BouncyCastle.Crypto.Tls
             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.DRAFT_TLS_DHE_PSK_WITH_CHACHA20_POLY1305_SHA256:
             case CipherSuite.TLS_DHE_PSK_WITH_NULL_SHA:
             case CipherSuite.TLS_DHE_PSK_WITH_NULL_SHA256:
             case CipherSuite.TLS_DHE_PSK_WITH_NULL_SHA384:
@@ -1630,7 +1640,7 @@ namespace Org.BouncyCastle.Crypto.Tls
             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.DRAFT_TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256:
             case CipherSuite.TLS_DHE_RSA_WITH_SEED_CBC_SHA:
                 return KeyExchangeAlgorithm.DHE_RSA;
 
@@ -1679,7 +1689,7 @@ namespace Org.BouncyCastle.Crypto.Tls
             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.DRAFT_TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256:
             case CipherSuite.TLS_ECDHE_ECDSA_WITH_NULL_SHA:
             case CipherSuite.TLS_ECDHE_ECDSA_WITH_RC4_128_SHA:
                 return KeyExchangeAlgorithm.ECDHE_ECDSA;
@@ -1691,6 +1701,7 @@ namespace Org.BouncyCastle.Crypto.Tls
             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.DRAFT_TLS_ECDHE_PSK_WITH_CHACHA20_POLY1305_SHA256:
             case CipherSuite.TLS_ECDHE_PSK_WITH_NULL_SHA:
             case CipherSuite.TLS_ECDHE_PSK_WITH_NULL_SHA256:
             case CipherSuite.TLS_ECDHE_PSK_WITH_NULL_SHA384:
@@ -1708,7 +1719,7 @@ namespace Org.BouncyCastle.Crypto.Tls
             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.DRAFT_TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256:
             case CipherSuite.TLS_ECDHE_RSA_WITH_NULL_SHA:
             case CipherSuite.TLS_ECDHE_RSA_WITH_RC4_128_SHA:
                 return KeyExchangeAlgorithm.ECDHE_RSA;
@@ -1728,6 +1739,7 @@ namespace Org.BouncyCastle.Crypto.Tls
             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.DRAFT_TLS_PSK_WITH_CHACHA20_POLY1305_SHA256:
             case CipherSuite.TLS_PSK_WITH_NULL_SHA:
             case CipherSuite.TLS_PSK_WITH_NULL_SHA256:
             case CipherSuite.TLS_PSK_WITH_NULL_SHA384:
@@ -1751,6 +1763,7 @@ namespace Org.BouncyCastle.Crypto.Tls
             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.DRAFT_TLS_RSA_PSK_WITH_CHACHA20_POLY1305_SHA256:
             case CipherSuite.TLS_RSA_WITH_NULL_MD5:
             case CipherSuite.TLS_RSA_WITH_NULL_SHA:
             case CipherSuite.TLS_RSA_WITH_NULL_SHA256:
@@ -1818,9 +1831,10 @@ namespace Org.BouncyCastle.Crypto.Tls
             case CipherSuite.TLS_DHE_PSK_WITH_AES_256_GCM_SHA384:
             case CipherSuite.TLS_DHE_PSK_WITH_CAMELLIA_128_GCM_SHA256:
             case CipherSuite.TLS_DHE_PSK_WITH_CAMELLIA_256_GCM_SHA384:
+            case CipherSuite.DRAFT_TLS_DHE_PSK_WITH_CHACHA20_POLY1305_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_CHACHA20_POLY1305_SHA256:
+            case CipherSuite.DRAFT_TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256:
             case CipherSuite.TLS_DHE_RSA_WITH_AES_128_GCM_SHA256:
             case CipherSuite.TLS_DHE_RSA_WITH_AES_256_CCM:
             case CipherSuite.TLS_DHE_RSA_WITH_AES_256_CCM_8:
@@ -1843,12 +1857,13 @@ namespace Org.BouncyCastle.Crypto.Tls
             case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384:
             case CipherSuite.TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_GCM_SHA256:
             case CipherSuite.TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_GCM_SHA384:
-            case CipherSuite.TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256:
+            case CipherSuite.DRAFT_TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256:
+            case CipherSuite.DRAFT_TLS_ECDHE_PSK_WITH_CHACHA20_POLY1305_SHA256:
             case CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256:
             case CipherSuite.TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384:
             case CipherSuite.TLS_ECDHE_RSA_WITH_CAMELLIA_128_GCM_SHA256:
             case CipherSuite.TLS_ECDHE_RSA_WITH_CAMELLIA_256_GCM_SHA384:
-            case CipherSuite.TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256:
+            case CipherSuite.DRAFT_TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256:
             case CipherSuite.TLS_PSK_DHE_WITH_AES_128_CCM_8:
             case CipherSuite.TLS_PSK_DHE_WITH_AES_256_CCM_8:
             case CipherSuite.TLS_PSK_WITH_AES_128_CCM:
@@ -1859,10 +1874,12 @@ namespace Org.BouncyCastle.Crypto.Tls
             case CipherSuite.TLS_PSK_WITH_AES_256_GCM_SHA384:
             case CipherSuite.TLS_PSK_WITH_CAMELLIA_128_GCM_SHA256:
             case CipherSuite.TLS_PSK_WITH_CAMELLIA_256_GCM_SHA384:
+            case CipherSuite.DRAFT_TLS_PSK_WITH_CHACHA20_POLY1305_SHA256:
             case CipherSuite.TLS_RSA_PSK_WITH_AES_128_GCM_SHA256:
             case CipherSuite.TLS_RSA_PSK_WITH_AES_256_GCM_SHA384:
             case CipherSuite.TLS_RSA_PSK_WITH_CAMELLIA_128_GCM_SHA256:
             case CipherSuite.TLS_RSA_PSK_WITH_CAMELLIA_256_GCM_SHA384:
+            case CipherSuite.DRAFT_TLS_RSA_PSK_WITH_CHACHA20_POLY1305_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:
@@ -2068,6 +2085,7 @@ namespace Org.BouncyCastle.Crypto.Tls
             case CipherSuite.TLS_DHE_PSK_WITH_AES_256_GCM_SHA384:
             case CipherSuite.TLS_DHE_PSK_WITH_CAMELLIA_128_GCM_SHA256:
             case CipherSuite.TLS_DHE_PSK_WITH_CAMELLIA_256_GCM_SHA384:
+            case CipherSuite.DRAFT_TLS_DHE_PSK_WITH_CHACHA20_POLY1305_SHA256:
             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:
@@ -2080,7 +2098,7 @@ namespace Org.BouncyCastle.Crypto.Tls
             case CipherSuite.TLS_DHE_RSA_WITH_CAMELLIA_128_GCM_SHA256:
             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.DRAFT_TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256:
             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_SHA384:
@@ -2109,7 +2127,8 @@ namespace Org.BouncyCastle.Crypto.Tls
             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.DRAFT_TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256:
+            case CipherSuite.DRAFT_TLS_ECDHE_PSK_WITH_CHACHA20_POLY1305_SHA256:
             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_SHA384:
@@ -2118,7 +2137,7 @@ namespace Org.BouncyCastle.Crypto.Tls
             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.DRAFT_TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256:
             case CipherSuite.TLS_PSK_DHE_WITH_AES_128_CCM_8:
             case CipherSuite.TLS_PSK_DHE_WITH_AES_256_CCM_8:
             case CipherSuite.TLS_PSK_WITH_AES_128_CCM:
@@ -2129,10 +2148,12 @@ namespace Org.BouncyCastle.Crypto.Tls
             case CipherSuite.TLS_PSK_WITH_AES_256_GCM_SHA384:
             case CipherSuite.TLS_PSK_WITH_CAMELLIA_128_GCM_SHA256:
             case CipherSuite.TLS_PSK_WITH_CAMELLIA_256_GCM_SHA384:
+            case CipherSuite.DRAFT_TLS_PSK_WITH_CHACHA20_POLY1305_SHA256:
             case CipherSuite.TLS_RSA_PSK_WITH_AES_128_GCM_SHA256:
             case CipherSuite.TLS_RSA_PSK_WITH_AES_256_GCM_SHA384:
             case CipherSuite.TLS_RSA_PSK_WITH_CAMELLIA_128_GCM_SHA256:
             case CipherSuite.TLS_RSA_PSK_WITH_CAMELLIA_256_GCM_SHA384:
+            case CipherSuite.DRAFT_TLS_RSA_PSK_WITH_CHACHA20_POLY1305_SHA256:
             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: