use MOONLIGHT symbol
[mono-project.git] / mcs / class / corlib / System.Security.Cryptography / RC2CryptoServiceProvider.cs
blob6a5d8461ac051421ff8ee69dedae29570ce6e097
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)
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.
31 #if !MOONLIGHT
33 using System.Globalization;
34 using System.Runtime.InteropServices;
36 using Mono.Security.Cryptography;
38 namespace System.Security.Cryptography {
40 // References:
41 // a. IETF RFC2286: A Description of the RC2(r) Encryption Algorithm
42 // http://www.ietf.org/rfc/rfc2268.txt
44 [ComVisible (true)]
45 public sealed class RC2CryptoServiceProvider : RC2 {
46 private bool _useSalt;
48 public RC2CryptoServiceProvider ()
52 public override int EffectiveKeySize {
53 get { return base.EffectiveKeySize; }
54 set {
55 if (value != KeySizeValue) {
56 throw new CryptographicUnexpectedOperationException (
57 Locale.GetText ("Effective key size must match key size for compatibility"));
59 base.EffectiveKeySize = value;
63 public override ICryptoTransform CreateDecryptor (byte[] rgbKey, byte[] rgbIV)
65 return new RC2Transform (this, false, rgbKey, rgbIV);
68 public override ICryptoTransform CreateEncryptor (byte[] rgbKey, byte[] rgbIV)
70 return new RC2Transform (this, true, rgbKey, rgbIV);
73 public override void GenerateIV ()
75 IVValue = KeyBuilder.IV (BlockSizeValue >> 3);
78 public override void GenerateKey ()
80 KeyValue = KeyBuilder.Key (KeySizeValue >> 3);
82 [MonoTODO ("Use salt in algorithm")]
83 [ComVisible (false)]
84 public bool UseSalt {
85 get { return _useSalt; }
86 set { _useSalt = value; }
90 internal class RC2Transform : SymmetricTransform {
92 private UInt16 R0, R1, R2, R3; // state
93 private UInt16[] K; // expanded key
94 private int j; // Key indexer
96 public RC2Transform (RC2 rc2Algo, bool encryption, byte[] key, byte[] iv)
97 : base (rc2Algo, encryption, iv)
99 #if ONLY_1_1
100 if (key == null)
101 throw new ArgumentNullException ("key");
102 #endif
103 int t1 = rc2Algo.EffectiveKeySize;
104 if (key == null) {
105 key = KeyBuilder.Key (rc2Algo.KeySize >> 3);
106 } else {
107 key = (byte[]) key.Clone ();
108 t1 = Math.Min (t1, key.Length << 3);
111 int t = key.Length;
112 if (!KeySizes.IsLegalKeySize (rc2Algo.LegalKeySizes, (t << 3))) {
113 string msg = Locale.GetText ("Key is too small ({0} bytes), it should be between {1} and {2} bytes long.",
114 t, 5, 16);
115 throw new CryptographicException (msg);
118 // Expand key into a byte array, then convert to word
119 // array since we always access the key in 16bit chunks.
120 byte[] L = new byte [128];
122 int t8 = ((t1 + 7) >> 3); // divide by 8
123 int tm = 255 % (2 << (8 + t1 - (t8 << 3) - 1));
125 for (int i=0; i < t; i++)
126 L [i] = key [i];
127 for (int i=t; i < 128; i++)
128 L [i] = (byte) (pitable [(L [i-1] + L [i-t]) & 0xff]);
130 L [128-t8] = pitable [L [128-t8] & tm];
132 for (int i=127-t8; i >= 0; i--)
133 L [i] = pitable [L [i+1] ^ L [i+t8]];
135 K = new UInt16 [64];
136 int pos = 0;
137 for (int i=0; i < 64; i++)
138 K [i] = (UInt16) (L [pos++] + (L [pos++] << 8));
141 protected override void ECB (byte[] input, byte[] output)
143 // unrolled loop, eliminated mul
144 R0 = (UInt16) (input [0] | (input [1] << 8));
145 R1 = (UInt16) (input [2] | (input [3] << 8));
146 R2 = (UInt16) (input [4] | (input [5] << 8));
147 R3 = (UInt16) (input [6] | (input [7] << 8));
149 if (encrypt) {
150 j = 0;
151 // inline, but looped, Mix(); Mix(); Mix(); Mix(); Mix();
152 while (j <= 16) {
153 R0 += (UInt16) (K[j++] + (R3 & R2) + ((~R3) & R1));
154 R0 = (UInt16) ((R0 << 1) | (R0 >> 15));
156 R1 += (UInt16) (K[j++] + (R0 & R3) + ((~R0) & R2));
157 R1 = (UInt16) ((R1 << 2) | (R1 >> 14));
159 R2 += (UInt16) (K[j++] + (R1 & R0) + ((~R1) & R3));
160 R2 = (UInt16) ((R2 << 3) | (R2 >> 13));
162 R3 += (UInt16) (K[j++] + (R2 & R1) + ((~R2) & R0));
163 R3 = (UInt16) ((R3 << 5) | (R3 >> 11));
166 // inline Mash(); j == 20
167 R0 += K [R3 & 63];
168 R1 += K [R0 & 63];
169 R2 += K [R1 & 63];
170 R3 += K [R2 & 63];
172 // inline, but looped, Mix(); Mix(); Mix(); Mix(); Mix(); Mix();
173 while (j <= 40) {
174 R0 += (UInt16) (K[j++] + (R3 & R2) + ((~R3) & R1));
175 R0 = (UInt16) ((R0 << 1) | (R0 >> 15));
177 R1 += (UInt16) (K[j++] + (R0 & R3) + ((~R0) & R2));
178 R1 = (UInt16) ((R1 << 2) | (R1 >> 14));
180 R2 += (UInt16) (K[j++] + (R1 & R0) + ((~R1) & R3));
181 R2 = (UInt16) ((R2 << 3) | (R2 >> 13));
183 R3 += (UInt16) (K[j++] + (R2 & R1) + ((~R2) & R0));
184 R3 = (UInt16) ((R3 << 5) | (R3 >> 11));
187 // inline Mash(); j == 44
188 R0 += K [R3 & 63];
189 R1 += K [R0 & 63];
190 R2 += K [R1 & 63];
191 R3 += K [R2 & 63];
193 // inline, but looped, Mix(); Mix(); Mix(); Mix(); Mix();
194 while (j < 64) {
195 R0 += (UInt16) (K[j++] + (R3 & R2) + ((~R3) & R1));
196 R0 = (UInt16) ((R0 << 1) | (R0 >> 15));
198 R1 += (UInt16) (K[j++] + (R0 & R3) + ((~R0) & R2));
199 R1 = (UInt16) ((R1 << 2) | (R1 >> 14));
201 R2 += (UInt16) (K[j++] + (R1 & R0) + ((~R1) & R3));
202 R2 = (UInt16) ((R2 << 3) | (R2 >> 13));
204 R3 += (UInt16) (K[j++] + (R2 & R1) + ((~R2) & R0));
205 R3 = (UInt16) ((R3 << 5) | (R3 >> 11));
208 else {
209 j = 63;
210 // inline, but looped, RMix(); RMix(); RMix(); RMix(); RMix();
211 while (j >= 44) {
212 R3 = (UInt16) ((R3 >> 5) | (R3 << 11));
213 R3 -= (UInt16) (K[j--] + (R2 & R1) + ((~R2) & R0));
215 R2 = (UInt16) ((R2 >> 3) | (R2 << 13));
216 R2 -= (UInt16) (K[j--] + (R1 & R0) + ((~R1) & R3));
218 R1 = (UInt16) ((R1 >> 2) | (R1 << 14));
219 R1 -= (UInt16) (K[j--] + (R0 & R3) + ((~R0) & R2));
221 R0 = (UInt16) ((R0 >> 1) | (R0 << 15));
222 R0 -= (UInt16) (K[j--] + (R3 & R2) + ((~R3) & R1));
225 // inline RMash();
226 R3 -= K [R2 & 63];
227 R2 -= K [R1 & 63];
228 R1 -= K [R0 & 63];
229 R0 -= K [R3 & 63];
231 // inline, but looped, RMix(); RMix(); RMix(); RMix(); RMix(); RMix();
232 while (j >= 20) {
233 R3 = (UInt16) ((R3 >> 5) | (R3 << 11));
234 R3 -= (UInt16) (K[j--] + (R2 & R1) + ((~R2) & R0));
236 R2 = (UInt16) ((R2 >> 3) | (R2 << 13));
237 R2 -= (UInt16) (K[j--] + (R1 & R0) + ((~R1) & R3));
239 R1 = (UInt16) ((R1 >> 2) | (R1 << 14));
240 R1 -= (UInt16) (K[j--] + (R0 & R3) + ((~R0) & R2));
242 R0 = (UInt16) ((R0 >> 1) | (R0 << 15));
243 R0 -= (UInt16) (K[j--] + (R3 & R2) + ((~R3) & R1));
246 // inline RMash();
247 R3 -= K [R2 & 63];
248 R2 -= K [R1 & 63];
249 R1 -= K [R0 & 63];
250 R0 -= K [R3 & 63];
252 // inline, but looped, RMix(); RMix(); RMix(); RMix(); RMix();
253 while (j >= 0) {
254 R3 = (UInt16) ((R3 >> 5) | (R3 << 11));
255 R3 -= (UInt16) (K[j--] + (R2 & R1) + ((~R2) & R0));
257 R2 = (UInt16) ((R2 >> 3) | (R2 << 13));
258 R2 -= (UInt16) (K[j--] + (R1 & R0) + ((~R1) & R3));
260 R1 = (UInt16) ((R1 >> 2) | (R1 << 14));
261 R1 -= (UInt16) (K[j--] + (R0 & R3) + ((~R0) & R2));
263 R0 = (UInt16) ((R0 >> 1) | (R0 << 15));
264 R0 -= (UInt16) (K[j--] + (R3 & R2) + ((~R3) & R1));
268 // unrolled loop
269 output[0] = (byte) R0;
270 output[1] = (byte) (R0 >> 8);
271 output[2] = (byte) R1;
272 output[3] = (byte) (R1 >> 8);
273 output[4] = (byte) R2;
274 output[5] = (byte) (R2 >> 8);
275 output[6] = (byte) R3;
276 output[7] = (byte) (R3 >> 8);
279 static readonly byte[] pitable = {
280 0xd9, 0x78, 0xf9, 0xc4, 0x19, 0xdd, 0xb5, 0xed,
281 0x28, 0xe9, 0xfd, 0x79, 0x4a, 0xa0, 0xd8, 0x9d,
282 0xc6, 0x7e, 0x37, 0x83, 0x2b, 0x76, 0x53, 0x8e,
283 0x62, 0x4c, 0x64, 0x88, 0x44, 0x8b, 0xfb, 0xa2,
284 0x17, 0x9a, 0x59, 0xf5, 0x87, 0xb3, 0x4f, 0x13,
285 0x61, 0x45, 0x6d, 0x8d, 0x09, 0x81, 0x7d, 0x32,
286 0xbd, 0x8f, 0x40, 0xeb, 0x86, 0xb7, 0x7b, 0x0b,
287 0xf0, 0x95, 0x21, 0x22, 0x5c, 0x6b, 0x4e, 0x82,
288 0x54, 0xd6, 0x65, 0x93, 0xce, 0x60, 0xb2, 0x1c,
289 0x73, 0x56, 0xc0, 0x14, 0xa7, 0x8c, 0xf1, 0xdc,
290 0x12, 0x75, 0xca, 0x1f, 0x3b, 0xbe, 0xe4, 0xd1,
291 0x42, 0x3d, 0xd4, 0x30, 0xa3, 0x3c, 0xb6, 0x26,
292 0x6f, 0xbf, 0x0e, 0xda, 0x46, 0x69, 0x07, 0x57,
293 0x27, 0xf2, 0x1d, 0x9b, 0xbc, 0x94, 0x43, 0x03,
294 0xf8, 0x11, 0xc7, 0xf6, 0x90, 0xef, 0x3e, 0xe7,
295 0x06, 0xc3, 0xd5, 0x2f, 0xc8, 0x66, 0x1e, 0xd7,
296 0x08, 0xe8, 0xea, 0xde, 0x80, 0x52, 0xee, 0xf7,
297 0x84, 0xaa, 0x72, 0xac, 0x35, 0x4d, 0x6a, 0x2a,
298 0x96, 0x1a, 0xd2, 0x71, 0x5a, 0x15, 0x49, 0x74,
299 0x4b, 0x9f, 0xd0, 0x5e, 0x04, 0x18, 0xa4, 0xec,
300 0xc2, 0xe0, 0x41, 0x6e, 0x0f, 0x51, 0xcb, 0xcc,
301 0x24, 0x91, 0xaf, 0x50, 0xa1, 0xf4, 0x70, 0x39,
302 0x99, 0x7c, 0x3a, 0x85, 0x23, 0xb8, 0xb4, 0x7a,
303 0xfc, 0x02, 0x36, 0x5b, 0x25, 0x55, 0x97, 0x31,
304 0x2d, 0x5d, 0xfa, 0x98, 0xe3, 0x8a, 0x92, 0xae,
305 0x05, 0xdf, 0x29, 0x10, 0x67, 0x6c, 0xba, 0xc9,
306 0xd3, 0x00, 0xe6, 0xcf, 0xe1, 0x9e, 0xa8, 0x2c,
307 0x63, 0x16, 0x01, 0x3f, 0x58, 0xe2, 0x89, 0xa9,
308 0x0d, 0x38, 0x34, 0x1b, 0xab, 0x33, 0xff, 0xb0,
309 0xbb, 0x48, 0x0c, 0x5f, 0xb9, 0xb1, 0xcd, 0x2e,
310 0xc5, 0xf3, 0xdb, 0x47, 0xe5, 0xa5, 0x9c, 0x77,
311 0x0a, 0xa6, 0x20, 0x68, 0xfe, 0x7f, 0xc1, 0xad
316 #endif