[runtime] Overwrite stacktrace for exception on re-throw. Fixes #1856.
[mono.git] / mcs / class / corlib / System.Security.Cryptography / RC2CryptoServiceProvider.cs
1 //
2 // System.Security.Cryptography.RC2CryptoServiceProvider.cs
3 //
4 // Authors:
5 //      Andrew Birkett (andy@nobugs.org)
6 //      Sebastien Pouliot (sebastien@ximian.com)
7 //
8 // Portions (C) 2002 Motus Technologies Inc. (http://www.motus.com)
9 // Copyright (C) 2004-2005 Novell, Inc (http://www.novell.com)
10 //
11 // Permission is hereby granted, free of charge, to any person obtaining
12 // a copy of this software and associated documentation files (the
13 // "Software"), to deal in the Software without restriction, including
14 // without limitation the rights to use, copy, modify, merge, publish,
15 // distribute, sublicense, and/or sell copies of the Software, and to
16 // permit persons to whom the Software is furnished to do so, subject to
17 // the following conditions:
18 // 
19 // The above copyright notice and this permission notice shall be
20 // included in all copies or substantial portions of the Software.
21 // 
22 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
23 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
24 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
25 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
26 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
27 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
28 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
29 //
30
31 using System.Globalization;
32 using System.Runtime.InteropServices;
33
34 using Mono.Security.Cryptography;
35
36 namespace System.Security.Cryptography {
37
38         // References:
39         // a.   IETF RFC2286: A Description of the RC2(r) Encryption Algorithm
40         //      http://www.ietf.org/rfc/rfc2268.txt
41         
42         [ComVisible (true)]
43         public sealed class RC2CryptoServiceProvider : RC2 {
44                 private bool _useSalt;
45         
46                 public RC2CryptoServiceProvider ()
47                 {
48                 }
49         
50                 public override int EffectiveKeySize {
51                         get { return base.EffectiveKeySize; }
52                         set {
53                                 if (value != KeySizeValue) {
54                                         throw new CryptographicUnexpectedOperationException (
55                                                 Locale.GetText ("Effective key size must match key size for compatibility"));
56                                 }
57                                 base.EffectiveKeySize = value; 
58                         }
59                 }
60         
61                 public override ICryptoTransform CreateDecryptor (byte[] rgbKey, byte[] rgbIV)
62                 {
63                         return new RC2Transform (this, false, rgbKey, rgbIV);
64                 }
65         
66                 public override ICryptoTransform CreateEncryptor (byte[] rgbKey, byte[] rgbIV)
67                 {
68                         return new RC2Transform (this, true, rgbKey, rgbIV);
69                 }
70         
71                 public override void GenerateIV ()
72                 {
73                         IVValue = KeyBuilder.IV (BlockSizeValue >> 3);
74                 }
75         
76                 public override void GenerateKey ()
77                 {
78                         KeyValue = KeyBuilder.Key (KeySizeValue >> 3);
79                 }
80                 [MonoTODO ("Use salt in algorithm")]
81                 [ComVisible (false)]
82                 public bool UseSalt {
83                         get { return _useSalt; }
84                         set { _useSalt = value; }
85                 }
86         }
87         
88         internal class RC2Transform : SymmetricTransform {
89         
90                 private UInt16 R0, R1, R2, R3;  // state
91                 private UInt16[] K;             // expanded key
92                 private int j;                  // Key indexer
93         
94                 public RC2Transform (RC2 rc2Algo, bool encryption, byte[] key, byte[] iv)
95                         : base (rc2Algo, encryption, iv)
96                 {
97                         int t1 = rc2Algo.EffectiveKeySize;
98                         if (key == null) {
99                                 key = KeyBuilder.Key (rc2Algo.KeySize >> 3);
100                         } else {
101                                 key = (byte[]) key.Clone ();
102                                 t1 = Math.Min (t1, key.Length << 3);
103                         }
104
105                         int t = key.Length;
106                         if (!KeySizes.IsLegalKeySize (rc2Algo.LegalKeySizes, (t << 3))) {
107                                 string msg = Locale.GetText ("Key is too small ({0} bytes), it should be between {1} and {2} bytes long.",
108                                         t, 5, 16);
109                                 throw new CryptographicException (msg);
110                         }
111
112                         // Expand key into a byte array, then convert to word
113                         // array since we always access the key in 16bit chunks.
114                         byte[] L = new byte [128];
115         
116                         int t8 = ((t1 + 7) >> 3); // divide by 8
117                         int tm = 255 % (2 << (8 + t1 - (t8 << 3) - 1));
118         
119                         for (int i=0; i < t; i++)
120                                 L [i] = key [i];
121                         for (int i=t; i < 128; i++) 
122                                 L [i] = (byte) (pitable [(L [i-1] + L [i-t]) & 0xff]);
123         
124                         L [128-t8] = pitable [L [128-t8] & tm];
125         
126                         for (int i=127-t8; i >= 0; i--) 
127                                 L [i] = pitable [L [i+1] ^ L [i+t8]];
128         
129                         K = new UInt16 [64];
130                         int pos = 0;
131                         for (int i=0; i < 64; i++) 
132                                 K [i] = (UInt16) (L [pos++] + (L [pos++] << 8));
133                 }
134         
135                 protected override void ECB (byte[] input, byte[] output) 
136                 {
137                         // unrolled loop, eliminated mul
138                         R0 = (UInt16) (input [0] | (input [1] << 8));
139                         R1 = (UInt16) (input [2] | (input [3] << 8));
140                         R2 = (UInt16) (input [4] | (input [5] << 8));
141                         R3 = (UInt16) (input [6] | (input [7] << 8));
142         
143                         if (encrypt) {
144                                 j = 0;
145                                 // inline, but looped, Mix(); Mix(); Mix(); Mix(); Mix();
146                                 while (j <= 16) {
147                                         R0 += (UInt16) (K[j++] + (R3 & R2) + ((~R3) & R1));
148                                         R0 = (UInt16) ((R0 << 1) | (R0 >> 15));
149         
150                                         R1 += (UInt16) (K[j++] + (R0 & R3) + ((~R0) & R2));
151                                         R1 = (UInt16) ((R1 << 2) | (R1 >> 14));
152         
153                                         R2 += (UInt16) (K[j++] + (R1 & R0) + ((~R1) & R3));
154                                         R2 = (UInt16) ((R2 << 3) | (R2 >> 13));
155         
156                                         R3 += (UInt16) (K[j++] + (R2 & R1) + ((~R2) & R0));
157                                         R3 = (UInt16) ((R3 << 5) | (R3 >> 11));
158                                 }
159         
160                                 // inline Mash(); j == 20
161                                 R0 += K [R3 & 63];
162                                 R1 += K [R0 & 63];
163                                 R2 += K [R1 & 63];
164                                 R3 += K [R2 & 63];
165         
166                                 // inline, but looped, Mix(); Mix(); Mix(); Mix(); Mix(); Mix();
167                                 while (j <= 40) {
168                                         R0 += (UInt16) (K[j++] + (R3 & R2) + ((~R3) & R1));
169                                         R0 = (UInt16) ((R0 << 1) | (R0 >> 15));
170         
171                                         R1 += (UInt16) (K[j++] + (R0 & R3) + ((~R0) & R2));
172                                         R1 = (UInt16) ((R1 << 2) | (R1 >> 14));
173         
174                                         R2 += (UInt16) (K[j++] + (R1 & R0) + ((~R1) & R3));
175                                         R2 = (UInt16) ((R2 << 3) | (R2 >> 13));
176         
177                                         R3 += (UInt16) (K[j++] + (R2 & R1) + ((~R2) & R0));
178                                         R3 = (UInt16) ((R3 << 5) | (R3 >> 11));
179                                 }
180         
181                                 // inline Mash(); j == 44
182                                 R0 += K [R3 & 63];
183                                 R1 += K [R0 & 63];
184                                 R2 += K [R1 & 63];
185                                 R3 += K [R2 & 63];
186         
187                                 // inline, but looped, Mix(); Mix(); Mix(); Mix(); Mix();
188                                 while (j < 64) {
189                                         R0 += (UInt16) (K[j++] + (R3 & R2) + ((~R3) & R1));
190                                         R0 = (UInt16) ((R0 << 1) | (R0 >> 15));
191         
192                                         R1 += (UInt16) (K[j++] + (R0 & R3) + ((~R0) & R2));
193                                         R1 = (UInt16) ((R1 << 2) | (R1 >> 14));
194         
195                                         R2 += (UInt16) (K[j++] + (R1 & R0) + ((~R1) & R3));
196                                         R2 = (UInt16) ((R2 << 3) | (R2 >> 13));
197         
198                                         R3 += (UInt16) (K[j++] + (R2 & R1) + ((~R2) & R0));
199                                         R3 = (UInt16) ((R3 << 5) | (R3 >> 11));
200                                 }
201                         } 
202                         else {
203                                 j = 63;
204                                 // inline, but looped, RMix(); RMix(); RMix(); RMix(); RMix();
205                                 while (j >= 44) {
206                                         R3 = (UInt16) ((R3 >> 5) | (R3 << 11));
207                                         R3 -= (UInt16) (K[j--] + (R2 & R1) + ((~R2) & R0));
208         
209                                         R2 = (UInt16) ((R2 >> 3) | (R2 << 13));
210                                         R2 -= (UInt16) (K[j--] + (R1 & R0) + ((~R1) & R3));
211         
212                                         R1 = (UInt16) ((R1 >> 2) | (R1 << 14));
213                                         R1 -= (UInt16) (K[j--] + (R0 & R3) + ((~R0) & R2));
214         
215                                         R0 = (UInt16) ((R0 >> 1) | (R0 << 15));
216                                         R0 -= (UInt16) (K[j--] + (R3 & R2) + ((~R3) & R1));
217                                 }
218         
219                                 // inline RMash();
220                                 R3 -= K [R2 & 63];
221                                 R2 -= K [R1 & 63];
222                                 R1 -= K [R0 & 63];
223                                 R0 -= K [R3 & 63];
224         
225                                 // inline, but looped, RMix(); RMix(); RMix(); RMix(); RMix(); RMix();
226                                 while (j >= 20) {
227                                         R3 = (UInt16) ((R3 >> 5) | (R3 << 11));
228                                         R3 -= (UInt16) (K[j--] + (R2 & R1) + ((~R2) & R0));
229         
230                                         R2 = (UInt16) ((R2 >> 3) | (R2 << 13));
231                                         R2 -= (UInt16) (K[j--] + (R1 & R0) + ((~R1) & R3));
232         
233                                         R1 = (UInt16) ((R1 >> 2) | (R1 << 14));
234                                         R1 -= (UInt16) (K[j--] + (R0 & R3) + ((~R0) & R2));
235         
236                                         R0 = (UInt16) ((R0 >> 1) | (R0 << 15));
237                                         R0 -= (UInt16) (K[j--] + (R3 & R2) + ((~R3) & R1));
238                                 }
239         
240                                 // inline RMash();
241                                 R3 -= K [R2 & 63];
242                                 R2 -= K [R1 & 63];
243                                 R1 -= K [R0 & 63];
244                                 R0 -= K [R3 & 63];
245         
246                                 // inline, but looped, RMix(); RMix(); RMix(); RMix(); RMix();
247                                 while (j >= 0) {
248                                         R3 = (UInt16) ((R3 >> 5) | (R3 << 11));
249                                         R3 -= (UInt16) (K[j--] + (R2 & R1) + ((~R2) & R0));
250         
251                                         R2 = (UInt16) ((R2 >> 3) | (R2 << 13));
252                                         R2 -= (UInt16) (K[j--] + (R1 & R0) + ((~R1) & R3));
253         
254                                         R1 = (UInt16) ((R1 >> 2) | (R1 << 14));
255                                         R1 -= (UInt16) (K[j--] + (R0 & R3) + ((~R0) & R2));
256         
257                                         R0 = (UInt16) ((R0 >> 1) | (R0 << 15));
258                                         R0 -= (UInt16) (K[j--] + (R3 & R2) + ((~R3) & R1));
259                                 }
260                         }
261         
262                         // unrolled loop
263                         output[0] = (byte) R0;
264                         output[1] = (byte) (R0 >> 8);
265                         output[2] = (byte) R1;
266                         output[3] = (byte) (R1 >> 8);
267                         output[4] = (byte) R2;
268                         output[5] = (byte) (R2 >> 8);
269                         output[6] = (byte) R3;
270                         output[7] = (byte) (R3 >> 8);
271                 }
272         
273                 static readonly byte[] pitable = {
274                         0xd9, 0x78, 0xf9, 0xc4, 0x19, 0xdd, 0xb5, 0xed, 
275                         0x28, 0xe9, 0xfd, 0x79, 0x4a, 0xa0, 0xd8, 0x9d,
276                         0xc6, 0x7e, 0x37, 0x83, 0x2b, 0x76, 0x53, 0x8e, 
277                         0x62, 0x4c, 0x64, 0x88, 0x44, 0x8b, 0xfb, 0xa2,
278                         0x17, 0x9a, 0x59, 0xf5, 0x87, 0xb3, 0x4f, 0x13, 
279                         0x61, 0x45, 0x6d, 0x8d, 0x09, 0x81, 0x7d, 0x32,
280                         0xbd, 0x8f, 0x40, 0xeb, 0x86, 0xb7, 0x7b, 0x0b, 
281                         0xf0, 0x95, 0x21, 0x22, 0x5c, 0x6b, 0x4e, 0x82,
282                         0x54, 0xd6, 0x65, 0x93, 0xce, 0x60, 0xb2, 0x1c, 
283                         0x73, 0x56, 0xc0, 0x14, 0xa7, 0x8c, 0xf1, 0xdc,
284                         0x12, 0x75, 0xca, 0x1f, 0x3b, 0xbe, 0xe4, 0xd1, 
285                         0x42, 0x3d, 0xd4, 0x30, 0xa3, 0x3c, 0xb6, 0x26,
286                         0x6f, 0xbf, 0x0e, 0xda, 0x46, 0x69, 0x07, 0x57, 
287                         0x27, 0xf2, 0x1d, 0x9b, 0xbc, 0x94, 0x43, 0x03,
288                         0xf8, 0x11, 0xc7, 0xf6, 0x90, 0xef, 0x3e, 0xe7, 
289                         0x06, 0xc3, 0xd5, 0x2f, 0xc8, 0x66, 0x1e, 0xd7,
290                         0x08, 0xe8, 0xea, 0xde, 0x80, 0x52, 0xee, 0xf7, 
291                         0x84, 0xaa, 0x72, 0xac, 0x35, 0x4d, 0x6a, 0x2a,
292                         0x96, 0x1a, 0xd2, 0x71, 0x5a, 0x15, 0x49, 0x74, 
293                         0x4b, 0x9f, 0xd0, 0x5e, 0x04, 0x18, 0xa4, 0xec,
294                         0xc2, 0xe0, 0x41, 0x6e, 0x0f, 0x51, 0xcb, 0xcc, 
295                         0x24, 0x91, 0xaf, 0x50, 0xa1, 0xf4, 0x70, 0x39,
296                         0x99, 0x7c, 0x3a, 0x85, 0x23, 0xb8, 0xb4, 0x7a, 
297                         0xfc, 0x02, 0x36, 0x5b, 0x25, 0x55, 0x97, 0x31,
298                         0x2d, 0x5d, 0xfa, 0x98, 0xe3, 0x8a, 0x92, 0xae, 
299                         0x05, 0xdf, 0x29, 0x10, 0x67, 0x6c, 0xba, 0xc9,
300                         0xd3, 0x00, 0xe6, 0xcf, 0xe1, 0x9e, 0xa8, 0x2c, 
301                         0x63, 0x16, 0x01, 0x3f, 0x58, 0xe2, 0x89, 0xa9,
302                         0x0d, 0x38, 0x34, 0x1b, 0xab, 0x33, 0xff, 0xb0, 
303                         0xbb, 0x48, 0x0c, 0x5f, 0xb9, 0xb1, 0xcd, 0x2e,
304                         0xc5, 0xf3, 0xdb, 0x47, 0xe5, 0xa5, 0x9c, 0x77, 
305                         0x0a, 0xa6, 0x20, 0x68, 0xfe, 0x7f, 0xc1, 0xad 
306                 };
307         }
308 }
309