bring Mono Security to monotouch
[mcs.git] / class / corlib / System.Security.Cryptography / RC2CryptoServiceProvider.cs
blobc4d5843dd515570e103cf27d0f9136c36649a18b
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 !NET_2_1 || MONOTOUCH
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 #if NET_2_0
45 [ComVisible (true)]
46 #endif
47 public sealed class RC2CryptoServiceProvider : RC2 {
49 #if NET_2_0
50 private bool _useSalt;
51 #endif
53 public RC2CryptoServiceProvider ()
57 public override int EffectiveKeySize {
58 get { return base.EffectiveKeySize; }
59 set {
60 if (value != KeySizeValue) {
61 #if NET_1_1
62 throw new CryptographicUnexpectedOperationException (
63 #else
64 throw new CryptographicException (
65 #endif
66 Locale.GetText ("Effective key size must match key size for compatibility"));
68 base.EffectiveKeySize = value;
72 public override ICryptoTransform CreateDecryptor (byte[] rgbKey, byte[] rgbIV)
74 return new RC2Transform (this, false, rgbKey, rgbIV);
77 public override ICryptoTransform CreateEncryptor (byte[] rgbKey, byte[] rgbIV)
79 return new RC2Transform (this, true, rgbKey, rgbIV);
82 public override void GenerateIV ()
84 IVValue = KeyBuilder.IV (BlockSizeValue >> 3);
87 public override void GenerateKey ()
89 KeyValue = KeyBuilder.Key (KeySizeValue >> 3);
91 #if NET_2_0
92 [MonoTODO ("Use salt in algorithm")]
93 [ComVisible (false)]
94 public bool UseSalt {
95 get { return _useSalt; }
96 set { _useSalt = value; }
98 #endif
101 internal class RC2Transform : SymmetricTransform {
103 private UInt16 R0, R1, R2, R3; // state
104 private UInt16[] K; // expanded key
105 private int j; // Key indexer
107 public RC2Transform (RC2 rc2Algo, bool encryption, byte[] key, byte[] iv)
108 : base (rc2Algo, encryption, iv)
110 #if ONLY_1_1
111 if (key == null)
112 throw new ArgumentNullException ("key");
113 #endif
114 int t1 = rc2Algo.EffectiveKeySize;
115 if (key == null) {
116 key = KeyBuilder.Key (rc2Algo.KeySize >> 3);
117 } else {
118 key = (byte[]) key.Clone ();
119 t1 = Math.Min (t1, key.Length << 3);
122 int t = key.Length;
123 if (!KeySizes.IsLegalKeySize (rc2Algo.LegalKeySizes, (t << 3))) {
124 string msg = Locale.GetText ("Key is too small ({0} bytes), it should be between {1} and {2} bytes long.",
125 t, 5, 16);
126 throw new CryptographicException (msg);
129 // Expand key into a byte array, then convert to word
130 // array since we always access the key in 16bit chunks.
131 byte[] L = new byte [128];
133 int t8 = ((t1 + 7) >> 3); // divide by 8
134 int tm = 255 % (2 << (8 + t1 - (t8 << 3) - 1));
136 for (int i=0; i < t; i++)
137 L [i] = key [i];
138 for (int i=t; i < 128; i++)
139 L [i] = (byte) (pitable [(L [i-1] + L [i-t]) & 0xff]);
141 L [128-t8] = pitable [L [128-t8] & tm];
143 for (int i=127-t8; i >= 0; i--)
144 L [i] = pitable [L [i+1] ^ L [i+t8]];
146 K = new UInt16 [64];
147 int pos = 0;
148 for (int i=0; i < 64; i++)
149 K [i] = (UInt16) (L [pos++] + (L [pos++] << 8));
152 protected override void ECB (byte[] input, byte[] output)
154 // unrolled loop, eliminated mul
155 R0 = (UInt16) (input [0] | (input [1] << 8));
156 R1 = (UInt16) (input [2] | (input [3] << 8));
157 R2 = (UInt16) (input [4] | (input [5] << 8));
158 R3 = (UInt16) (input [6] | (input [7] << 8));
160 if (encrypt) {
161 j = 0;
162 // inline, but looped, Mix(); Mix(); Mix(); Mix(); Mix();
163 while (j <= 16) {
164 R0 += (UInt16) (K[j++] + (R3 & R2) + ((~R3) & R1));
165 R0 = (UInt16) ((R0 << 1) | (R0 >> 15));
167 R1 += (UInt16) (K[j++] + (R0 & R3) + ((~R0) & R2));
168 R1 = (UInt16) ((R1 << 2) | (R1 >> 14));
170 R2 += (UInt16) (K[j++] + (R1 & R0) + ((~R1) & R3));
171 R2 = (UInt16) ((R2 << 3) | (R2 >> 13));
173 R3 += (UInt16) (K[j++] + (R2 & R1) + ((~R2) & R0));
174 R3 = (UInt16) ((R3 << 5) | (R3 >> 11));
177 // inline Mash(); j == 20
178 R0 += K [R3 & 63];
179 R1 += K [R0 & 63];
180 R2 += K [R1 & 63];
181 R3 += K [R2 & 63];
183 // inline, but looped, Mix(); Mix(); Mix(); Mix(); Mix(); Mix();
184 while (j <= 40) {
185 R0 += (UInt16) (K[j++] + (R3 & R2) + ((~R3) & R1));
186 R0 = (UInt16) ((R0 << 1) | (R0 >> 15));
188 R1 += (UInt16) (K[j++] + (R0 & R3) + ((~R0) & R2));
189 R1 = (UInt16) ((R1 << 2) | (R1 >> 14));
191 R2 += (UInt16) (K[j++] + (R1 & R0) + ((~R1) & R3));
192 R2 = (UInt16) ((R2 << 3) | (R2 >> 13));
194 R3 += (UInt16) (K[j++] + (R2 & R1) + ((~R2) & R0));
195 R3 = (UInt16) ((R3 << 5) | (R3 >> 11));
198 // inline Mash(); j == 44
199 R0 += K [R3 & 63];
200 R1 += K [R0 & 63];
201 R2 += K [R1 & 63];
202 R3 += K [R2 & 63];
204 // inline, but looped, Mix(); Mix(); Mix(); Mix(); Mix();
205 while (j < 64) {
206 R0 += (UInt16) (K[j++] + (R3 & R2) + ((~R3) & R1));
207 R0 = (UInt16) ((R0 << 1) | (R0 >> 15));
209 R1 += (UInt16) (K[j++] + (R0 & R3) + ((~R0) & R2));
210 R1 = (UInt16) ((R1 << 2) | (R1 >> 14));
212 R2 += (UInt16) (K[j++] + (R1 & R0) + ((~R1) & R3));
213 R2 = (UInt16) ((R2 << 3) | (R2 >> 13));
215 R3 += (UInt16) (K[j++] + (R2 & R1) + ((~R2) & R0));
216 R3 = (UInt16) ((R3 << 5) | (R3 >> 11));
219 else {
220 j = 63;
221 // inline, but looped, RMix(); RMix(); RMix(); RMix(); RMix();
222 while (j >= 44) {
223 R3 = (UInt16) ((R3 >> 5) | (R3 << 11));
224 R3 -= (UInt16) (K[j--] + (R2 & R1) + ((~R2) & R0));
226 R2 = (UInt16) ((R2 >> 3) | (R2 << 13));
227 R2 -= (UInt16) (K[j--] + (R1 & R0) + ((~R1) & R3));
229 R1 = (UInt16) ((R1 >> 2) | (R1 << 14));
230 R1 -= (UInt16) (K[j--] + (R0 & R3) + ((~R0) & R2));
232 R0 = (UInt16) ((R0 >> 1) | (R0 << 15));
233 R0 -= (UInt16) (K[j--] + (R3 & R2) + ((~R3) & R1));
236 // inline RMash();
237 R3 -= K [R2 & 63];
238 R2 -= K [R1 & 63];
239 R1 -= K [R0 & 63];
240 R0 -= K [R3 & 63];
242 // inline, but looped, RMix(); RMix(); RMix(); RMix(); RMix(); RMix();
243 while (j >= 20) {
244 R3 = (UInt16) ((R3 >> 5) | (R3 << 11));
245 R3 -= (UInt16) (K[j--] + (R2 & R1) + ((~R2) & R0));
247 R2 = (UInt16) ((R2 >> 3) | (R2 << 13));
248 R2 -= (UInt16) (K[j--] + (R1 & R0) + ((~R1) & R3));
250 R1 = (UInt16) ((R1 >> 2) | (R1 << 14));
251 R1 -= (UInt16) (K[j--] + (R0 & R3) + ((~R0) & R2));
253 R0 = (UInt16) ((R0 >> 1) | (R0 << 15));
254 R0 -= (UInt16) (K[j--] + (R3 & R2) + ((~R3) & R1));
257 // inline RMash();
258 R3 -= K [R2 & 63];
259 R2 -= K [R1 & 63];
260 R1 -= K [R0 & 63];
261 R0 -= K [R3 & 63];
263 // inline, but looped, RMix(); RMix(); RMix(); RMix(); RMix();
264 while (j >= 0) {
265 R3 = (UInt16) ((R3 >> 5) | (R3 << 11));
266 R3 -= (UInt16) (K[j--] + (R2 & R1) + ((~R2) & R0));
268 R2 = (UInt16) ((R2 >> 3) | (R2 << 13));
269 R2 -= (UInt16) (K[j--] + (R1 & R0) + ((~R1) & R3));
271 R1 = (UInt16) ((R1 >> 2) | (R1 << 14));
272 R1 -= (UInt16) (K[j--] + (R0 & R3) + ((~R0) & R2));
274 R0 = (UInt16) ((R0 >> 1) | (R0 << 15));
275 R0 -= (UInt16) (K[j--] + (R3 & R2) + ((~R3) & R1));
279 // unrolled loop
280 output[0] = (byte) R0;
281 output[1] = (byte) (R0 >> 8);
282 output[2] = (byte) R1;
283 output[3] = (byte) (R1 >> 8);
284 output[4] = (byte) R2;
285 output[5] = (byte) (R2 >> 8);
286 output[6] = (byte) R3;
287 output[7] = (byte) (R3 >> 8);
290 static readonly byte[] pitable = {
291 0xd9, 0x78, 0xf9, 0xc4, 0x19, 0xdd, 0xb5, 0xed,
292 0x28, 0xe9, 0xfd, 0x79, 0x4a, 0xa0, 0xd8, 0x9d,
293 0xc6, 0x7e, 0x37, 0x83, 0x2b, 0x76, 0x53, 0x8e,
294 0x62, 0x4c, 0x64, 0x88, 0x44, 0x8b, 0xfb, 0xa2,
295 0x17, 0x9a, 0x59, 0xf5, 0x87, 0xb3, 0x4f, 0x13,
296 0x61, 0x45, 0x6d, 0x8d, 0x09, 0x81, 0x7d, 0x32,
297 0xbd, 0x8f, 0x40, 0xeb, 0x86, 0xb7, 0x7b, 0x0b,
298 0xf0, 0x95, 0x21, 0x22, 0x5c, 0x6b, 0x4e, 0x82,
299 0x54, 0xd6, 0x65, 0x93, 0xce, 0x60, 0xb2, 0x1c,
300 0x73, 0x56, 0xc0, 0x14, 0xa7, 0x8c, 0xf1, 0xdc,
301 0x12, 0x75, 0xca, 0x1f, 0x3b, 0xbe, 0xe4, 0xd1,
302 0x42, 0x3d, 0xd4, 0x30, 0xa3, 0x3c, 0xb6, 0x26,
303 0x6f, 0xbf, 0x0e, 0xda, 0x46, 0x69, 0x07, 0x57,
304 0x27, 0xf2, 0x1d, 0x9b, 0xbc, 0x94, 0x43, 0x03,
305 0xf8, 0x11, 0xc7, 0xf6, 0x90, 0xef, 0x3e, 0xe7,
306 0x06, 0xc3, 0xd5, 0x2f, 0xc8, 0x66, 0x1e, 0xd7,
307 0x08, 0xe8, 0xea, 0xde, 0x80, 0x52, 0xee, 0xf7,
308 0x84, 0xaa, 0x72, 0xac, 0x35, 0x4d, 0x6a, 0x2a,
309 0x96, 0x1a, 0xd2, 0x71, 0x5a, 0x15, 0x49, 0x74,
310 0x4b, 0x9f, 0xd0, 0x5e, 0x04, 0x18, 0xa4, 0xec,
311 0xc2, 0xe0, 0x41, 0x6e, 0x0f, 0x51, 0xcb, 0xcc,
312 0x24, 0x91, 0xaf, 0x50, 0xa1, 0xf4, 0x70, 0x39,
313 0x99, 0x7c, 0x3a, 0x85, 0x23, 0xb8, 0xb4, 0x7a,
314 0xfc, 0x02, 0x36, 0x5b, 0x25, 0x55, 0x97, 0x31,
315 0x2d, 0x5d, 0xfa, 0x98, 0xe3, 0x8a, 0x92, 0xae,
316 0x05, 0xdf, 0x29, 0x10, 0x67, 0x6c, 0xba, 0xc9,
317 0xd3, 0x00, 0xe6, 0xcf, 0xe1, 0x9e, 0xa8, 0x2c,
318 0x63, 0x16, 0x01, 0x3f, 0x58, 0xe2, 0x89, 0xa9,
319 0x0d, 0x38, 0x34, 0x1b, 0xab, 0x33, 0xff, 0xb0,
320 0xbb, 0x48, 0x0c, 0x5f, 0xb9, 0xb1, 0xcd, 0x2e,
321 0xc5, 0xf3, 0xdb, 0x47, 0xe5, 0xa5, 0x9c, 0x77,
322 0x0a, 0xa6, 0x20, 0x68, 0xfe, 0x7f, 0xc1, 0xad
327 #endif