2 // System.Security.Cryptography.RC2CryptoServiceProvider.cs
5 // Andrew Birkett (andy@nobugs.org)
6 // Sebastien Pouliot (sebastien@ximian.com)
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:
19 // The above copyright notice and this permission notice shall be
20 // included in all copies or substantial portions of the Software.
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 using System.Globalization;
32 using System.Runtime.InteropServices;
34 using Mono.Security.Cryptography;
36 namespace System.Security.Cryptography {
39 // a. IETF RFC2286: A Description of the RC2(r) Encryption Algorithm
40 // http://www.ietf.org/rfc/rfc2268.txt
45 public sealed class RC2CryptoServiceProvider : RC2 {
48 private bool _useSalt;
51 public RC2CryptoServiceProvider ()
55 public override int EffectiveKeySize {
56 get { return base.EffectiveKeySize; }
58 if (value != KeySizeValue) {
60 throw new CryptographicUnexpectedOperationException (
62 throw new CryptographicException (
64 Locale.GetText ("Effective key size must match key size for compatibility"));
66 base.EffectiveKeySize = value;
70 public override ICryptoTransform CreateDecryptor (byte[] rgbKey, byte[] rgbIV)
72 return new RC2Transform (this, false, rgbKey, rgbIV);
75 public override ICryptoTransform CreateEncryptor (byte[] rgbKey, byte[] rgbIV)
77 return new RC2Transform (this, true, rgbKey, rgbIV);
80 public override void GenerateIV ()
82 IVValue = KeyBuilder.IV (BlockSizeValue >> 3);
85 public override void GenerateKey ()
87 KeyValue = KeyBuilder.Key (KeySizeValue >> 3);
90 [MonoTODO ("Use salt in algorithm")]
93 get { return _useSalt; }
94 set { _useSalt = value; }
99 internal class RC2Transform : SymmetricTransform {
101 private UInt16 R0, R1, R2, R3; // state
102 private UInt16[] K; // expanded key
103 private int j; // Key indexer
105 public RC2Transform (RC2 rc2Algo, bool encryption, byte[] key, byte[] iv)
106 : base (rc2Algo, encryption, iv)
110 throw new ArgumentNullException ("key");
112 int t1 = rc2Algo.EffectiveKeySize;
114 key = KeyBuilder.Key (rc2Algo.KeySize >> 3);
116 key = (byte[]) key.Clone ();
117 t1 = Math.Min (t1, key.Length << 3);
121 if (!KeySizes.IsLegalKeySize (rc2Algo.LegalKeySizes, (t << 3))) {
122 string msg = Locale.GetText ("Key is too small ({0} bytes), it should be between {1} and {2} bytes long.",
124 throw new CryptographicException (msg);
127 // Expand key into a byte array, then convert to word
128 // array since we always access the key in 16bit chunks.
129 byte[] L = new byte [128];
131 int t8 = ((t1 + 7) >> 3); // divide by 8
132 int tm = 255 % (2 << (8 + t1 - (t8 << 3) - 1));
134 for (int i=0; i < t; i++)
136 for (int i=t; i < 128; i++)
137 L [i] = (byte) (pitable [(L [i-1] + L [i-t]) & 0xff]);
139 L [128-t8] = pitable [L [128-t8] & tm];
141 for (int i=127-t8; i >= 0; i--)
142 L [i] = pitable [L [i+1] ^ L [i+t8]];
146 for (int i=0; i < 64; i++)
147 K [i] = (UInt16) (L [pos++] + (L [pos++] << 8));
150 protected override void ECB (byte[] input, byte[] output)
152 // unrolled loop, eliminated mul
153 R0 = (UInt16) (input [0] | (input [1] << 8));
154 R1 = (UInt16) (input [2] | (input [3] << 8));
155 R2 = (UInt16) (input [4] | (input [5] << 8));
156 R3 = (UInt16) (input [6] | (input [7] << 8));
160 // inline, but looped, Mix(); Mix(); Mix(); Mix(); Mix();
162 R0 += (UInt16) (K[j++] + (R3 & R2) + ((~R3) & R1));
163 R0 = (UInt16) ((R0 << 1) | (R0 >> 15));
165 R1 += (UInt16) (K[j++] + (R0 & R3) + ((~R0) & R2));
166 R1 = (UInt16) ((R1 << 2) | (R1 >> 14));
168 R2 += (UInt16) (K[j++] + (R1 & R0) + ((~R1) & R3));
169 R2 = (UInt16) ((R2 << 3) | (R2 >> 13));
171 R3 += (UInt16) (K[j++] + (R2 & R1) + ((~R2) & R0));
172 R3 = (UInt16) ((R3 << 5) | (R3 >> 11));
175 // inline Mash(); j == 20
181 // inline, but looped, Mix(); Mix(); Mix(); Mix(); Mix(); Mix();
183 R0 += (UInt16) (K[j++] + (R3 & R2) + ((~R3) & R1));
184 R0 = (UInt16) ((R0 << 1) | (R0 >> 15));
186 R1 += (UInt16) (K[j++] + (R0 & R3) + ((~R0) & R2));
187 R1 = (UInt16) ((R1 << 2) | (R1 >> 14));
189 R2 += (UInt16) (K[j++] + (R1 & R0) + ((~R1) & R3));
190 R2 = (UInt16) ((R2 << 3) | (R2 >> 13));
192 R3 += (UInt16) (K[j++] + (R2 & R1) + ((~R2) & R0));
193 R3 = (UInt16) ((R3 << 5) | (R3 >> 11));
196 // inline Mash(); j == 44
202 // inline, but looped, Mix(); Mix(); Mix(); Mix(); Mix();
204 R0 += (UInt16) (K[j++] + (R3 & R2) + ((~R3) & R1));
205 R0 = (UInt16) ((R0 << 1) | (R0 >> 15));
207 R1 += (UInt16) (K[j++] + (R0 & R3) + ((~R0) & R2));
208 R1 = (UInt16) ((R1 << 2) | (R1 >> 14));
210 R2 += (UInt16) (K[j++] + (R1 & R0) + ((~R1) & R3));
211 R2 = (UInt16) ((R2 << 3) | (R2 >> 13));
213 R3 += (UInt16) (K[j++] + (R2 & R1) + ((~R2) & R0));
214 R3 = (UInt16) ((R3 << 5) | (R3 >> 11));
219 // inline, but looped, RMix(); RMix(); RMix(); RMix(); RMix();
221 R3 = (UInt16) ((R3 >> 5) | (R3 << 11));
222 R3 -= (UInt16) (K[j--] + (R2 & R1) + ((~R2) & R0));
224 R2 = (UInt16) ((R2 >> 3) | (R2 << 13));
225 R2 -= (UInt16) (K[j--] + (R1 & R0) + ((~R1) & R3));
227 R1 = (UInt16) ((R1 >> 2) | (R1 << 14));
228 R1 -= (UInt16) (K[j--] + (R0 & R3) + ((~R0) & R2));
230 R0 = (UInt16) ((R0 >> 1) | (R0 << 15));
231 R0 -= (UInt16) (K[j--] + (R3 & R2) + ((~R3) & R1));
240 // inline, but looped, RMix(); RMix(); RMix(); RMix(); RMix(); RMix();
242 R3 = (UInt16) ((R3 >> 5) | (R3 << 11));
243 R3 -= (UInt16) (K[j--] + (R2 & R1) + ((~R2) & R0));
245 R2 = (UInt16) ((R2 >> 3) | (R2 << 13));
246 R2 -= (UInt16) (K[j--] + (R1 & R0) + ((~R1) & R3));
248 R1 = (UInt16) ((R1 >> 2) | (R1 << 14));
249 R1 -= (UInt16) (K[j--] + (R0 & R3) + ((~R0) & R2));
251 R0 = (UInt16) ((R0 >> 1) | (R0 << 15));
252 R0 -= (UInt16) (K[j--] + (R3 & R2) + ((~R3) & R1));
261 // inline, but looped, RMix(); RMix(); RMix(); RMix(); RMix();
263 R3 = (UInt16) ((R3 >> 5) | (R3 << 11));
264 R3 -= (UInt16) (K[j--] + (R2 & R1) + ((~R2) & R0));
266 R2 = (UInt16) ((R2 >> 3) | (R2 << 13));
267 R2 -= (UInt16) (K[j--] + (R1 & R0) + ((~R1) & R3));
269 R1 = (UInt16) ((R1 >> 2) | (R1 << 14));
270 R1 -= (UInt16) (K[j--] + (R0 & R3) + ((~R0) & R2));
272 R0 = (UInt16) ((R0 >> 1) | (R0 << 15));
273 R0 -= (UInt16) (K[j--] + (R3 & R2) + ((~R3) & R1));
278 output[0] = (byte) R0;
279 output[1] = (byte) (R0 >> 8);
280 output[2] = (byte) R1;
281 output[3] = (byte) (R1 >> 8);
282 output[4] = (byte) R2;
283 output[5] = (byte) (R2 >> 8);
284 output[6] = (byte) R3;
285 output[7] = (byte) (R3 >> 8);
288 static readonly byte[] pitable = {
289 0xd9, 0x78, 0xf9, 0xc4, 0x19, 0xdd, 0xb5, 0xed,
290 0x28, 0xe9, 0xfd, 0x79, 0x4a, 0xa0, 0xd8, 0x9d,
291 0xc6, 0x7e, 0x37, 0x83, 0x2b, 0x76, 0x53, 0x8e,
292 0x62, 0x4c, 0x64, 0x88, 0x44, 0x8b, 0xfb, 0xa2,
293 0x17, 0x9a, 0x59, 0xf5, 0x87, 0xb3, 0x4f, 0x13,
294 0x61, 0x45, 0x6d, 0x8d, 0x09, 0x81, 0x7d, 0x32,
295 0xbd, 0x8f, 0x40, 0xeb, 0x86, 0xb7, 0x7b, 0x0b,
296 0xf0, 0x95, 0x21, 0x22, 0x5c, 0x6b, 0x4e, 0x82,
297 0x54, 0xd6, 0x65, 0x93, 0xce, 0x60, 0xb2, 0x1c,
298 0x73, 0x56, 0xc0, 0x14, 0xa7, 0x8c, 0xf1, 0xdc,
299 0x12, 0x75, 0xca, 0x1f, 0x3b, 0xbe, 0xe4, 0xd1,
300 0x42, 0x3d, 0xd4, 0x30, 0xa3, 0x3c, 0xb6, 0x26,
301 0x6f, 0xbf, 0x0e, 0xda, 0x46, 0x69, 0x07, 0x57,
302 0x27, 0xf2, 0x1d, 0x9b, 0xbc, 0x94, 0x43, 0x03,
303 0xf8, 0x11, 0xc7, 0xf6, 0x90, 0xef, 0x3e, 0xe7,
304 0x06, 0xc3, 0xd5, 0x2f, 0xc8, 0x66, 0x1e, 0xd7,
305 0x08, 0xe8, 0xea, 0xde, 0x80, 0x52, 0xee, 0xf7,
306 0x84, 0xaa, 0x72, 0xac, 0x35, 0x4d, 0x6a, 0x2a,
307 0x96, 0x1a, 0xd2, 0x71, 0x5a, 0x15, 0x49, 0x74,
308 0x4b, 0x9f, 0xd0, 0x5e, 0x04, 0x18, 0xa4, 0xec,
309 0xc2, 0xe0, 0x41, 0x6e, 0x0f, 0x51, 0xcb, 0xcc,
310 0x24, 0x91, 0xaf, 0x50, 0xa1, 0xf4, 0x70, 0x39,
311 0x99, 0x7c, 0x3a, 0x85, 0x23, 0xb8, 0xb4, 0x7a,
312 0xfc, 0x02, 0x36, 0x5b, 0x25, 0x55, 0x97, 0x31,
313 0x2d, 0x5d, 0xfa, 0x98, 0xe3, 0x8a, 0x92, 0xae,
314 0x05, 0xdf, 0x29, 0x10, 0x67, 0x6c, 0xba, 0xc9,
315 0xd3, 0x00, 0xe6, 0xcf, 0xe1, 0x9e, 0xa8, 0x2c,
316 0x63, 0x16, 0x01, 0x3f, 0x58, 0xe2, 0x89, 0xa9,
317 0x0d, 0x38, 0x34, 0x1b, 0xab, 0x33, 0xff, 0xb0,
318 0xbb, 0x48, 0x0c, 0x5f, 0xb9, 0xb1, 0xcd, 0x2e,
319 0xc5, 0xf3, 0xdb, 0x47, 0xe5, 0xa5, 0x9c, 0x77,
320 0x0a, 0xa6, 0x20, 0x68, 0xfe, 0x7f, 0xc1, 0xad