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 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
42 public sealed class RC2CryptoServiceProvider : RC2 {
44 private bool _useSalt;
46 public RC2CryptoServiceProvider ()
50 public override int EffectiveKeySize {
51 get { return base.EffectiveKeySize; }
53 if (value != KeySizeValue) {
55 throw new CryptographicUnexpectedOperationException (
57 throw new CryptographicException (
59 Locale.GetText ("Effective key size must match key size for compatibility"));
61 base.EffectiveKeySize = value;
65 public override ICryptoTransform CreateDecryptor (byte[] rgbKey, byte[] rgbIV)
69 return new RC2Transform (this, false);
72 public override ICryptoTransform CreateEncryptor (byte[] rgbKey, byte[] rgbIV)
76 return new RC2Transform (this, true);
79 public override void GenerateIV ()
81 IVValue = KeyBuilder.IV (BlockSizeValue >> 3);
84 public override void GenerateKey ()
86 KeyValue = KeyBuilder.Key (KeySizeValue >> 3);
89 [MonoTODO ("Use salt in algorithm")]
92 get { return _useSalt; }
93 set { _useSalt = value; }
98 internal class RC2Transform : SymmetricTransform {
100 private UInt16 R0, R1, R2, R3; // state
101 private UInt16[] K; // expanded key
102 private int j; // Key indexer
104 public RC2Transform (RC2 rc2Algo, bool encryption) : base (rc2Algo, encryption, rc2Algo.IV)
106 byte[] key = rc2Algo.Key;
107 int t1 = rc2Algo.EffectiveKeySize;
108 // Expand key into a byte array, then convert to word
109 // array since we always access the key in 16bit chunks.
110 byte[] L = new byte [128];
113 int t8 = ((t1 + 7) >> 3); // divide by 8
114 int tm = 255 % (2 << (8 + t1 - (t8 << 3) - 1));
116 for (int i=0; i < t; i++)
118 for (int i=t; i < 128; i++)
119 L [i] = (byte) (pitable [(L [i-1] + L [i-t]) & 0xff]);
121 L [128-t8] = pitable [L [128-t8] & tm];
123 for (int i=127-t8; i >= 0; i--)
124 L [i] = pitable [L [i+1] ^ L [i+t8]];
128 for (int i=0; i < 64; i++)
129 K [i] = (UInt16) (L [pos++] + (L [pos++] << 8));
132 protected override void ECB (byte[] input, byte[] output)
134 // unrolled loop, eliminated mul
135 R0 = (UInt16) (input [0] | (input [1] << 8));
136 R1 = (UInt16) (input [2] | (input [3] << 8));
137 R2 = (UInt16) (input [4] | (input [5] << 8));
138 R3 = (UInt16) (input [6] | (input [7] << 8));
142 // inline, but looped, Mix(); Mix(); Mix(); Mix(); Mix();
144 R0 += (UInt16) (K[j++] + (R3 & R2) + ((~R3) & R1));
145 R0 = (UInt16) ((R0 << 1) | (R0 >> 15));
147 R1 += (UInt16) (K[j++] + (R0 & R3) + ((~R0) & R2));
148 R1 = (UInt16) ((R1 << 2) | (R1 >> 14));
150 R2 += (UInt16) (K[j++] + (R1 & R0) + ((~R1) & R3));
151 R2 = (UInt16) ((R2 << 3) | (R2 >> 13));
153 R3 += (UInt16) (K[j++] + (R2 & R1) + ((~R2) & R0));
154 R3 = (UInt16) ((R3 << 5) | (R3 >> 11));
157 // inline Mash(); j == 20
163 // inline, but looped, Mix(); Mix(); Mix(); Mix(); Mix(); Mix();
165 R0 += (UInt16) (K[j++] + (R3 & R2) + ((~R3) & R1));
166 R0 = (UInt16) ((R0 << 1) | (R0 >> 15));
168 R1 += (UInt16) (K[j++] + (R0 & R3) + ((~R0) & R2));
169 R1 = (UInt16) ((R1 << 2) | (R1 >> 14));
171 R2 += (UInt16) (K[j++] + (R1 & R0) + ((~R1) & R3));
172 R2 = (UInt16) ((R2 << 3) | (R2 >> 13));
174 R3 += (UInt16) (K[j++] + (R2 & R1) + ((~R2) & R0));
175 R3 = (UInt16) ((R3 << 5) | (R3 >> 11));
178 // inline Mash(); j == 44
184 // inline, but looped, Mix(); Mix(); Mix(); Mix(); Mix();
186 R0 += (UInt16) (K[j++] + (R3 & R2) + ((~R3) & R1));
187 R0 = (UInt16) ((R0 << 1) | (R0 >> 15));
189 R1 += (UInt16) (K[j++] + (R0 & R3) + ((~R0) & R2));
190 R1 = (UInt16) ((R1 << 2) | (R1 >> 14));
192 R2 += (UInt16) (K[j++] + (R1 & R0) + ((~R1) & R3));
193 R2 = (UInt16) ((R2 << 3) | (R2 >> 13));
195 R3 += (UInt16) (K[j++] + (R2 & R1) + ((~R2) & R0));
196 R3 = (UInt16) ((R3 << 5) | (R3 >> 11));
201 // inline, but looped, RMix(); RMix(); RMix(); RMix(); RMix();
203 R3 = (UInt16) ((R3 >> 5) | (R3 << 11));
204 R3 -= (UInt16) (K[j--] + (R2 & R1) + ((~R2) & R0));
206 R2 = (UInt16) ((R2 >> 3) | (R2 << 13));
207 R2 -= (UInt16) (K[j--] + (R1 & R0) + ((~R1) & R3));
209 R1 = (UInt16) ((R1 >> 2) | (R1 << 14));
210 R1 -= (UInt16) (K[j--] + (R0 & R3) + ((~R0) & R2));
212 R0 = (UInt16) ((R0 >> 1) | (R0 << 15));
213 R0 -= (UInt16) (K[j--] + (R3 & R2) + ((~R3) & R1));
222 // inline, but looped, RMix(); RMix(); RMix(); RMix(); RMix(); RMix();
224 R3 = (UInt16) ((R3 >> 5) | (R3 << 11));
225 R3 -= (UInt16) (K[j--] + (R2 & R1) + ((~R2) & R0));
227 R2 = (UInt16) ((R2 >> 3) | (R2 << 13));
228 R2 -= (UInt16) (K[j--] + (R1 & R0) + ((~R1) & R3));
230 R1 = (UInt16) ((R1 >> 2) | (R1 << 14));
231 R1 -= (UInt16) (K[j--] + (R0 & R3) + ((~R0) & R2));
233 R0 = (UInt16) ((R0 >> 1) | (R0 << 15));
234 R0 -= (UInt16) (K[j--] + (R3 & R2) + ((~R3) & R1));
243 // inline, but looped, RMix(); RMix(); RMix(); RMix(); RMix();
245 R3 = (UInt16) ((R3 >> 5) | (R3 << 11));
246 R3 -= (UInt16) (K[j--] + (R2 & R1) + ((~R2) & R0));
248 R2 = (UInt16) ((R2 >> 3) | (R2 << 13));
249 R2 -= (UInt16) (K[j--] + (R1 & R0) + ((~R1) & R3));
251 R1 = (UInt16) ((R1 >> 2) | (R1 << 14));
252 R1 -= (UInt16) (K[j--] + (R0 & R3) + ((~R0) & R2));
254 R0 = (UInt16) ((R0 >> 1) | (R0 << 15));
255 R0 -= (UInt16) (K[j--] + (R3 & R2) + ((~R3) & R1));
260 output[0] = (byte) R0;
261 output[1] = (byte) (R0 >> 8);
262 output[2] = (byte) R1;
263 output[3] = (byte) (R1 >> 8);
264 output[4] = (byte) R2;
265 output[5] = (byte) (R2 >> 8);
266 output[6] = (byte) R3;
267 output[7] = (byte) (R3 >> 8);
270 static readonly byte[] pitable = {
271 0xd9, 0x78, 0xf9, 0xc4, 0x19, 0xdd, 0xb5, 0xed,
272 0x28, 0xe9, 0xfd, 0x79, 0x4a, 0xa0, 0xd8, 0x9d,
273 0xc6, 0x7e, 0x37, 0x83, 0x2b, 0x76, 0x53, 0x8e,
274 0x62, 0x4c, 0x64, 0x88, 0x44, 0x8b, 0xfb, 0xa2,
275 0x17, 0x9a, 0x59, 0xf5, 0x87, 0xb3, 0x4f, 0x13,
276 0x61, 0x45, 0x6d, 0x8d, 0x09, 0x81, 0x7d, 0x32,
277 0xbd, 0x8f, 0x40, 0xeb, 0x86, 0xb7, 0x7b, 0x0b,
278 0xf0, 0x95, 0x21, 0x22, 0x5c, 0x6b, 0x4e, 0x82,
279 0x54, 0xd6, 0x65, 0x93, 0xce, 0x60, 0xb2, 0x1c,
280 0x73, 0x56, 0xc0, 0x14, 0xa7, 0x8c, 0xf1, 0xdc,
281 0x12, 0x75, 0xca, 0x1f, 0x3b, 0xbe, 0xe4, 0xd1,
282 0x42, 0x3d, 0xd4, 0x30, 0xa3, 0x3c, 0xb6, 0x26,
283 0x6f, 0xbf, 0x0e, 0xda, 0x46, 0x69, 0x07, 0x57,
284 0x27, 0xf2, 0x1d, 0x9b, 0xbc, 0x94, 0x43, 0x03,
285 0xf8, 0x11, 0xc7, 0xf6, 0x90, 0xef, 0x3e, 0xe7,
286 0x06, 0xc3, 0xd5, 0x2f, 0xc8, 0x66, 0x1e, 0xd7,
287 0x08, 0xe8, 0xea, 0xde, 0x80, 0x52, 0xee, 0xf7,
288 0x84, 0xaa, 0x72, 0xac, 0x35, 0x4d, 0x6a, 0x2a,
289 0x96, 0x1a, 0xd2, 0x71, 0x5a, 0x15, 0x49, 0x74,
290 0x4b, 0x9f, 0xd0, 0x5e, 0x04, 0x18, 0xa4, 0xec,
291 0xc2, 0xe0, 0x41, 0x6e, 0x0f, 0x51, 0xcb, 0xcc,
292 0x24, 0x91, 0xaf, 0x50, 0xa1, 0xf4, 0x70, 0x39,
293 0x99, 0x7c, 0x3a, 0x85, 0x23, 0xb8, 0xb4, 0x7a,
294 0xfc, 0x02, 0x36, 0x5b, 0x25, 0x55, 0x97, 0x31,
295 0x2d, 0x5d, 0xfa, 0x98, 0xe3, 0x8a, 0x92, 0xae,
296 0x05, 0xdf, 0x29, 0x10, 0x67, 0x6c, 0xba, 0xc9,
297 0xd3, 0x00, 0xe6, 0xcf, 0xe1, 0x9e, 0xa8, 0x2c,
298 0x63, 0x16, 0x01, 0x3f, 0x58, 0xe2, 0x89, 0xa9,
299 0x0d, 0x38, 0x34, 0x1b, 0xab, 0x33, 0xff, 0xb0,
300 0xbb, 0x48, 0x0c, 0x5f, 0xb9, 0xb1, 0xcd, 0x2e,
301 0xc5, 0xf3, 0xdb, 0x47, 0xe5, 0xa5, 0x9c, 0x77,
302 0x0a, 0xa6, 0x20, 0x68, 0xfe, 0x7f, 0xc1, 0xad