1 using System.Diagnostics.Contracts; 2 // ==++== 3 // 4 // Copyright (c) Microsoft Corporation. All rights reserved. 5 // 6 // ==--== 7 // <OWNER>Microsoft</OWNER> 8 // 9 10 // 11 // SymmetricAlgorithm.cs 12 // 13 14 namespace System.Security.Cryptography { 15 [System.Runtime.InteropServices.ComVisible(true)] 16 public abstract class SymmetricAlgorithm : IDisposable { 17 protected int BlockSizeValue; 18 protected int FeedbackSizeValue; 19 protected byte[] IVValue; 20 protected byte[] KeyValue; 21 protected KeySizes[] LegalBlockSizesValue; 22 protected KeySizes[] LegalKeySizesValue; 23 protected int KeySizeValue; 24 protected CipherMode ModeValue; 25 protected PaddingMode PaddingValue; 26 27 // 28 // protected constructors 29 // 30 SymmetricAlgorithm()31 protected SymmetricAlgorithm() { 32 // Default to cipher block chaining (CipherMode.CBC) and 33 // PKCS-style padding (pad n bytes with value n) 34 ModeValue = CipherMode.CBC; 35 PaddingValue = PaddingMode.PKCS7; 36 } 37 38 // SymmetricAlgorithm implements IDisposable 39 40 // To keep mscorlib compatibility with Orcas, CoreCLR's SymmetricAlgorithm has an explicit IDisposable 41 // implementation. Post-Orcas the desktop has an implicit IDispoable implementation. 42 #if FEATURE_CORECLR IDisposable.Dispose()43 void IDisposable.Dispose() 44 { 45 Dispose(); 46 } 47 #endif // FEATURE_CORECLR 48 Dispose()49 public void Dispose() 50 { 51 Dispose(true); 52 GC.SuppressFinalize(this); 53 } 54 Clear()55 public void Clear() { 56 (this as IDisposable).Dispose(); 57 } 58 Dispose(bool disposing)59 protected virtual void Dispose(bool disposing) { 60 if (disposing) { 61 // Note: we always want to zeroize the sensitive key material 62 if (KeyValue != null) { 63 Array.Clear(KeyValue, 0, KeyValue.Length); 64 KeyValue = null; 65 } 66 if (IVValue != null) { 67 Array.Clear(IVValue, 0, IVValue.Length); 68 IVValue = null; 69 } 70 } 71 } 72 73 // 74 // public properties 75 // 76 77 public virtual int BlockSize { 78 get { return BlockSizeValue; } 79 set { 80 int i; 81 int j; 82 83 for (i=0; i<LegalBlockSizesValue.Length; i++) { 84 // If a cipher has only one valid key size, MinSize == MaxSize and SkipSize will be 0 85 if (LegalBlockSizesValue[i].SkipSize == 0) { 86 if (LegalBlockSizesValue[i].MinSize == value) { // assume MinSize = MaxSize 87 BlockSizeValue = value; 88 IVValue = null; 89 return; 90 } 91 } else { 92 for (j = LegalBlockSizesValue[i].MinSize; j<=LegalBlockSizesValue[i].MaxSize; 93 j += LegalBlockSizesValue[i].SkipSize) { 94 if (j == value) { 95 if (BlockSizeValue != value) { 96 BlockSizeValue = value; 97 IVValue = null; // Wrong length now 98 } 99 return; 100 } 101 } 102 } 103 } 104 throw new CryptographicException(Environment.GetResourceString("Cryptography_InvalidBlockSize")); 105 } 106 } 107 108 public virtual int FeedbackSize { 109 get { return FeedbackSizeValue; } 110 set { 111 if (value <= 0 || value > BlockSizeValue || (value % 8) != 0) 112 throw new CryptographicException(Environment.GetResourceString("Cryptography_InvalidFeedbackSize")); 113 114 FeedbackSizeValue = value; 115 } 116 } 117 118 public virtual byte[] IV { 119 get { 120 if (IVValue == null) GenerateIV(); 121 return (byte[]) IVValue.Clone(); 122 } 123 set { 124 if (value == null) throw new ArgumentNullException("value"); 125 Contract.EndContractBlock(); 126 if (value.Length != BlockSizeValue / 8) 127 throw new CryptographicException(Environment.GetResourceString("Cryptography_InvalidIVSize")); 128 129 IVValue = (byte[]) value.Clone(); 130 } 131 } 132 133 public virtual byte[] Key { 134 get { 135 if (KeyValue == null) GenerateKey(); 136 return (byte[]) KeyValue.Clone(); 137 } 138 set { 139 if (value == null) throw new ArgumentNullException("value"); 140 Contract.EndContractBlock(); 141 if (!ValidKeySize(value.Length * 8)) 142 throw new CryptographicException(Environment.GetResourceString("Cryptography_InvalidKeySize")); 143 144 // must convert bytes to bits 145 KeyValue = (byte[]) value.Clone(); 146 KeySizeValue = value.Length * 8; 147 } 148 } 149 150 public virtual KeySizes[] LegalBlockSizes { 151 get { return (KeySizes[]) LegalBlockSizesValue.Clone(); } 152 } 153 154 public virtual KeySizes[] LegalKeySizes { 155 get { return (KeySizes[]) LegalKeySizesValue.Clone(); } 156 } 157 158 public virtual int KeySize { 159 get { return KeySizeValue; } 160 set { 161 if (!ValidKeySize(value)) 162 throw new CryptographicException(Environment.GetResourceString("Cryptography_InvalidKeySize")); 163 164 KeySizeValue = value; 165 KeyValue = null; 166 } 167 } 168 169 public virtual CipherMode Mode { 170 get { return ModeValue; } 171 set { 172 if ((value < CipherMode.CBC) || (CipherMode.CFB < value)) 173 throw new CryptographicException(Environment.GetResourceString("Cryptography_InvalidCipherMode")); 174 175 ModeValue = value; 176 } 177 } 178 179 public virtual PaddingMode Padding { 180 get { return PaddingValue; } 181 set { 182 if ((value < PaddingMode.None) || (PaddingMode.ISO10126 < value)) 183 throw new CryptographicException(Environment.GetResourceString("Cryptography_InvalidPaddingMode")); 184 185 PaddingValue = value; 186 } 187 } 188 189 // 190 // public methods 191 // 192 193 // The following method takes a bit length input and returns whether that length is a valid size 194 // according to LegalKeySizes ValidKeySize(int bitLength)195 public bool ValidKeySize(int bitLength) { 196 KeySizes[] validSizes = this.LegalKeySizes; 197 int i,j; 198 199 if (validSizes == null) return false; 200 for (i=0; i< validSizes.Length; i++) { 201 if (validSizes[i].SkipSize == 0) { 202 if (validSizes[i].MinSize == bitLength) { // assume MinSize = MaxSize 203 return true; 204 } 205 } else { 206 for (j = validSizes[i].MinSize; j<= validSizes[i].MaxSize; 207 j += validSizes[i].SkipSize) { 208 if (j == bitLength) { 209 return true; 210 } 211 } 212 } 213 } 214 return false; 215 } 216 Create()217 static public SymmetricAlgorithm Create() { 218 #if FULL_AOT_RUNTIME 219 return new System.Security.Cryptography.RijndaelManaged (); 220 #else 221 // use the crypto config system to return an instance of 222 // the default SymmetricAlgorithm on this machine 223 return Create("System.Security.Cryptography.SymmetricAlgorithm"); 224 #endif 225 } 226 Create(String algName)227 static public SymmetricAlgorithm Create(String algName) { 228 return (SymmetricAlgorithm) CryptoConfig.CreateFromName(algName); 229 } 230 CreateEncryptor()231 public virtual ICryptoTransform CreateEncryptor() { 232 return CreateEncryptor(Key, IV); 233 } 234 CreateEncryptor(byte[] rgbKey, byte[] rgbIV)235 public abstract ICryptoTransform CreateEncryptor(byte[] rgbKey, byte[] rgbIV); 236 CreateDecryptor()237 public virtual ICryptoTransform CreateDecryptor() { 238 return CreateDecryptor(Key, IV); 239 } 240 CreateDecryptor(byte[] rgbKey, byte[] rgbIV)241 public abstract ICryptoTransform CreateDecryptor(byte[] rgbKey, byte[] rgbIV); 242 GenerateKey()243 public abstract void GenerateKey(); 244 GenerateIV()245 public abstract void GenerateIV(); 246 } 247 } 248