| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357 |
- //------------------------------------------------------------
- // Copyright (c) Microsoft Corporation. All rights reserved.
- //------------------------------------------------------------
- namespace System.ServiceModel.Security
- {
- using System.Collections;
- using System.Collections.Generic;
- using System.ServiceModel.Channels;
- using System.ServiceModel;
- using System.Reflection;
- using System.Threading;
- using System.IO;
- using System.Runtime.InteropServices;
- using System.IdentityModel.Tokens;
- using System.Text;
- using System.Xml;
- using System.Diagnostics;
- using System.Security.Cryptography;
- using Psha1DerivedKeyGenerator = System.IdentityModel.Psha1DerivedKeyGenerator;
- using CryptoAlgorithms = System.IdentityModel.CryptoHelper;
- static class CryptoHelper
- {
- static byte[] emptyBuffer;
- static readonly RandomNumberGenerator random = new RNGCryptoServiceProvider();
- enum CryptoAlgorithmType
- {
- Unknown,
- Symmetric,
- Asymmetric
- }
- internal static byte[] EmptyBuffer
- {
- get
- {
- if (emptyBuffer == null)
- {
- byte[] tmp = new byte[0];
- emptyBuffer = tmp;
- }
- return emptyBuffer;
- }
- }
- internal static HashAlgorithm NewSha1HashAlgorithm()
- {
- return CryptoHelper.CreateHashAlgorithm(SecurityAlgorithms.Sha1Digest);
- }
- internal static HashAlgorithm NewSha256HashAlgorithm()
- {
- return CryptoHelper.CreateHashAlgorithm(SecurityAlgorithms.Sha256Digest);
- }
- internal static HashAlgorithm CreateHashAlgorithm(string digestMethod)
- {
- object algorithmObject = CryptoAlgorithms.GetAlgorithmFromConfig(digestMethod);
- if (algorithmObject != null)
- {
- HashAlgorithm hashAlgorithm = algorithmObject as HashAlgorithm;
- if (hashAlgorithm != null)
- return hashAlgorithm;
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperWarning(new MessageSecurityException(SR.GetString(SR.CustomCryptoAlgorithmIsNotValidHashAlgorithm, digestMethod)));
- }
- switch (digestMethod)
- {
- case SecurityAlgorithms.Sha1Digest:
- if (SecurityUtilsEx.RequiresFipsCompliance)
- return new SHA1CryptoServiceProvider();
- else
- return new SHA1Managed();
- case SecurityAlgorithms.Sha256Digest:
- if (SecurityUtilsEx.RequiresFipsCompliance)
- return new SHA256CryptoServiceProvider();
- else
- return new SHA256Managed();
- default:
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperWarning(new MessageSecurityException(SR.GetString(SR.UnsupportedCryptoAlgorithm, digestMethod)));
- }
- }
- internal static HashAlgorithm CreateHashForAsymmetricSignature(string signatureMethod)
- {
- object algorithmObject = CryptoAlgorithms.GetAlgorithmFromConfig(signatureMethod);
- if (algorithmObject != null)
- {
- HashAlgorithm hashAlgorithm;
- SignatureDescription signatureDescription = algorithmObject as SignatureDescription;
- if (signatureDescription != null)
- {
- hashAlgorithm = signatureDescription.CreateDigest();
- if (hashAlgorithm != null)
- return hashAlgorithm;
- }
- hashAlgorithm = algorithmObject as HashAlgorithm;
- if (hashAlgorithm != null)
- return hashAlgorithm;
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperWarning(new MessageSecurityException(SR.GetString(SR.CustomCryptoAlgorithmIsNotValidAsymmetricSignature, signatureMethod)));
- }
- switch (signatureMethod)
- {
- case SecurityAlgorithms.RsaSha1Signature:
- case SecurityAlgorithms.DsaSha1Signature:
- if (SecurityUtilsEx.RequiresFipsCompliance)
- return new SHA1CryptoServiceProvider();
- else
- return new SHA1Managed();
- case SecurityAlgorithms.RsaSha256Signature:
- if (SecurityUtilsEx.RequiresFipsCompliance)
- return new SHA256CryptoServiceProvider();
- else
- return new SHA256Managed();
- default:
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperWarning(new MessageSecurityException(SR.GetString(SR.UnsupportedCryptoAlgorithm, signatureMethod)));
- }
- }
- internal static byte[] ExtractIVAndDecrypt(SymmetricAlgorithm algorithm, byte[] cipherText, int offset, int count)
- {
- if (cipherText == null)
- {
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("cipherText");
- }
- if (count < 0 || count > cipherText.Length)
- {
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException("count", SR.GetString(SR.ValueMustBeInRange, 0, cipherText.Length)));
- }
- if (offset < 0 || offset > cipherText.Length - count)
- {
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException("offset", SR.GetString(SR.ValueMustBeInRange, 0, cipherText.Length - count)));
- }
- int ivSize = algorithm.BlockSize / 8;
- byte[] iv = new byte[ivSize];
- Buffer.BlockCopy(cipherText, offset, iv, 0, iv.Length);
- algorithm.Padding = PaddingMode.ISO10126;
- algorithm.Mode = CipherMode.CBC;
- try
- {
- using (ICryptoTransform decrTransform = algorithm.CreateDecryptor(algorithm.Key, iv))
- {
- return decrTransform.TransformFinalBlock(cipherText, offset + iv.Length, count - iv.Length);
- }
- }
- catch (CryptographicException ex)
- {
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new MessageSecurityException(SR.GetString(SR.DecryptionFailed), ex));
- }
- }
- internal static void FillRandomBytes(byte[] buffer)
- {
- random.GetBytes(buffer);
- }
- static CryptoAlgorithmType GetAlgorithmType(string algorithm)
- {
- object algorithmObject = null;
- try
- {
- algorithmObject = CryptoAlgorithms.GetAlgorithmFromConfig(algorithm);
- }
- catch (InvalidOperationException)
- {
- algorithmObject = null;
- // We ---- the exception and continue.
- }
- if (algorithmObject != null)
- {
- SymmetricAlgorithm symmetricAlgorithm = algorithmObject as SymmetricAlgorithm;
- KeyedHashAlgorithm keyedHashAlgorithm = algorithmObject as KeyedHashAlgorithm;
- if (symmetricAlgorithm != null || keyedHashAlgorithm != null)
- return CryptoAlgorithmType.Symmetric;
- // NOTE: A KeyedHashAlgorithm is symmetric in nature.
- AsymmetricAlgorithm asymmetricAlgorithm = algorithmObject as AsymmetricAlgorithm;
- SignatureDescription signatureDescription = algorithmObject as SignatureDescription;
- if (asymmetricAlgorithm != null || signatureDescription != null)
- return CryptoAlgorithmType.Asymmetric;
- return CryptoAlgorithmType.Unknown;
- }
- switch (algorithm)
- {
- case SecurityAlgorithms.DsaSha1Signature:
- case SecurityAlgorithms.RsaSha1Signature:
- case SecurityAlgorithms.RsaSha256Signature:
- case SecurityAlgorithms.RsaOaepKeyWrap:
- case SecurityAlgorithms.RsaV15KeyWrap:
- return CryptoAlgorithmType.Asymmetric;
- case SecurityAlgorithms.HmacSha1Signature:
- case SecurityAlgorithms.HmacSha256Signature:
- case SecurityAlgorithms.Aes128Encryption:
- case SecurityAlgorithms.Aes192Encryption:
- case SecurityAlgorithms.Aes256Encryption:
- case SecurityAlgorithms.TripleDesEncryption:
- case SecurityAlgorithms.Aes128KeyWrap:
- case SecurityAlgorithms.Aes192KeyWrap:
- case SecurityAlgorithms.Aes256KeyWrap:
- case SecurityAlgorithms.TripleDesKeyWrap:
- case SecurityAlgorithms.Psha1KeyDerivation:
- case SecurityAlgorithms.Psha1KeyDerivationDec2005:
- return CryptoAlgorithmType.Symmetric;
- default:
- return CryptoAlgorithmType.Unknown;
- }
- }
- internal static byte[] GenerateIVAndEncrypt(SymmetricAlgorithm algorithm, byte[] plainText, int offset, int count)
- {
- byte[] iv;
- byte[] cipherText;
- GenerateIVAndEncrypt(algorithm, new ArraySegment<byte>(plainText, offset, count), out iv, out cipherText);
- byte[] output = DiagnosticUtility.Utility.AllocateByteArray(checked(iv.Length + cipherText.Length));
- Buffer.BlockCopy(iv, 0, output, 0, iv.Length);
- Buffer.BlockCopy(cipherText, 0, output, iv.Length, cipherText.Length);
- return output;
- }
- internal static void GenerateIVAndEncrypt(SymmetricAlgorithm algorithm, ArraySegment<byte> plainText, out byte[] iv, out byte[] cipherText)
- {
- int ivSize = algorithm.BlockSize / 8;
- iv = new byte[ivSize];
- FillRandomBytes(iv);
- algorithm.Padding = PaddingMode.PKCS7;
- algorithm.Mode = CipherMode.CBC;
- using (ICryptoTransform encrTransform = algorithm.CreateEncryptor(algorithm.Key, iv))
- {
- cipherText = encrTransform.TransformFinalBlock(plainText.Array, plainText.Offset, plainText.Count);
- }
- }
- internal static bool IsEqual(byte[] a, byte[] b)
- {
- if (a == null || b == null || a.Length != b.Length)
- {
- return false;
- }
- for (int i = 0; i < a.Length; i++)
- {
- if (a[i] != b[i])
- {
- return false;
- }
- }
- return true;
- }
- internal static bool IsSymmetricAlgorithm(string algorithm)
- {
- return GetAlgorithmType(algorithm) == CryptoAlgorithmType.Symmetric;
- }
- internal static bool IsSymmetricSupportedAlgorithm(string algorithm, int keySize)
- {
- bool found = false;
- object algorithmObject = null;
- try
- {
- algorithmObject = CryptoAlgorithms.GetAlgorithmFromConfig(algorithm);
- }
- catch (InvalidOperationException)
- {
- algorithmObject = null;
- // We ---- the exception and continue.
- }
- if (algorithmObject != null)
- {
- SymmetricAlgorithm symmetricAlgorithm = algorithmObject as SymmetricAlgorithm;
- KeyedHashAlgorithm keyedHashAlgorithm = algorithmObject as KeyedHashAlgorithm;
- if (symmetricAlgorithm != null || keyedHashAlgorithm != null)
- found = true;
- }
- switch (algorithm)
- {
- case SecurityAlgorithms.DsaSha1Signature:
- case SecurityAlgorithms.RsaSha1Signature:
- case SecurityAlgorithms.RsaSha256Signature:
- case SecurityAlgorithms.RsaOaepKeyWrap:
- case SecurityAlgorithms.RsaV15KeyWrap:
- return false;
- case SecurityAlgorithms.HmacSha1Signature:
- case SecurityAlgorithms.HmacSha256Signature:
- case SecurityAlgorithms.Psha1KeyDerivation:
- case SecurityAlgorithms.Psha1KeyDerivationDec2005:
- return true;
- case SecurityAlgorithms.Aes128Encryption:
- case SecurityAlgorithms.Aes128KeyWrap:
- return keySize == 128;
- case SecurityAlgorithms.Aes192Encryption:
- case SecurityAlgorithms.Aes192KeyWrap:
- return keySize == 192;
- case SecurityAlgorithms.Aes256Encryption:
- case SecurityAlgorithms.Aes256KeyWrap:
- return keySize == 256;
- case SecurityAlgorithms.TripleDesEncryption:
- case SecurityAlgorithms.TripleDesKeyWrap:
- return keySize == 128 || keySize == 192;
- default:
- if (found)
- return true;
- return false;
- }
- }
- internal static void ValidateBufferBounds(Array buffer, int offset, int count)
- {
- if (buffer == null)
- {
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException("buffer"));
- }
- if (count < 0 || count > buffer.Length)
- {
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException("count", SR.GetString(SR.ValueMustBeInRange, 0, buffer.Length)));
- }
- if (offset < 0 || offset > buffer.Length - count)
- {
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException("offset", SR.GetString(SR.ValueMustBeInRange, 0, buffer.Length - count)));
- }
- }
- internal static void ValidateSymmetricKeyLength(int keyLength, SecurityAlgorithmSuite algorithmSuite)
- {
- if (!algorithmSuite.IsSymmetricKeyLengthSupported(keyLength))
- {
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperWarning(new ArgumentOutOfRangeException("algorithmSuite",
- SR.GetString(SR.UnsupportedKeyLength, keyLength, algorithmSuite.ToString())));
- }
- if (keyLength % 8 != 0)
- {
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperWarning(new ArgumentOutOfRangeException("algorithmSuite",
- SR.GetString(SR.KeyLengthMustBeMultipleOfEight, keyLength)));
- }
- }
- }
- }
|