summary refs log tree commit diff
path: root/crypto/src/security/MacUtilities.cs
diff options
context:
space:
mode:
Diffstat (limited to 'crypto/src/security/MacUtilities.cs')
-rw-r--r--crypto/src/security/MacUtilities.cs212
1 files changed, 137 insertions, 75 deletions
diff --git a/crypto/src/security/MacUtilities.cs b/crypto/src/security/MacUtilities.cs
index 9490616be..76b2ed353 100644
--- a/crypto/src/security/MacUtilities.cs
+++ b/crypto/src/security/MacUtilities.cs
@@ -5,6 +5,7 @@ using Org.BouncyCastle.Asn1;
 using Org.BouncyCastle.Asn1.Iana;
 using Org.BouncyCastle.Asn1.Misc;
 using Org.BouncyCastle.Asn1.Nist;
+using Org.BouncyCastle.Asn1.Oiw;
 using Org.BouncyCastle.Asn1.Pkcs;
 using Org.BouncyCastle.Asn1.Rosstandart;
 using Org.BouncyCastle.Crypto;
@@ -21,69 +22,133 @@ namespace Org.BouncyCastle.Security
     /// </remarks>
     public static class MacUtilities
     {
-        private static readonly IDictionary<string, string> Algorithms =
+        private static readonly Dictionary<string, string> AlgorithmMap =
             new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
+        private static readonly Dictionary<DerObjectIdentifier, string> AlgorithmOidMap =
+            new Dictionary<DerObjectIdentifier, string>();
 
         static MacUtilities()
         {
-            Algorithms[IanaObjectIdentifiers.HmacMD5.Id] = "HMAC-MD5";
-            Algorithms[IanaObjectIdentifiers.HmacRipeMD160.Id] = "HMAC-RIPEMD160";
-            Algorithms[IanaObjectIdentifiers.HmacSha1.Id] = "HMAC-SHA1";
-            Algorithms[IanaObjectIdentifiers.HmacTiger.Id] = "HMAC-TIGER";
-
-            Algorithms[PkcsObjectIdentifiers.IdHmacWithSha1.Id] = "HMAC-SHA1";
-            Algorithms[MiscObjectIdentifiers.HMAC_SHA1.Id] = "HMAC-SHA1";
-            Algorithms[PkcsObjectIdentifiers.IdHmacWithSha224.Id] = "HMAC-SHA224";
-            Algorithms[PkcsObjectIdentifiers.IdHmacWithSha256.Id] = "HMAC-SHA256";
-            Algorithms[PkcsObjectIdentifiers.IdHmacWithSha384.Id] = "HMAC-SHA384";
-            Algorithms[PkcsObjectIdentifiers.IdHmacWithSha512.Id] = "HMAC-SHA512";
-
-            Algorithms[NistObjectIdentifiers.IdHMacWithSha3_224.Id] = "HMAC-SHA3-224";
-            Algorithms[NistObjectIdentifiers.IdHMacWithSha3_256.Id] = "HMAC-SHA3-256";
-            Algorithms[NistObjectIdentifiers.IdHMacWithSha3_384.Id] = "HMAC-SHA3-384";
-            Algorithms[NistObjectIdentifiers.IdHMacWithSha3_512.Id] = "HMAC-SHA3-512";
-
-            Algorithms[RosstandartObjectIdentifiers.id_tc26_hmac_gost_3411_12_256.Id] = "HMAC-GOST3411-2012-256";
-            Algorithms[RosstandartObjectIdentifiers.id_tc26_hmac_gost_3411_12_512.Id] = "HMAC-GOST3411-2012-512";
+            AlgorithmOidMap[IanaObjectIdentifiers.HmacMD5] = "HMAC-MD5";
+            AlgorithmOidMap[IanaObjectIdentifiers.HmacRipeMD160] = "HMAC-RIPEMD160";
+            AlgorithmOidMap[IanaObjectIdentifiers.HmacSha1] = "HMAC-SHA1";
+            AlgorithmOidMap[IanaObjectIdentifiers.HmacTiger] = "HMAC-TIGER";
+
+            AlgorithmOidMap[PkcsObjectIdentifiers.IdHmacWithSha1] = "HMAC-SHA1";
+            AlgorithmOidMap[MiscObjectIdentifiers.HMAC_SHA1] = "HMAC-SHA1";
+            AlgorithmOidMap[PkcsObjectIdentifiers.IdHmacWithSha224] = "HMAC-SHA224";
+            AlgorithmOidMap[PkcsObjectIdentifiers.IdHmacWithSha256] = "HMAC-SHA256";
+            AlgorithmOidMap[PkcsObjectIdentifiers.IdHmacWithSha384] = "HMAC-SHA384";
+            AlgorithmOidMap[PkcsObjectIdentifiers.IdHmacWithSha512] = "HMAC-SHA512";
+
+            AlgorithmOidMap[NistObjectIdentifiers.IdHMacWithSha3_224] = "HMAC-SHA3-224";
+            AlgorithmOidMap[NistObjectIdentifiers.IdHMacWithSha3_256] = "HMAC-SHA3-256";
+            AlgorithmOidMap[NistObjectIdentifiers.IdHMacWithSha3_384] = "HMAC-SHA3-384";
+            AlgorithmOidMap[NistObjectIdentifiers.IdHMacWithSha3_512] = "HMAC-SHA3-512";
+
+            AlgorithmOidMap[RosstandartObjectIdentifiers.id_tc26_hmac_gost_3411_12_256] = "HMAC-GOST3411-2012-256";
+            AlgorithmOidMap[RosstandartObjectIdentifiers.id_tc26_hmac_gost_3411_12_512] = "HMAC-GOST3411-2012-512";
 
             // TODO AESMAC?
 
-            Algorithms["DES"] = "DESMAC";
-            Algorithms["DES/CFB8"] = "DESMAC/CFB8";
-            Algorithms["DES64"] = "DESMAC64";
-            Algorithms["DESEDE"] = "DESEDEMAC";
-            Algorithms[PkcsObjectIdentifiers.DesEde3Cbc.Id] = "DESEDEMAC";
-            Algorithms["DESEDE/CFB8"] = "DESEDEMAC/CFB8";
-            Algorithms["DESISO9797MAC"] = "DESWITHISO9797";
-            Algorithms["DESEDE64"] = "DESEDEMAC64";
-
-            Algorithms["DESEDE64WITHISO7816-4PADDING"] = "DESEDEMAC64WITHISO7816-4PADDING";
-            Algorithms["DESEDEISO9797ALG1MACWITHISO7816-4PADDING"] = "DESEDEMAC64WITHISO7816-4PADDING";
-            Algorithms["DESEDEISO9797ALG1WITHISO7816-4PADDING"] = "DESEDEMAC64WITHISO7816-4PADDING";
-
-            Algorithms["ISO9797ALG3"] = "ISO9797ALG3MAC";
-            Algorithms["ISO9797ALG3MACWITHISO7816-4PADDING"] = "ISO9797ALG3WITHISO7816-4PADDING";
-
-            Algorithms["SKIPJACK"] = "SKIPJACKMAC";
-            Algorithms["SKIPJACK/CFB8"] = "SKIPJACKMAC/CFB8";
-            Algorithms["IDEA"] = "IDEAMAC";
-            Algorithms["IDEA/CFB8"] = "IDEAMAC/CFB8";
-            Algorithms["RC2"] = "RC2MAC";
-            Algorithms["RC2/CFB8"] = "RC2MAC/CFB8";
-            Algorithms["RC5"] = "RC5MAC";
-            Algorithms["RC5/CFB8"] = "RC5MAC/CFB8";
-            Algorithms["GOST28147"] = "GOST28147MAC";
-            Algorithms["VMPC"] = "VMPCMAC";
-            Algorithms["VMPC-MAC"] = "VMPCMAC";
-            Algorithms["SIPHASH"] = "SIPHASH-2-4";
-
-            Algorithms["PBEWITHHMACSHA"] = "PBEWITHHMACSHA1";
-            Algorithms["1.3.14.3.2.26"] = "PBEWITHHMACSHA1";
+            AlgorithmMap["DES"] = "DESMAC";
+            AlgorithmMap["DES/CFB8"] = "DESMAC/CFB8";
+            AlgorithmMap["DES64"] = "DESMAC64";
+            AlgorithmMap["DESEDE"] = "DESEDEMAC";
+            AlgorithmOidMap[PkcsObjectIdentifiers.DesEde3Cbc] = "DESEDEMAC";
+            AlgorithmMap["DESEDE/CFB8"] = "DESEDEMAC/CFB8";
+            AlgorithmMap["DESISO9797MAC"] = "DESWITHISO9797";
+            AlgorithmMap["DESEDE64"] = "DESEDEMAC64";
+
+            AlgorithmMap["DESEDE64WITHISO7816-4PADDING"] = "DESEDEMAC64WITHISO7816-4PADDING";
+            AlgorithmMap["DESEDEISO9797ALG1MACWITHISO7816-4PADDING"] = "DESEDEMAC64WITHISO7816-4PADDING";
+            AlgorithmMap["DESEDEISO9797ALG1WITHISO7816-4PADDING"] = "DESEDEMAC64WITHISO7816-4PADDING";
+
+            AlgorithmMap["ISO9797ALG3"] = "ISO9797ALG3MAC";
+            AlgorithmMap["ISO9797ALG3MACWITHISO7816-4PADDING"] = "ISO9797ALG3WITHISO7816-4PADDING";
+
+            AlgorithmMap["SKIPJACK"] = "SKIPJACKMAC";
+            AlgorithmMap["SKIPJACK/CFB8"] = "SKIPJACKMAC/CFB8";
+            AlgorithmMap["IDEA"] = "IDEAMAC";
+            AlgorithmMap["IDEA/CFB8"] = "IDEAMAC/CFB8";
+            AlgorithmMap["RC2"] = "RC2MAC";
+            AlgorithmMap["RC2/CFB8"] = "RC2MAC/CFB8";
+            AlgorithmMap["RC5"] = "RC5MAC";
+            AlgorithmMap["RC5/CFB8"] = "RC5MAC/CFB8";
+            AlgorithmMap["GOST28147"] = "GOST28147MAC";
+            AlgorithmMap["VMPC"] = "VMPCMAC";
+            AlgorithmMap["VMPC-MAC"] = "VMPCMAC";
+            AlgorithmMap["SIPHASH"] = "SIPHASH-2-4";
+
+            AlgorithmMap["PBEWITHHMACSHA"] = "PBEWITHHMACSHA1";
+            AlgorithmOidMap[OiwObjectIdentifiers.IdSha1] = "PBEWITHHMACSHA1";
+
+#if DEBUG
+            foreach (var key in AlgorithmMap.Keys)
+            {
+                if (DerObjectIdentifier.TryFromID(key, out var ignore))
+                    throw new Exception("OID mapping belongs in AlgorithmOidMap: " + key);
+            }
+
+            var mechanisms = new HashSet<string>(AlgorithmMap.Values);
+            mechanisms.UnionWith(AlgorithmOidMap.Values);
+
+            foreach (var mechanism in mechanisms)
+            {
+                if (AlgorithmMap.TryGetValue(mechanism, out var check))
+                {
+                    if (mechanism != check)
+                        throw new Exception("Mechanism mapping MUST be to self: " + mechanism);
+                }
+                else
+                {
+                    if (!mechanism.Equals(mechanism.ToUpperInvariant()))
+                        throw new Exception("Unmapped mechanism MUST be uppercase: " + mechanism);
+                }
+            }
+#endif
+        }
+
+        public static byte[] CalculateMac(string algorithm, ICipherParameters cp, byte[] input)
+        {
+            IMac mac = GetMac(algorithm);
+            mac.Init(cp);
+            mac.BlockUpdate(input, 0, input.Length);
+            return DoFinal(mac);
+        }
+
+        public static byte[] DoFinal(IMac mac)
+        {
+            byte[] b = new byte[mac.GetMacSize()];
+            mac.DoFinal(b, 0);
+            return b;
+        }
+
+        public static byte[] DoFinal(IMac mac, byte[] input)
+        {
+            mac.BlockUpdate(input, 0, input.Length);
+            return DoFinal(mac);
+        }
+
+        public static string GetAlgorithmName(DerObjectIdentifier oid)
+        {
+            return CollectionUtilities.GetValueOrNull(AlgorithmOidMap, oid);
         }
 
+        // TODO[api] Change parameter name to 'oid'
         public static IMac GetMac(DerObjectIdentifier id)
         {
-            return GetMac(id.Id);
+            if (id == null)
+                throw new ArgumentNullException(nameof(id));
+
+            if (AlgorithmOidMap.TryGetValue(id, out var mechanism))
+            {
+                var mac = GetMacForMechanism(mechanism);
+                if (mac != null)
+                    return mac;
+            }
+
+            throw new SecurityUtilityException("Mac OID not recognised.");
         }
 
         public static IMac GetMac(string algorithm)
@@ -91,8 +156,17 @@ namespace Org.BouncyCastle.Security
             if (algorithm == null)
                 throw new ArgumentNullException(nameof(algorithm));
 
-            string mechanism = CollectionUtilities.GetValueOrKey(Algorithms, algorithm).ToUpperInvariant();
+            string mechanism = GetMechanism(algorithm) ?? algorithm.ToUpperInvariant();
+
+            var mac = GetMacForMechanism(mechanism);
+            if (mac != null)
+                return mac;
 
+            throw new SecurityUtilityException("Mac " + algorithm + " not recognised.");
+        }
+
+        private static IMac GetMacForMechanism(string mechanism)
+        {
             if (Platform.StartsWith(mechanism, "PBEWITH"))
             {
                 mechanism = mechanism.Substring("PBEWITH".Length);
@@ -202,33 +276,21 @@ namespace Org.BouncyCastle.Security
             {
                 return new SipHash();
             }
-            throw new SecurityUtilityException("Mac " + mechanism + " not recognised.");
+            return null;
         }
 
-        public static string GetAlgorithmName(DerObjectIdentifier oid)
+        private static string GetMechanism(string algorithm)
         {
-            return CollectionUtilities.GetValueOrNull(Algorithms, oid.Id);
-        }
+            if (AlgorithmMap.TryGetValue(algorithm, out var mechanism1))
+                return mechanism1;
 
-        public static byte[] CalculateMac(string algorithm, ICipherParameters cp, byte[] input)
-        {
-            IMac mac = GetMac(algorithm);
-            mac.Init(cp);
-            mac.BlockUpdate(input, 0, input.Length);
-            return DoFinal(mac);
-        }
-
-        public static byte[] DoFinal(IMac mac)
-        {
-            byte[] b = new byte[mac.GetMacSize()];
-            mac.DoFinal(b, 0);
-            return b;
-        }
+            if (DerObjectIdentifier.TryFromID(algorithm, out var oid))
+            {
+                if (AlgorithmOidMap.TryGetValue(oid, out var mechanism2))
+                    return mechanism2;
+            }
 
-        public static byte[] DoFinal(IMac mac, byte[] input)
-        {
-            mac.BlockUpdate(input, 0, input.Length);
-            return DoFinal(mac);
+            return null;
         }
     }
 }