< Summary - CoreWCF Coverage — PR #1766

Information
Class: CoreWCF.Security.CryptoHelper
Assembly: CoreWCF.Primitives
File(s): /home/runner/work/CoreWCF/CoreWCF/src/CoreWCF.Primitives/src/CoreWCF/Security/CryptoHelper.cs
Line coverage
0%
Covered lines: 0
Uncovered lines: 119
Coverable lines: 119
Total lines: 341
Line coverage: 0%
Branch coverage
0%
Covered branches: 0
Total branches: 226
Branch coverage: 0%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

File(s)

/home/runner/work/CoreWCF/CoreWCF/src/CoreWCF.Primitives/src/CoreWCF/Security/CryptoHelper.cs

#LineLine coverage
 1// Licensed to the .NET Foundation under one or more agreements.
 2// The .NET Foundation licenses this file to you under the MIT license.
 3
 4using System;
 5using System.Security.Cryptography;
 6using CoreWCF.IdentityModel.Tokens;
 7using CoreWCF.Runtime;
 8using CryptoAlgorithms = CoreWCF.IdentityModel.CryptoHelper;
 9
 10namespace CoreWCF.Security
 11{
 12    internal static class CryptoHelper
 13    {
 14        private static byte[] s_emptyBuffer;
 015        private static readonly RandomNumberGenerator s_random = new RNGCryptoServiceProvider();
 16
 17        private enum CryptoAlgorithmType
 18        {
 19            Unknown,
 20            Symmetric,
 21            Asymmetric
 22        }
 23
 24        internal static byte[] EmptyBuffer
 25        {
 26            get
 27            {
 028                if (s_emptyBuffer == null)
 29                {
 030                    byte[] tmp = Array.Empty<byte>();
 031                    s_emptyBuffer = tmp;
 32                }
 033                return s_emptyBuffer;
 34            }
 35        }
 36
 37        internal static HashAlgorithm NewSha1HashAlgorithm()
 38        {
 039            return CreateHashAlgorithm(SecurityAlgorithms.Sha1Digest);
 40        }
 41
 42        internal static HashAlgorithm NewSha256HashAlgorithm()
 43        {
 044            return CreateHashAlgorithm(SecurityAlgorithms.Sha256Digest);
 45        }
 46
 47        internal static HashAlgorithm CreateHashAlgorithm(string digestMethod)
 48        {
 049            object algorithmObject = CryptoAlgorithms.GetAlgorithmFromConfig(digestMethod);
 050            if (algorithmObject != null)
 51            {
 052                if (algorithmObject is HashAlgorithm hashAlgorithm)
 53                {
 054                    return hashAlgorithm;
 55                }
 56
 057                throw DiagnosticUtility.ExceptionUtility.ThrowHelperWarning(new MessageSecurityException(SR.Format(SR.Cu
 58            }
 59
 60            switch (digestMethod)
 61            {
 62                case SecurityAlgorithms.Sha1Digest:
 063                    return SHA1.Create();
 64                case SecurityAlgorithms.Sha256Digest:
 065                    return SHA256.Create();
 66                default:
 067                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperWarning(new MessageSecurityException(SR.Format(S
 68            }
 69        }
 70
 71        internal static HashAlgorithm CreateHashForAsymmetricSignature(string signatureMethod)
 72        {
 073            object algorithmObject = CryptoAlgorithms.GetAlgorithmFromConfig(signatureMethod);
 074            if (algorithmObject != null)
 75            {
 76                HashAlgorithm hashAlgorithm;
 77
 078                if (algorithmObject is SignatureDescription signatureDescription)
 79                {
 080                    hashAlgorithm = signatureDescription.CreateDigest();
 081                    if (hashAlgorithm != null)
 82                    {
 083                        return hashAlgorithm;
 84                    }
 85                }
 86
 087                hashAlgorithm = algorithmObject as HashAlgorithm;
 088                if (hashAlgorithm != null)
 89                {
 090                    return hashAlgorithm;
 91                }
 92
 093                throw DiagnosticUtility.ExceptionUtility.ThrowHelperWarning(new MessageSecurityException(SR.Format(SR.Cu
 94            }
 95
 96            switch (signatureMethod)
 97            {
 98                case SecurityAlgorithms.RsaSha1Signature:
 99                case SecurityAlgorithms.DsaSha1Signature:
 0100                    return SHA1.Create();
 101                case SecurityAlgorithms.RsaSha256Signature:
 0102                    return SHA256.Create();
 103                default:
 0104                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperWarning(new MessageSecurityException(SR.Format(S
 105            }
 106        }
 107
 108        internal static byte[] ExtractIVAndDecrypt(SymmetricAlgorithm algorithm, byte[] cipherText, int offset, int coun
 109        {
 0110            if (cipherText == null)
 111            {
 0112                throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull(nameof(cipherText));
 113            }
 0114            if (count < 0 || count > cipherText.Length)
 115            {
 0116                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException(nameof(count),
 117            }
 0118            if (offset < 0 || offset > cipherText.Length - count)
 119            {
 0120                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException(nameof(offset)
 121            }
 122
 0123            int ivSize = algorithm.BlockSize / 8;
 0124            byte[] iv = new byte[ivSize];
 0125            Buffer.BlockCopy(cipherText, offset, iv, 0, iv.Length);
 0126            algorithm.Padding = PaddingMode.ISO10126;
 0127            algorithm.Mode = CipherMode.CBC;
 128            try
 129            {
 0130                using (ICryptoTransform decrTransform = algorithm.CreateDecryptor(algorithm.Key, iv))
 131                {
 0132                    return decrTransform.TransformFinalBlock(cipherText, offset + iv.Length, count - iv.Length);
 133                }
 134            }
 0135            catch (CryptographicException ex)
 136            {
 0137                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new MessageSecurityException(SR.Format(SR.Decr
 138            }
 0139        }
 140
 141        internal static void FillRandomBytes(byte[] buffer)
 142        {
 0143            s_random.GetBytes(buffer);
 0144        }
 145
 146        private static CryptoAlgorithmType GetAlgorithmType(string algorithm)
 147        {
 148            object algorithmObject;
 149            try
 150            {
 0151                algorithmObject = CryptoAlgorithms.GetAlgorithmFromConfig(algorithm);
 0152            }
 153#pragma warning disable CA1031 // Do not catch general exception types
 0154            catch (InvalidOperationException)
 155            {
 0156                algorithmObject = null;
 157                // We swallow the exception and continue.
 0158            }
 159#pragma warning restore CA1031 // Do not catch general exception types
 0160            if (algorithmObject != null)
 161            {
 0162                SymmetricAlgorithm symmetricAlgorithm = algorithmObject as SymmetricAlgorithm;
 0163                KeyedHashAlgorithm keyedHashAlgorithm = algorithmObject as KeyedHashAlgorithm;
 0164                if (symmetricAlgorithm != null || keyedHashAlgorithm != null)
 165                {
 0166                    return CryptoAlgorithmType.Symmetric;
 167                }
 168
 169                // NOTE: A KeyedHashAlgorithm is symmetric in nature.
 170
 0171                AsymmetricAlgorithm asymmetricAlgorithm = algorithmObject as AsymmetricAlgorithm;
 0172                SignatureDescription signatureDescription = algorithmObject as SignatureDescription;
 0173                if (asymmetricAlgorithm != null || signatureDescription != null)
 174                {
 0175                    return CryptoAlgorithmType.Asymmetric;
 176                }
 177
 0178                return CryptoAlgorithmType.Unknown;
 179            }
 180
 181            switch (algorithm)
 182            {
 183                case SecurityAlgorithms.DsaSha1Signature:
 184                case SecurityAlgorithms.RsaSha1Signature:
 185                case SecurityAlgorithms.RsaSha256Signature:
 186                case SecurityAlgorithms.RsaOaepKeyWrap:
 187                case SecurityAlgorithms.RsaV15KeyWrap:
 0188                    return CryptoAlgorithmType.Asymmetric;
 189                case SecurityAlgorithms.HmacSha1Signature:
 190                case SecurityAlgorithms.HmacSha256Signature:
 191                case SecurityAlgorithms.Aes128Encryption:
 192                case SecurityAlgorithms.Aes192Encryption:
 193                case SecurityAlgorithms.Aes256Encryption:
 194                case SecurityAlgorithms.TripleDesEncryption:
 195                case SecurityAlgorithms.Aes128KeyWrap:
 196                case SecurityAlgorithms.Aes192KeyWrap:
 197                case SecurityAlgorithms.Aes256KeyWrap:
 198                case SecurityAlgorithms.TripleDesKeyWrap:
 199                case SecurityAlgorithms.Psha1KeyDerivation:
 200                case SecurityAlgorithms.Psha1KeyDerivationDec2005:
 0201                    return CryptoAlgorithmType.Symmetric;
 202                default:
 0203                    return CryptoAlgorithmType.Unknown;
 204            }
 205        }
 206
 207        internal static byte[] GenerateIVAndEncrypt(SymmetricAlgorithm algorithm, byte[] plainText, int offset, int coun
 208        {
 0209            GenerateIVAndEncrypt(algorithm, new ArraySegment<byte>(plainText, offset, count), out byte[] iv, out byte[] 
 0210            byte[] output = Fx.AllocateByteArray(checked(iv.Length + cipherText.Length));
 0211            Buffer.BlockCopy(iv, 0, output, 0, iv.Length);
 0212            Buffer.BlockCopy(cipherText, 0, output, iv.Length, cipherText.Length);
 0213            return output;
 214        }
 215
 216        internal static void GenerateIVAndEncrypt(SymmetricAlgorithm algorithm, ArraySegment<byte> plainText, out byte[]
 217        {
 0218            int ivSize = algorithm.BlockSize / 8;
 0219            iv = new byte[ivSize];
 0220            FillRandomBytes(iv);
 0221            algorithm.Padding = PaddingMode.PKCS7;
 0222            algorithm.Mode = CipherMode.CBC;
 0223            using (ICryptoTransform encrTransform = algorithm.CreateEncryptor(algorithm.Key, iv))
 224            {
 0225                cipherText = encrTransform.TransformFinalBlock(plainText.Array, plainText.Offset, plainText.Count);
 0226            }
 0227        }
 228
 229        internal static bool IsEqual(byte[] a, byte[] b)
 230        {
 0231            if (a == null || b == null || a.Length != b.Length)
 232            {
 0233                return false;
 234            }
 235
 0236            for (int i = 0; i < a.Length; i++)
 237            {
 0238                if (a[i] != b[i])
 239                {
 0240                    return false;
 241                }
 242            }
 0243            return true;
 244        }
 245
 246        internal static bool IsSymmetricAlgorithm(string algorithm)
 247        {
 0248            return GetAlgorithmType(algorithm) == CryptoAlgorithmType.Symmetric;
 249        }
 250
 251        internal static bool IsSymmetricSupportedAlgorithm(string algorithm, int keySize)
 252        {
 0253            bool found = false;
 254            object algorithmObject;
 255            try
 256            {
 0257                algorithmObject = CryptoAlgorithms.GetAlgorithmFromConfig(algorithm);
 0258            }
 259#pragma warning disable CA1031 // Do not catch general exception types
 0260            catch (InvalidOperationException)
 261            {
 0262                algorithmObject = null;
 263                // We swallow the exception and continue.
 0264            }
 265#pragma warning restore CA1031 // Do not catch general exception types
 0266            if (algorithmObject != null)
 267            {
 0268                SymmetricAlgorithm symmetricAlgorithm = algorithmObject as SymmetricAlgorithm;
 0269                KeyedHashAlgorithm keyedHashAlgorithm = algorithmObject as KeyedHashAlgorithm;
 0270                if (symmetricAlgorithm != null || keyedHashAlgorithm != null)
 271                {
 0272                    found = true;
 273                }
 274            }
 275
 276            switch (algorithm)
 277            {
 278                case SecurityAlgorithms.DsaSha1Signature:
 279                case SecurityAlgorithms.RsaSha1Signature:
 280                case SecurityAlgorithms.RsaSha256Signature:
 281                case SecurityAlgorithms.RsaOaepKeyWrap:
 282                case SecurityAlgorithms.RsaV15KeyWrap:
 0283                    return false;
 284                case SecurityAlgorithms.HmacSha1Signature:
 285                case SecurityAlgorithms.HmacSha256Signature:
 286                case SecurityAlgorithms.Psha1KeyDerivation:
 287                case SecurityAlgorithms.Psha1KeyDerivationDec2005:
 0288                    return true;
 289                case SecurityAlgorithms.Aes128Encryption:
 290                case SecurityAlgorithms.Aes128KeyWrap:
 0291                    return keySize == 128;
 292                case SecurityAlgorithms.Aes192Encryption:
 293                case SecurityAlgorithms.Aes192KeyWrap:
 0294                    return keySize == 192;
 295                case SecurityAlgorithms.Aes256Encryption:
 296                case SecurityAlgorithms.Aes256KeyWrap:
 0297                    return keySize == 256;
 298                case SecurityAlgorithms.TripleDesEncryption:
 299                case SecurityAlgorithms.TripleDesKeyWrap:
 0300                    return keySize == 128 || keySize == 192;
 301                default:
 0302                    if (found)
 303                    {
 0304                        return true;
 305                    }
 306
 0307                    return false;
 308            }
 309        }
 310
 311        internal static void ValidateBufferBounds(Array buffer, int offset, int count)
 312        {
 0313            if (buffer == null)
 314            {
 0315                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException(nameof(buffer)));
 316            }
 0317            if (count < 0 || count > buffer.Length)
 318            {
 0319                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException(nameof(count),
 320            }
 0321            if (offset < 0 || offset > buffer.Length - count)
 322            {
 0323                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException(nameof(offset)
 324            }
 0325        }
 326
 327        internal static void ValidateSymmetricKeyLength(int keyLength, SecurityAlgorithmSuite algorithmSuite)
 328        {
 0329            if (!algorithmSuite.IsSymmetricKeyLengthSupported(keyLength))
 330            {
 0331                throw DiagnosticUtility.ExceptionUtility.ThrowHelperWarning(new ArgumentOutOfRangeException(nameof(algor
 0332                   SR.Format(SR.UnsupportedKeyLength, keyLength, algorithmSuite.ToString())));
 333            }
 0334            if (keyLength % 8 != 0)
 335            {
 0336                throw DiagnosticUtility.ExceptionUtility.ThrowHelperWarning(new ArgumentOutOfRangeException(nameof(algor
 0337                   SR.Format(SR.KeyLengthMustBeMultipleOfEight, keyLength)));
 338            }
 0339        }
 340    }
 341}