Enable System.Runtime.Remoting tests on Windows
[mono.git] / mcs / class / referencesource / mscorlib / system / security / cryptography / symmetricalgorithm.cs
1 using System.Diagnostics.Contracts;
2 // ==++==
3 // 
4 //   Copyright (c) Microsoft Corporation.  All rights reserved.
5 // 
6 // ==--==
7 // <OWNER>[....]</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     
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
43         void IDisposable.Dispose()
44         {
45             Dispose();
46         }
47 #endif // FEATURE_CORECLR
48
49         public void Dispose()
50         {
51             Dispose(true);
52             GC.SuppressFinalize(this);
53         }
54
55         public void Clear() {
56             (this as IDisposable).Dispose();
57         }
58
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
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
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
227         static public SymmetricAlgorithm Create(String algName) {
228             return (SymmetricAlgorithm) CryptoConfig.CreateFromName(algName);
229         }
230
231         public virtual ICryptoTransform CreateEncryptor() {
232             return CreateEncryptor(Key, IV);
233         }
234
235         public abstract ICryptoTransform CreateEncryptor(byte[] rgbKey, byte[] rgbIV);
236
237         public virtual ICryptoTransform CreateDecryptor() {
238             return CreateDecryptor(Key, IV);
239         }
240
241         public abstract ICryptoTransform CreateDecryptor(byte[] rgbKey, byte[] rgbIV);
242         
243         public abstract void GenerateKey();
244
245         public abstract void GenerateIV();
246     }
247 }