summary refs log tree commit diff
path: root/crypto/src/tls/TlsUtilities.cs
diff options
context:
space:
mode:
Diffstat (limited to 'crypto/src/tls/TlsUtilities.cs')
-rw-r--r--crypto/src/tls/TlsUtilities.cs265
1 files changed, 122 insertions, 143 deletions
diff --git a/crypto/src/tls/TlsUtilities.cs b/crypto/src/tls/TlsUtilities.cs
index 1e0b403c9..97895e8f2 100644
--- a/crypto/src/tls/TlsUtilities.cs
+++ b/crypto/src/tls/TlsUtilities.cs
@@ -1,9 +1,7 @@
 using System;
-using System.Collections;
+using System.Collections.Generic;
 using System.IO;
-#if !PORTABLE || DOTNET
 using System.Net.Sockets;
-#endif
 
 using Org.BouncyCastle.Asn1;
 using Org.BouncyCastle.Asn1.Bsi;
@@ -18,6 +16,7 @@ using Org.BouncyCastle.Asn1.X9;
 using Org.BouncyCastle.Math;
 using Org.BouncyCastle.Tls.Crypto;
 using Org.BouncyCastle.Utilities;
+using Org.BouncyCastle.Utilities.Collections;
 using Org.BouncyCastle.Utilities.Date;
 using Org.BouncyCastle.Utilities.Encoders;
 using Org.BouncyCastle.Utilities.IO;
@@ -29,24 +28,24 @@ namespace Org.BouncyCastle.Tls
         private static readonly byte[] DowngradeTlsV11 = Hex.DecodeStrict("444F574E47524400");
         private static readonly byte[] DowngradeTlsV12 = Hex.DecodeStrict("444F574E47524401");
 
-        private static readonly IDictionary CertSigAlgOids = CreateCertSigAlgOids();
-        private static readonly IList DefaultSupportedSigAlgs = CreateDefaultSupportedSigAlgs();
+        private static readonly IDictionary<string, SignatureAndHashAlgorithm> CertSigAlgOids = CreateCertSigAlgOids();
+        private static readonly IList<SignatureAndHashAlgorithm> DefaultSupportedSigAlgs = CreateDefaultSupportedSigAlgs();
 
-        private static void AddCertSigAlgOid(IDictionary d, DerObjectIdentifier oid,
+        private static void AddCertSigAlgOid(IDictionary<string, SignatureAndHashAlgorithm> d, DerObjectIdentifier oid,
             SignatureAndHashAlgorithm sigAndHash)
         {
             d[oid.Id] = sigAndHash;
         }
 
-        private static void AddCertSigAlgOid(IDictionary d, DerObjectIdentifier oid, short hashAlgorithm,
-            short signatureAlgorithm)
+        private static void AddCertSigAlgOid(IDictionary<string, SignatureAndHashAlgorithm> d, DerObjectIdentifier oid,
+            short hashAlgorithm, short signatureAlgorithm)
         {
             AddCertSigAlgOid(d, oid, SignatureAndHashAlgorithm.GetInstance(hashAlgorithm, signatureAlgorithm));
         }
 
-        private static IDictionary CreateCertSigAlgOids()
+        private static IDictionary<string, SignatureAndHashAlgorithm> CreateCertSigAlgOids()
         {
-            IDictionary d = Platform.CreateHashtable();
+            var d = new Dictionary<string, SignatureAndHashAlgorithm>();
 
             AddCertSigAlgOid(d, NistObjectIdentifiers.DsaWithSha224, HashAlgorithm.sha224, SignatureAlgorithm.dsa);
             AddCertSigAlgOid(d, NistObjectIdentifiers.DsaWithSha256, HashAlgorithm.sha256, SignatureAlgorithm.dsa);
@@ -97,9 +96,9 @@ namespace Org.BouncyCastle.Tls
             return d;
         }
 
-        private static IList CreateDefaultSupportedSigAlgs()
+        private static IList<SignatureAndHashAlgorithm> CreateDefaultSupportedSigAlgs()
         {
-            IList result = Platform.CreateArrayList();
+            var result = new List<SignatureAndHashAlgorithm>();
             result.Add(SignatureAndHashAlgorithm.ed25519);
             result.Add(SignatureAndHashAlgorithm.ed448);
             result.Add(SignatureAndHashAlgorithm.GetInstance(HashAlgorithm.sha256, SignatureAlgorithm.ecdsa));
@@ -970,7 +969,8 @@ namespace Org.BouncyCastle.Tls
             buf[offset + 1] = (byte)version.MinorVersion;
         }
 
-        public static void AddIfSupported(IList supportedAlgs, TlsCrypto crypto, SignatureAndHashAlgorithm alg)
+        public static void AddIfSupported(IList<SignatureAndHashAlgorithm> supportedAlgs, TlsCrypto crypto,
+            SignatureAndHashAlgorithm alg)
         {
             if (crypto.HasSignatureAndHashAlgorithm(alg))
             {
@@ -978,7 +978,7 @@ namespace Org.BouncyCastle.Tls
             }
         }
 
-        public static void AddIfSupported(IList supportedGroups, TlsCrypto crypto, int namedGroup)
+        public static void AddIfSupported(IList<int> supportedGroups, TlsCrypto crypto, int namedGroup)
         {
             if (crypto.HasNamedGroup(namedGroup))
             {
@@ -986,7 +986,7 @@ namespace Org.BouncyCastle.Tls
             }
         }
 
-        public static void AddIfSupported(IList supportedGroups, TlsCrypto crypto, int[] namedGroups)
+        public static void AddIfSupported(IList<int> supportedGroups, TlsCrypto crypto, int[] namedGroups)
         {
             for (int i = 0; i < namedGroups.Length; ++i)
             {
@@ -994,7 +994,7 @@ namespace Org.BouncyCastle.Tls
             }
         }
 
-        public static bool AddToSet(IList s, int i)
+        public static bool AddToSet<T>(IList<T> s, T i)
         {
             bool result = !s.Contains(i);
             if (result)
@@ -1004,17 +1004,17 @@ namespace Org.BouncyCastle.Tls
             return result;
         }
 
-        public static IList GetDefaultDssSignatureAlgorithms()
+        public static IList<SignatureAndHashAlgorithm> GetDefaultDssSignatureAlgorithms()
         {
             return GetDefaultSignatureAlgorithms(SignatureAlgorithm.dsa);
         }
 
-        public static IList GetDefaultECDsaSignatureAlgorithms()
+        public static IList<SignatureAndHashAlgorithm> GetDefaultECDsaSignatureAlgorithms()
         {
             return GetDefaultSignatureAlgorithms(SignatureAlgorithm.ecdsa);
         }
 
-        public static IList GetDefaultRsaSignatureAlgorithms()
+        public static IList<SignatureAndHashAlgorithm> GetDefaultRsaSignatureAlgorithms()
         {
             return GetDefaultSignatureAlgorithms(SignatureAlgorithm.rsa);
         }
@@ -1046,23 +1046,24 @@ namespace Org.BouncyCastle.Tls
             }
         }
 
-        public static IList GetDefaultSignatureAlgorithms(short signatureAlgorithm)
+        public static IList<SignatureAndHashAlgorithm> GetDefaultSignatureAlgorithms(short signatureAlgorithm)
         {
             SignatureAndHashAlgorithm sigAndHashAlg = GetDefaultSignatureAlgorithm(signatureAlgorithm);
 
-            return null == sigAndHashAlg ? Platform.CreateArrayList() : VectorOfOne(sigAndHashAlg);
+            return null == sigAndHashAlg ? new List<SignatureAndHashAlgorithm>() : VectorOfOne(sigAndHashAlg);
         }
 
-        public static IList GetDefaultSupportedSignatureAlgorithms(TlsContext context)
+        public static IList<SignatureAndHashAlgorithm> GetDefaultSupportedSignatureAlgorithms(TlsContext context)
         {
             return GetSupportedSignatureAlgorithms(context, DefaultSupportedSigAlgs);
         }
 
-        public static IList GetSupportedSignatureAlgorithms(TlsContext context, IList candidates)
+        public static IList<SignatureAndHashAlgorithm> GetSupportedSignatureAlgorithms(TlsContext context,
+            IList<SignatureAndHashAlgorithm> candidates)
         {
             TlsCrypto crypto = context.Crypto;
 
-            IList result = Platform.CreateArrayList(DefaultSupportedSigAlgs.Count);
+            var result = new List<SignatureAndHashAlgorithm>(candidates.Count);
             foreach (SignatureAndHashAlgorithm sigAndHashAlg in candidates)
             {
                 AddIfSupported(result, crypto, sigAndHashAlg);
@@ -1088,14 +1089,15 @@ namespace Org.BouncyCastle.Tls
             return signatureAndHashAlgorithm;
         }
 
-        public static byte[] GetExtensionData(IDictionary extensions, int extensionType)
+        public static byte[] GetExtensionData(IDictionary<int, byte[]> extensions, int extensionType)
         {
-            return extensions == null || !extensions.Contains(extensionType)
-                ? null
-                : (byte[])extensions[extensionType];
+            if (extensions == null || !extensions.TryGetValue(extensionType, out var extensionData))
+                return null;
+
+            return extensionData;
         }
 
-        public static bool HasExpectedEmptyExtensionData(IDictionary extensions, int extensionType,
+        public static bool HasExpectedEmptyExtensionData(IDictionary<int, byte[]> extensions, int extensionType,
             short alertDescription)
         {
             byte[] extension_data = GetExtensionData(extensions, extensionType);
@@ -1140,22 +1142,7 @@ namespace Org.BouncyCastle.Tls
             return false;
         }
 
-        public static bool IsNullOrEmpty(byte[] array)
-        {
-            return null == array || array.Length < 1;
-        }
-
-        public static bool IsNullOrEmpty(short[] array)
-        {
-            return null == array || array.Length < 1;
-        }
-
-        public static bool IsNullOrEmpty(int[] array)
-        {
-            return null == array || array.Length < 1;
-        }
-
-        public static bool IsNullOrEmpty(object[] array)
+        public static bool IsNullOrEmpty<T>(T[] array)
         {
             return null == array || array.Length < 1;
         }
@@ -1165,7 +1152,7 @@ namespace Org.BouncyCastle.Tls
             return null == s || s.Length < 1;
         }
 
-        public static bool IsNullOrEmpty(IList v)
+        public static bool IsNullOrEmpty<T>(IList<T> v)
         {
             return null == v || v.Count < 1;
         }
@@ -1275,9 +1262,9 @@ namespace Org.BouncyCastle.Tls
             }
         }
 
-        public static IList GetLegacySupportedSignatureAlgorithms()
+        public static IList<SignatureAndHashAlgorithm> GetLegacySupportedSignatureAlgorithms()
         {
-            IList result = Platform.CreateArrayList(3);
+            var result = new List<SignatureAndHashAlgorithm>(3);
             result.Add(SignatureAndHashAlgorithm.GetInstance(HashAlgorithm.sha1, SignatureAlgorithm.dsa));
             result.Add(SignatureAndHashAlgorithm.GetInstance(HashAlgorithm.sha1, SignatureAlgorithm.ecdsa));
             result.Add(SignatureAndHashAlgorithm.GetInstance(HashAlgorithm.sha1, SignatureAlgorithm.rsa));
@@ -1285,10 +1272,12 @@ namespace Org.BouncyCastle.Tls
         }
 
         /// <exception cref="IOException"/>
-        public static void EncodeSupportedSignatureAlgorithms(IList supportedSignatureAlgorithms, Stream output)
+        public static void EncodeSupportedSignatureAlgorithms(
+            IList<SignatureAndHashAlgorithm> supportedSignatureAlgorithms, Stream output)
         {
-            if (supportedSignatureAlgorithms == null || supportedSignatureAlgorithms.Count < 1
-                || supportedSignatureAlgorithms.Count >= (1 << 15))
+            if (supportedSignatureAlgorithms == null ||
+                supportedSignatureAlgorithms.Count < 1 ||
+                supportedSignatureAlgorithms.Count >= (1 << 15))
             {
                 throw new ArgumentException("must have length from 1 to (2^15 - 1)", "supportedSignatureAlgorithms");
             }
@@ -1313,7 +1302,7 @@ namespace Org.BouncyCastle.Tls
         }
 
         /// <exception cref="IOException"/>
-        public static IList ParseSupportedSignatureAlgorithms(Stream input)
+        public static IList<SignatureAndHashAlgorithm> ParseSupportedSignatureAlgorithms(Stream input)
         {
             // supported_signature_algorithms
             int length = ReadUint16(input);
@@ -1321,7 +1310,7 @@ namespace Org.BouncyCastle.Tls
                 throw new TlsFatalAlert(AlertDescription.decode_error);
 
             int count = length / 2;
-            IList supportedSignatureAlgorithms = Platform.CreateArrayList(count);
+            var supportedSignatureAlgorithms = new List<SignatureAndHashAlgorithm>(count);
             for (int i = 0; i < count; ++i)
             {
                 SignatureAndHashAlgorithm sigAndHashAlg = SignatureAndHashAlgorithm.Parse(input);
@@ -1335,16 +1324,17 @@ namespace Org.BouncyCastle.Tls
         }
 
         /// <exception cref="IOException"/>
-        public static void VerifySupportedSignatureAlgorithm(IList supportedSignatureAlgorithms,
-            SignatureAndHashAlgorithm signatureAlgorithm)
+        public static void VerifySupportedSignatureAlgorithm(
+            IList<SignatureAndHashAlgorithm> supportedSignatureAlgorithms, SignatureAndHashAlgorithm signatureAlgorithm)
         {
             VerifySupportedSignatureAlgorithm(supportedSignatureAlgorithms, signatureAlgorithm,
                 AlertDescription.illegal_parameter);
         }
 
         /// <exception cref="IOException"/>
-        internal static void VerifySupportedSignatureAlgorithm(IList supportedSignatureAlgorithms,
-            SignatureAndHashAlgorithm signatureAlgorithm, short alertDescription)
+        internal static void VerifySupportedSignatureAlgorithm(
+            IList<SignatureAndHashAlgorithm> supportedSignatureAlgorithms, SignatureAndHashAlgorithm signatureAlgorithm,
+            short alertDescription)
         {
             if (supportedSignatureAlgorithms == null || supportedSignatureAlgorithms.Count < 1
                 || supportedSignatureAlgorithms.Count >= (1 << 15))
@@ -1362,7 +1352,7 @@ namespace Org.BouncyCastle.Tls
         }
 
         /// <exception cref="IOException"/>
-        public static bool ContainsSignatureAlgorithm(IList supportedSignatureAlgorithms,
+        public static bool ContainsSignatureAlgorithm(IList<SignatureAndHashAlgorithm> supportedSignatureAlgorithms,
             SignatureAndHashAlgorithm signatureAlgorithm)
         {
             foreach (SignatureAndHashAlgorithm entry in supportedSignatureAlgorithms)
@@ -1374,7 +1364,8 @@ namespace Org.BouncyCastle.Tls
             return false;
         }
 
-        public static bool ContainsAnySignatureAlgorithm(IList supportedSignatureAlgorithms, short signatureAlgorithm)
+        public static bool ContainsAnySignatureAlgorithm(IList<SignatureAndHashAlgorithm> supportedSignatureAlgorithms,
+            short signatureAlgorithm)
         {
             foreach (SignatureAndHashAlgorithm entry in supportedSignatureAlgorithms)
             {
@@ -1464,9 +1455,9 @@ namespace Org.BouncyCastle.Tls
                 }
                 else
                 {
-                    if (CertSigAlgOids.Contains(sigAlgOid))
+                    if (CertSigAlgOids.TryGetValue(sigAlgOid, out var algorithm))
                     {
-                        hashAlgorithm = ((SignatureAndHashAlgorithm)CertSigAlgOids[sigAlgOid]).Hash;
+                        hashAlgorithm = algorithm.Hash;
                     }
                 }
             }
@@ -2271,7 +2262,7 @@ namespace Org.BouncyCastle.Tls
         {
             SecurityParameters securityParameters = serverContext.SecurityParameters;
 
-            IList supportedAlgorithms = securityParameters.ServerSigAlgs;
+            var supportedAlgorithms = securityParameters.ServerSigAlgs;
             TlsCertificate certificate = securityParameters.PeerCertificate.GetCertificateAt(0);
 
             Verify13CertificateVerify(supportedAlgorithms, "TLS 1.3, client CertificateVerify", handshakeHash,
@@ -2284,7 +2275,7 @@ namespace Org.BouncyCastle.Tls
         {
             SecurityParameters securityParameters = clientContext.SecurityParameters;
 
-            IList supportedAlgorithms = securityParameters.ClientSigAlgs;
+            var supportedAlgorithms = securityParameters.ClientSigAlgs;
             TlsCertificate certificate = securityParameters.PeerCertificate.GetCertificateAt(0);
 
             Verify13CertificateVerify(supportedAlgorithms, "TLS 1.3, server CertificateVerify", handshakeHash,
@@ -2292,8 +2283,9 @@ namespace Org.BouncyCastle.Tls
         }
 
         /// <exception cref="IOException"/>
-        private static void Verify13CertificateVerify(IList supportedAlgorithms, string contextString,
-            TlsHandshakeHash handshakeHash, TlsCertificate certificate, CertificateVerify certificateVerify)
+        private static void Verify13CertificateVerify(IList<SignatureAndHashAlgorithm> supportedAlgorithms,
+            string contextString, TlsHandshakeHash handshakeHash, TlsCertificate certificate,
+            CertificateVerify certificateVerify)
         {
             // Verify the CertificateVerify message contains a correct signature.
             bool verified;
@@ -2430,7 +2422,8 @@ namespace Org.BouncyCastle.Tls
             }
         }
 
-        internal static void TrackHashAlgorithms(TlsHandshakeHash handshakeHash, IList supportedSignatureAlgorithms)
+        internal static void TrackHashAlgorithms(TlsHandshakeHash handshakeHash,
+            IList<SignatureAndHashAlgorithm> supportedSignatureAlgorithms)
         {
             foreach (SignatureAndHashAlgorithm signatureAndHashAlgorithm in supportedSignatureAlgorithms)
             {
@@ -2459,9 +2452,9 @@ namespace Org.BouncyCastle.Tls
             }
         }
 
-        public static IList VectorOfOne(object obj)
+        public static IList<T> VectorOfOne<T>(T obj)
         {
-            IList v = Platform.CreateArrayList(1);
+            var v = new List<T>(1);
             v.Add(obj);
             return v;
         }
@@ -3203,9 +3196,9 @@ namespace Org.BouncyCastle.Tls
             }
         }
 
-        public static IList GetKeyExchangeAlgorithms(int[] cipherSuites)
+        public static IList<int> GetKeyExchangeAlgorithms(int[] cipherSuites)
         {
-            IList result = Platform.CreateArrayList();
+            var result = new List<int>();
             if (null != cipherSuites)
             {
                 for (int i = 0; i < cipherSuites.Length; ++i)
@@ -3723,14 +3716,14 @@ namespace Org.BouncyCastle.Tls
             }
         }
 
-        public static IList GetNamedGroupRoles(int[] cipherSuites)
+        public static IList<int> GetNamedGroupRoles(int[] cipherSuites)
         {
             return GetNamedGroupRoles(GetKeyExchangeAlgorithms(cipherSuites));
         }
 
-        public static IList GetNamedGroupRoles(IList keyExchangeAlgorithms)
+        public static IList<int> GetNamedGroupRoles(IList<int> keyExchangeAlgorithms)
         {
-            IList result = Platform.CreateArrayList();
+            var result = new List<int>();
             foreach (int keyExchangeAlgorithm in keyExchangeAlgorithms)
             {
                 switch (keyExchangeAlgorithm)
@@ -3795,7 +3788,7 @@ namespace Org.BouncyCastle.Tls
 
         /// <returns>Whether a server can select the specified cipher suite given the available signature algorithms
         /// for ServerKeyExchange.</returns>
-        public static bool IsValidCipherSuiteForSignatureAlgorithms(int cipherSuite, IList sigAlgs)
+        public static bool IsValidCipherSuiteForSignatureAlgorithms(int cipherSuite, IList<short> sigAlgs)
         {
             int keyExchangeAlgorithm = GetKeyExchangeAlgorithm(cipherSuite);
 
@@ -3832,11 +3825,11 @@ namespace Org.BouncyCastle.Tls
         }
 
         internal static bool IsValidKeyShareSelection(ProtocolVersion negotiatedVersion, int[] clientSupportedGroups,
-            IDictionary clientAgreements, int keyShareGroup)
+            IDictionary<int, TlsAgreement> clientAgreements, int keyShareGroup)
         {
             return null != clientSupportedGroups
                 && Arrays.Contains(clientSupportedGroups, keyShareGroup)
-                && !clientAgreements.Contains(keyShareGroup)
+                && !clientAgreements.ContainsKey(keyShareGroup)
                 && NamedGroup.CanBeNegotiated(keyShareGroup, negotiatedVersion);
         }
 
@@ -3910,20 +3903,19 @@ namespace Org.BouncyCastle.Tls
         }
 
         /// <exception cref="IOException"/>
-        public static SignatureAndHashAlgorithm ChooseSignatureAndHashAlgorithm(TlsContext context, IList sigHashAlgs,
-            short signatureAlgorithm)
+        public static SignatureAndHashAlgorithm ChooseSignatureAndHashAlgorithm(TlsContext context,
+            IList<SignatureAndHashAlgorithm> sigHashAlgs, short signatureAlgorithm)
         {
             return ChooseSignatureAndHashAlgorithm(context.ServerVersion, sigHashAlgs, signatureAlgorithm);
         }
 
         /// <exception cref="IOException"/>
         public static SignatureAndHashAlgorithm ChooseSignatureAndHashAlgorithm(ProtocolVersion negotiatedVersion,
-            IList sigHashAlgs, short signatureAlgorithm)
+            IList<SignatureAndHashAlgorithm> sigHashAlgs, short signatureAlgorithm)
         {
             if (!IsTlsV12(negotiatedVersion))
                 return null;
 
-
             if (sigHashAlgs == null)
             {
                 /*
@@ -3972,33 +3964,25 @@ namespace Org.BouncyCastle.Tls
             return result;
         }
 
-        public static IList GetUsableSignatureAlgorithms(IList sigHashAlgs)
+        public static IList<short> GetUsableSignatureAlgorithms(IList<SignatureAndHashAlgorithm> sigHashAlgs)
         {
             if (sigHashAlgs == null)
+                return new List<short>(){ SignatureAlgorithm.rsa, SignatureAlgorithm.dsa, SignatureAlgorithm.ecdsa };
+
+            var v = new List<short>();
+            foreach (SignatureAndHashAlgorithm sigHashAlg in sigHashAlgs)
             {
-                IList v = Platform.CreateArrayList(3);
-                v.Add(SignatureAlgorithm.rsa);
-                v.Add(SignatureAlgorithm.dsa);
-                v.Add(SignatureAlgorithm.ecdsa);
-                return v;
-            }
-            else
-            {
-                IList v = Platform.CreateArrayList();
-                foreach (SignatureAndHashAlgorithm sigHashAlg in sigHashAlgs)
+                if (sigHashAlg.Hash >= MinimumHashStrict)
                 {
-                    if (sigHashAlg.Hash >= MinimumHashStrict)
+                    short sigAlg = sigHashAlg.Signature;
+                    if (!v.Contains(sigAlg))
                     {
-                        short sigAlg = sigHashAlg.Signature;
-                        if (!v.Contains(sigAlg))
-                        {
-                            // TODO Check for crypto support before choosing (or pass in cached list?)
-                            v.Add(sigAlg);
-                        }
+                        // TODO Check for crypto support before choosing (or pass in cached list?)
+                        v.Add(sigAlg);
                     }
                 }
-                return v;
             }
+            return v;
         }
 
         public static int GetCommonCipherSuite13(ProtocolVersion negotiatedVersion, int[] peerCipherSuites,
@@ -4355,7 +4339,7 @@ namespace Org.BouncyCastle.Tls
         {
             SecurityParameters securityParameters = context.SecurityParameters;
             short[] clientCertTypes = securityParameters.ClientCertTypes;
-            IList serverSigAlgsCert = securityParameters.ServerSigAlgsCert;
+            var serverSigAlgsCert = securityParameters.ServerSigAlgsCert;
 
             int trustAnchorPos = clientCertPath.Length - 1;
             for (int i = 0; i < trustAnchorPos; ++i)
@@ -4405,8 +4389,8 @@ namespace Org.BouncyCastle.Tls
         private static void CheckSigAlgOfServerCerts(TlsContext context, TlsCertificate[] serverCertPath)
         {
             SecurityParameters securityParameters = context.SecurityParameters;
-            IList clientSigAlgsCert = securityParameters.ClientSigAlgsCert;
-            IList clientSigAlgs = securityParameters.ClientSigAlgs;
+            var clientSigAlgsCert = securityParameters.ClientSigAlgsCert;
+            var clientSigAlgs = securityParameters.ClientSigAlgs;
 
             /*
              * NOTE: For TLS 1.2, we'll check 'signature_algorithms' too (if it's distinct), since
@@ -4457,8 +4441,8 @@ namespace Org.BouncyCastle.Tls
             }
         }
 
-        internal static void CheckTlsFeatures(Certificate serverCertificate, IDictionary clientExtensions,
-            IDictionary serverExtensions)
+        internal static void CheckTlsFeatures(Certificate serverCertificate, IDictionary<int, byte[]> clientExtensions,
+            IDictionary<int, byte[]> serverExtensions)
         {
             /*
              * RFC 7633 4.3.3. A client MUST treat a certificate with a TLS feature extension as an
@@ -4485,7 +4469,7 @@ namespace Org.BouncyCastle.Tls
                     {
                         int extensionType = tlsExtension.IntValueExact;
 
-                        if (clientExtensions.Contains(extensionType) && !serverExtensions.Contains(extensionType))
+                        if (clientExtensions.ContainsKey(extensionType) && !serverExtensions.ContainsKey(extensionType))
                             throw new TlsFatalAlert(AlertDescription.certificate_unknown);
                     }
                 }
@@ -4533,7 +4517,8 @@ namespace Org.BouncyCastle.Tls
 
         internal static void ProcessServerCertificate(TlsClientContext clientContext,
             CertificateStatus serverCertificateStatus, TlsKeyExchange keyExchange,
-            TlsAuthentication clientAuthentication, IDictionary clientExtensions, IDictionary serverExtensions)
+            TlsAuthentication clientAuthentication, IDictionary<int, byte[]> clientExtensions,
+            IDictionary<int, byte[]> serverExtensions)
         {
             SecurityParameters securityParameters = clientContext.SecurityParameters;
             bool isTlsV13 = IsTlsV13(securityParameters.NegotiatedVersion);
@@ -4569,12 +4554,7 @@ namespace Org.BouncyCastle.Tls
             if (null != sigAlgOid)
             {
                 if (!PkcsObjectIdentifiers.IdRsassaPss.Id.Equals(sigAlgOid))
-                {
-                    if (!CertSigAlgOids.Contains(sigAlgOid))
-                        return null;
-
-                    return (SignatureAndHashAlgorithm)CertSigAlgOids[sigAlgOid];
-                }
+                    return CollectionUtilities.GetValueOrNull(CertSigAlgOids, sigAlgOid);
 
                 RsassaPssParameters pssParams = RsassaPssParameters.GetInstance(subjectCert.GetSigAlgParams());
                 if (null != pssParams)
@@ -4871,8 +4851,8 @@ namespace Org.BouncyCastle.Tls
             return false;
         }
 
-        internal static IDictionary AddKeyShareToClientHello(TlsClientContext clientContext, TlsClient client,
-            IDictionary clientExtensions)
+        internal static IDictionary<int, TlsAgreement> AddKeyShareToClientHello(TlsClientContext clientContext,
+            TlsClient client, IDictionary<int, byte[]> clientExtensions)
         {
             /*
              * RFC 8446 9.2. If containing a "supported_groups" extension, it MUST also contain a
@@ -4880,15 +4860,15 @@ namespace Org.BouncyCastle.Tls
              * permitted.
              */
             if (!IsTlsV13(clientContext.ClientVersion)
-                || !clientExtensions.Contains(ExtensionType.supported_groups))
+                || !clientExtensions.ContainsKey(ExtensionType.supported_groups))
             {
                 return null;
             }
 
-            int[] supportedGroups = TlsExtensionsUtilities.GetSupportedGroupsExtension(clientExtensions);
-            IList keyShareGroups = client.GetEarlyKeyShareGroups();
-            IDictionary clientAgreements = Platform.CreateHashtable(3);
-            IList clientShares = Platform.CreateArrayList(2);
+            var supportedGroups = TlsExtensionsUtilities.GetSupportedGroupsExtension(clientExtensions);
+            var keyShareGroups = client.GetEarlyKeyShareGroups();
+            var clientAgreements = new Dictionary<int, TlsAgreement>(3);
+            var clientShares = new List<KeyShareEntry>(2);
 
             CollectKeyShares(clientContext.Crypto, supportedGroups, keyShareGroups, clientAgreements, clientShares);
 
@@ -4898,13 +4878,13 @@ namespace Org.BouncyCastle.Tls
             return clientAgreements;
         }
 
-        internal static IDictionary AddKeyShareToClientHelloRetry(TlsClientContext clientContext,
-            IDictionary clientExtensions, int keyShareGroup)
+        internal static IDictionary<int, TlsAgreement> AddKeyShareToClientHelloRetry(TlsClientContext clientContext,
+            IDictionary<int, byte[]> clientExtensions, int keyShareGroup)
         {
             int[] supportedGroups = new int[]{ keyShareGroup };
-            IList keyShareGroups = VectorOfOne(keyShareGroup);
-            IDictionary clientAgreements = Platform.CreateHashtable(1);
-            IList clientShares = Platform.CreateArrayList(1);
+            var keyShareGroups = VectorOfOne(keyShareGroup);
+            var clientAgreements = new Dictionary<int, TlsAgreement>(1);
+            var clientShares = new List<KeyShareEntry>(1);
 
             CollectKeyShares(clientContext.Crypto, supportedGroups, keyShareGroups, clientAgreements, clientShares);
 
@@ -4919,8 +4899,8 @@ namespace Org.BouncyCastle.Tls
             return clientAgreements;
         }
 
-        private static void CollectKeyShares(TlsCrypto crypto, int[] supportedGroups, IList keyShareGroups,
-            IDictionary clientAgreements, IList clientShares)
+        private static void CollectKeyShares(TlsCrypto crypto, int[] supportedGroups, IList<int> keyShareGroups,
+            IDictionary<int, TlsAgreement> clientAgreements, IList<KeyShareEntry> clientShares)
         {
             if (IsNullOrEmpty(supportedGroups))
                 return;
@@ -4933,7 +4913,7 @@ namespace Org.BouncyCastle.Tls
                 int supportedGroup = supportedGroups[i];
 
                 if (!keyShareGroups.Contains(supportedGroup)
-                    || clientAgreements.Contains(supportedGroup)
+                    || clientAgreements.ContainsKey(supportedGroup)
                     || !crypto.HasNamedGroup(supportedGroup))
                 {
                     continue;
@@ -4966,7 +4946,7 @@ namespace Org.BouncyCastle.Tls
             }
         }
 
-        internal static KeyShareEntry SelectKeyShare(IList clientShares, int keyShareGroup)
+        internal static KeyShareEntry SelectKeyShare(IList<KeyShareEntry> clientShares, int keyShareGroup)
         {
             if (null != clientShares && 1 == clientShares.Count)
             {
@@ -4980,7 +4960,7 @@ namespace Org.BouncyCastle.Tls
         }
 
         internal static KeyShareEntry SelectKeyShare(TlsCrypto crypto, ProtocolVersion negotiatedVersion,
-            IList clientShares, int[] clientSupportedGroups, int[] serverSupportedGroups)
+            IList<KeyShareEntry> clientShares, int[] clientSupportedGroups, int[] serverSupportedGroups)
         {
             if (null != clientShares && !IsNullOrEmpty(clientSupportedGroups) && !IsNullOrEmpty(serverSupportedGroups))
             {
@@ -5104,7 +5084,7 @@ namespace Org.BouncyCastle.Tls
         }
 
         internal static void EstablishClientSigAlgs(SecurityParameters securityParameters,
-            IDictionary clientExtensions)
+            IDictionary<int, byte[]> clientExtensions)
         {
             securityParameters.m_clientSigAlgs = TlsExtensionsUtilities.GetSignatureAlgorithmsExtension(
                 clientExtensions);
@@ -5429,7 +5409,8 @@ namespace Org.BouncyCastle.Tls
         }
 
         /// <exception cref="IOException"/>
-        internal static void CheckExtensionData13(IDictionary extensions, int handshakeType, short alertDescription)
+        internal static void CheckExtensionData13(IDictionary<int, byte[]> extensions, int handshakeType,
+            short alertDescription)
         {
             foreach (int extensionType in extensions.Keys)
             {
@@ -5451,17 +5432,15 @@ namespace Org.BouncyCastle.Tls
             return preMasterSecret;
         }
 
-#if !PORTABLE || DOTNET
         public static bool IsTimeout(SocketException e)
         {
             return SocketError.TimedOut == e.SocketErrorCode;
         }
-#endif
 
         /// <exception cref="IOException"/>
-        internal static void AddPreSharedKeyToClientExtensions(TlsPsk[] psks, IDictionary clientExtensions)
+        internal static void AddPreSharedKeyToClientExtensions(TlsPsk[] psks, IDictionary<int, byte[]> clientExtensions)
         {
-            IList identities = Platform.CreateArrayList(psks.Length);
+            var identities = new List<PskIdentity>(psks.Length);
             for (int i = 0; i < psks.Length; ++i)
             {
                 TlsPsk psk = psks[i];
@@ -5475,7 +5454,7 @@ namespace Org.BouncyCastle.Tls
 
         /// <exception cref="IOException"/>
         internal static OfferedPsks.BindersConfig AddPreSharedKeyToClientHello(TlsClientContext clientContext,
-            TlsClient client, IDictionary clientExtensions, int[] offeredCipherSuites)
+            TlsClient client, IDictionary<int, byte[]> clientExtensions, int[] offeredCipherSuites)
         {
             if (!IsTlsV13(clientContext.ClientVersion))
                 return null;
@@ -5501,13 +5480,13 @@ namespace Org.BouncyCastle.Tls
 
         /// <exception cref="IOException"/>
         internal static OfferedPsks.BindersConfig AddPreSharedKeyToClientHelloRetry(TlsClientContext clientContext,
-            OfferedPsks.BindersConfig clientBinders, IDictionary clientExtensions)
+            OfferedPsks.BindersConfig clientBinders, IDictionary<int, byte[]> clientExtensions)
         {
             SecurityParameters securityParameters = clientContext.SecurityParameters;
 
             int prfAlgorithm = GetPrfAlgorithm13(securityParameters.CipherSuite);
 
-            IList pskIndices = GetPskIndices(clientBinders.m_psks, prfAlgorithm);
+            var pskIndices = GetPskIndices(clientBinders.m_psks, prfAlgorithm);
             if (pskIndices.Count < 1)
                 return null;
 
@@ -5540,8 +5519,8 @@ namespace Org.BouncyCastle.Tls
         }
 
         internal static OfferedPsks.SelectedConfig SelectPreSharedKey(TlsServerContext serverContext, TlsServer server,
-            IDictionary clientHelloExtensions, HandshakeMessageInput clientHelloMessage, TlsHandshakeHash handshakeHash,
-            bool afterHelloRetryRequest)
+            IDictionary<int, byte[]> clientHelloExtensions, HandshakeMessageInput clientHelloMessage,
+            TlsHandshakeHash handshakeHash, bool afterHelloRetryRequest)
         {
             bool handshakeHashUpdated = false;
 
@@ -5633,7 +5612,7 @@ namespace Org.BouncyCastle.Tls
         /// <exception cref="IOException"/>
         internal static TlsPskExternal[] GetPskExternalsClient(TlsClient client, int[] offeredCipherSuites)
         {
-            IList externalPsks = client.GetExternalPsks();
+            var externalPsks = client.GetExternalPsks();
             if (IsNullOrEmpty(externalPsks))
                 return null;
 
@@ -5659,9 +5638,9 @@ namespace Org.BouncyCastle.Tls
             return result;
         }
 
-        internal static IList GetPskIndices(TlsPsk[] psks, int prfAlgorithm)
+        internal static IList<int> GetPskIndices(TlsPsk[] psks, int prfAlgorithm)
         {
-            IList v = Platform.CreateArrayList(psks.Length);
+            var v = new List<int>(psks.Length);
             for (int i = 0; i < psks.Length; ++i)
             {
                 if (psks[i].PrfAlgorithm == prfAlgorithm)