Wrap always_inline and noinline attributes in compiler checks and use MSVC equivalent.
[mono.git] / mcs / class / corlib / Test / System.Security.Cryptography / RijndaelManagedTest.cs
1 //
2 // TestSuite.System.Security.Cryptography.RijndaelManaged.cs
3 //
4 // Authors:
5 //      Andrew Birkett (andy@nobugs.org)
6 //      Sebastien Pouliot  <sebastien@ximian.com>
7 //
8 // Copyright (C) 2005 Novell, Inc (http://www.novell.com)
9 //
10
11 using System;
12 using System.Security.Cryptography;
13
14 using NUnit.Framework;
15
16 namespace MonoTests.System.Security.Cryptography {
17
18         [TestFixture]
19         public class RijndaelManagedTest {
20
21                 private RijndaelManaged aes;
22
23                 [SetUp]
24                 public void SetUp ()
25                 {
26                         aes = new RijndaelManaged ();
27                 }
28
29                 public void CheckCBC(ICryptoTransform encryptor, ICryptoTransform decryptor, 
30                                            byte[] plaintext, byte[] expected) 
31                 {
32         
33                         if ((plaintext.Length % encryptor.InputBlockSize) != 0) {
34                                 throw new ArgumentException("Must have complete blocks");
35                         }
36         
37                         byte[] ciphertext = new byte[plaintext.Length];
38                         for (int i=0; i < plaintext.Length; i += encryptor.InputBlockSize) {
39                                 encryptor.TransformBlock(plaintext, i, encryptor.InputBlockSize, ciphertext, i);
40                         }
41                         Assert.AreEqual (expected, ciphertext, "CBC");
42         
43                         byte[] roundtrip = new byte[plaintext.Length];
44                         for (int i=0; i < ciphertext.Length; i += decryptor.InputBlockSize) {
45                                 decryptor.TransformBlock(ciphertext, i, decryptor.InputBlockSize, roundtrip, i);
46                         }
47                         Assert.AreEqual (plaintext, roundtrip, "CBC-rt");
48                 }
49
50                 [Test]
51                 public void CBC_0() {
52         
53                         byte[] plaintext = new byte[32];
54                         for (int i=0; i < plaintext.Length; i++) plaintext[i] = 0;
55         
56                         byte[] iv = new byte[16];
57                         for (byte i=0; i < iv.Length; i++) {
58                                 iv[i] = 0;
59                         }
60         
61                         RijndaelManaged r = new RijndaelManaged();
62                         byte[] key = new byte[16];      
63         
64                         for (int i=0; i < 16; i++) r.Key[i] = 0;
65                         r.BlockSize = 128;
66                         r.Mode = CipherMode.CBC;
67                         r.Padding = PaddingMode.Zeros;
68                         r.Key = key;
69         
70                         byte[] expected = { 
71                                 0x66, 0xe9, 0x4b, 0xd4, 0xef, 0x8a, 0x2c, 0x3b, 
72                                 0x88, 0x4c, 0xfa, 0x59, 0xca, 0x34, 0x2b, 0x2e, 
73                                 0xf7, 0x95, 0xbd, 0x4a, 0x52, 0xe2, 0x9e, 0xd7, 
74                                 0x13, 0xd3, 0x13, 0xfa, 0x20, 0xe9, 0x8d, 0xbc };
75         
76                         CheckCBC(r.CreateEncryptor(key, iv), r.CreateDecryptor(key, iv), plaintext, expected);
77                 }
78
79                 [Test]
80                 public void CBC_1 ()
81                 {
82                         byte[] plaintext = new byte[32];
83                         for (int i=0; i < plaintext.Length; i++) plaintext[i] = 0;
84         
85                         byte[] iv = new byte[16];
86                         for (byte i=0; i < iv.Length; i++) {
87                                 iv[i] = i;
88                         }
89         
90                         RijndaelManaged r = new RijndaelManaged();
91                         byte[] key = new byte[16];
92                         for (byte i=0; i < 16; i++) key[i] = 0;
93
94                         r.Key = key;
95                         r.BlockSize = 128;
96                         r.Mode = CipherMode.CBC;
97                         r.Padding = PaddingMode.Zeros;
98         
99                         byte[] expected = { 
100                                 0x7a, 0xca, 0x0f, 0xd9, 0xbc, 0xd6, 0xec, 0x7c, 
101                                 0x9f, 0x97, 0x46, 0x66, 0x16, 0xe6, 0xa2, 0x82, 
102                                 0x66, 0xc5, 0x84, 0x17, 0x1d, 0x3c, 0x20, 0x53, 
103                                 0x6f, 0x0a, 0x09, 0xdc, 0x4d, 0x1e, 0x45, 0x3b };
104         
105                         CheckCBC(r.CreateEncryptor(key, iv), r.CreateDecryptor(key, iv), plaintext, expected);
106                 }
107         
108                 public void CheckECBRoundtrip(ICryptoTransform encryptor, ICryptoTransform decryptor, 
109                                            byte[] plaintext, byte[] expected)
110                 {
111                         byte[] ciphertext = new byte[plaintext.Length];
112                         int n = encryptor.TransformBlock(plaintext, 0, plaintext.Length, ciphertext, 0);
113
114                         Assert.AreEqual (expected, ciphertext, "ECB");
115         
116                         byte[] roundtrip = new byte[plaintext.Length];
117                         n = decryptor.TransformBlock(ciphertext, 0, ciphertext.Length, roundtrip, 0);
118
119                         Assert.AreEqual (plaintext, roundtrip, "ECB-rt-len");
120                 }
121
122                 [Test]
123                 public void ECB ()
124                 {
125                         byte[] plaintext = new byte[16];
126                         byte[] iv = new byte[16];
127         
128                         for (int i=0; i < 16; i++) {
129                                 plaintext[i] = (byte) (i*16 + i);
130                         }
131         
132                         RijndaelManaged r = new RijndaelManaged();
133                         r.Mode = CipherMode.ECB;
134                         r.Padding = PaddingMode.Zeros;
135         
136                         byte[] key16 = new byte[16];
137                         byte[] key24 = new byte[24];
138                         byte[] key32 = new byte[32];
139         
140                         for (int i=0; i < 32; i++) {
141                                 if (i < 16) key16[i] = (byte) i;
142                                 if (i < 24) key24[i] = (byte) i;
143                                 key32[i] = (byte) i;
144                         }
145         
146                                 
147                         byte[] exp16 = { 0x69, 0xc4, 0xe0, 0xd8, 0x6a, 0x7b, 0x04, 0x30,
148                                          0xd8, 0xcd, 0xb7, 0x80, 0x70, 0xb4, 0xc5, 0x5a };
149                         byte[] exp24 = { 0xdd, 0xa9, 0x7c, 0xa4, 0x86, 0x4c, 0xdf, 0xe0,
150                                          0x6e, 0xaf, 0x70, 0xa0, 0xec, 0x0d, 0x71, 0x91 };
151                         byte[] exp32 = { 0x8e, 0xa2, 0xb7, 0xca, 0x51, 0x67, 0x45, 0xbf,
152                                          0xea, 0xfc, 0x49, 0x90, 0x4b, 0x49, 0x60, 0x89 }; 
153         
154                         r.Key = key16;
155                         r.KeySize = 128;        
156                         CheckECBRoundtrip(
157                                 r.CreateEncryptor(key16, iv), r.CreateDecryptor(key16, iv), 
158                                 plaintext, exp16
159                         );
160         
161         
162                         r.Key = key24;
163                         r.KeySize = 192;
164                         CheckECBRoundtrip(
165                                 r.CreateEncryptor(key24, iv), r.CreateDecryptor(key24, iv), 
166                                 plaintext, exp24
167                         );
168         
169         
170                         r.Key = key32;
171                         r.KeySize = 256;
172                         CheckECBRoundtrip(
173                                 r.CreateEncryptor(key32, iv), r.CreateDecryptor(key32, iv), 
174                                 plaintext, exp32
175                         );
176                 }
177
178                 [Test]
179                 [ExpectedException (typeof (CryptographicException))]
180                 public void CreateEncryptor_KeyNull ()
181                 {
182                         ICryptoTransform encryptor = aes.CreateEncryptor (null, aes.IV);
183                         byte[] data = new byte[encryptor.InputBlockSize];
184                         byte[] encdata = encryptor.TransformFinalBlock (data, 0, data.Length);
185
186                         ICryptoTransform decryptor = aes.CreateDecryptor (aes.Key, aes.IV);
187                         byte[] decdata = decryptor.TransformFinalBlock (encdata, 0, encdata.Length);
188                         // null key != SymmetricAlgorithm.Key
189                 }
190
191                 [Test]
192                 public void CreateEncryptor_IvNull ()
193                 {
194                         ICryptoTransform encryptor = aes.CreateEncryptor (aes.Key, null);
195                         byte[] data = new byte[encryptor.InputBlockSize];
196                         byte[] encdata = encryptor.TransformFinalBlock (data, 0, data.Length);
197
198                         ICryptoTransform decryptor = aes.CreateDecryptor (aes.Key, aes.IV);
199                         byte[] decdata = decryptor.TransformFinalBlock (encdata, 0, encdata.Length);
200                         Assert.IsFalse (BitConverter.ToString (data) == BitConverter.ToString (decdata), "Compare");
201                         // null iv != SymmetricAlgorithm.IV
202                 }
203
204                 [Test]
205                 public void CreateEncryptor_KeyIv ()
206                 {
207                         byte[] originalKey = aes.Key;
208                         byte[] originalIV = aes.IV;
209
210                         byte[] key = (byte[]) aes.Key.Clone ();
211                         Array.Reverse (key);
212                         byte[] iv = (byte[]) aes.IV.Clone ();
213                         Array.Reverse (iv);
214
215                         Assert.IsNotNull (aes.CreateEncryptor (key, iv), "CreateEncryptor");
216
217                         Assert.AreEqual (originalKey, aes.Key, "Key");
218                         Assert.AreEqual (originalIV, aes.IV, "IV");
219                         // SymmetricAlgorithm Key and IV not changed by CreateEncryptor
220                 }
221
222                 [Test]
223                 [ExpectedException (typeof (CryptographicException))]
224                 [Category ("NotWorking")] // data is bad but no exception is thrown
225                 public void CreateDecryptor_KeyNull ()
226                 {
227                         ICryptoTransform encryptor = aes.CreateEncryptor (aes.Key, aes.IV);
228                         byte[] data = new byte[encryptor.InputBlockSize];
229                         byte[] encdata = encryptor.TransformFinalBlock (data, 0, data.Length);
230
231                         ICryptoTransform decryptor = aes.CreateDecryptor (null, aes.IV);
232                         byte[] decdata = decryptor.TransformFinalBlock (encdata, 0, encdata.Length);
233                         // null key != SymmetricAlgorithm.Key
234                 }
235
236                 [Test]
237                 public void CreateDecryptor_IvNull ()
238                 {
239                         ICryptoTransform encryptor = aes.CreateEncryptor (aes.Key, aes.IV);
240                         byte[] data = new byte[encryptor.InputBlockSize];
241                         byte[] encdata = encryptor.TransformFinalBlock (data, 0, data.Length);
242
243                         ICryptoTransform decryptor = aes.CreateDecryptor (aes.Key, null);
244                         byte[] decdata = decryptor.TransformFinalBlock (encdata, 0, encdata.Length);
245                         Assert.IsFalse (BitConverter.ToString (data) == BitConverter.ToString (decdata), "Compare");
246                         // null iv != SymmetricAlgorithm.IV
247                 }
248
249                 [Test]
250                 public void CreateDecryptor_KeyIv ()
251                 {
252                         byte[] originalKey = aes.Key;
253                         byte[] originalIV = aes.IV;
254
255                         byte[] key = (byte[]) aes.Key.Clone ();
256                         Array.Reverse (key);
257                         byte[] iv = (byte[]) aes.IV.Clone ();
258                         Array.Reverse (iv);
259
260                         Assert.IsNotNull (aes.CreateEncryptor (key, iv), "CreateDecryptor");
261
262                         Assert.AreEqual (originalKey, aes.Key, "Key");
263                         Assert.AreEqual (originalIV, aes.IV, "IV");
264                         // SymmetricAlgorithm Key and IV not changed by CreateDecryptor
265                 }
266
267                 // Setting the IV is more restrictive than supplying an IV to
268                 // CreateEncryptor and CreateDecryptor. See bug #76483
269
270                 private ICryptoTransform CreateEncryptor_IV (int size)
271                 {
272                         byte[] iv = (size == -1) ? null : new byte[size];
273                         return aes.CreateEncryptor (aes.Key, iv);
274                 }
275
276                 [Test]
277                 public void CreateEncryptor_IV_Null ()
278                 {
279                         int size = (aes.BlockSize >> 3) - 1;
280                         CreateEncryptor_IV (-1);
281                 }
282
283                 [Test]
284                 [ExpectedException (typeof (CryptographicException))]
285                 public void CreateEncryptor_IV_Zero ()
286                 {
287                         int size = (aes.BlockSize >> 3) - 1;
288                         CreateEncryptor_IV (0);
289                 }
290
291                 [Test]
292                 [ExpectedException (typeof (CryptographicException))]
293                 public void CreateEncryptor_IV_TooSmall ()
294                 {
295                         int size = (aes.BlockSize >> 3) - 1;
296                         CreateEncryptor_IV (size);
297                 }
298
299                 [Test]
300                 public void CreateEncryptor_IV_BlockSize ()
301                 {
302                         int size = (aes.BlockSize >> 3);
303                         CreateEncryptor_IV (size);
304                 }
305
306 #if !NET_2_1
307                 [Test]
308                 [ExpectedException (typeof (CryptographicException))]
309                 // Rijndael is the only implementation that has
310                 // this behaviour for IV that are too large
311                 [Category ("NotWorking")]
312                 public void CreateEncryptor_IV_TooBig ()
313                 {
314                         int size = aes.BlockSize; // 8 times too big
315                         CreateEncryptor_IV (size);
316                 }
317 #endif
318
319                 private ICryptoTransform CreateDecryptor_IV (int size)
320                 {
321                         byte[] iv = (size == -1) ? null : new byte[size];
322                         return aes.CreateDecryptor (aes.Key, iv);
323                 }
324
325                 [Test]
326                 public void CreateDecryptor_IV_Null ()
327                 {
328                         int size = (aes.BlockSize >> 3) - 1;
329                         CreateDecryptor_IV (-1);
330                 }
331
332                 [Test]
333                 [ExpectedException (typeof (CryptographicException))]
334                 public void CreateDecryptor_IV_Zero ()
335                 {
336                         int size = (aes.BlockSize >> 3) - 1;
337                         CreateDecryptor_IV (0);
338                 }
339
340                 [Test]
341                 [ExpectedException (typeof (CryptographicException))]
342                 public void CreateDecryptor_IV_TooSmall ()
343                 {
344                         int size = (aes.BlockSize >> 3) - 1;
345                         CreateDecryptor_IV (size);
346                 }
347
348                 [Test]
349                 public void CreateDecryptor_IV_BlockSize ()
350                 {
351                         int size = (aes.BlockSize >> 3);
352                         CreateDecryptor_IV (size);
353                 }
354 #if !NET_2_1
355                 [Test]
356                 [ExpectedException (typeof (CryptographicException))]
357                 // Rijndael is the only implementation that has
358                 // this behaviour for IV that are too large
359                 [Category ("NotWorking")]
360                 public void CreateDecryptor_IV_TooBig ()
361                 {
362                         int size = aes.BlockSize; // 8 times too big
363                         CreateDecryptor_IV (size);
364                 }
365 #endif
366         }
367 }