2 // System.Security.Cryptography.RC2CryptoServiceProvider.cs
5 // Andrew Birkett (andy@nobugs.org)
6 // Sebastien Pouliot (spouliot@motus.com)
8 // Portions (C) 2002 Motus Technologies Inc. (http://www.motus.com)
12 using Mono.Security.Cryptography;
14 namespace System.Security.Cryptography {
17 // a. IETF RFC2286: A Description of the RC2(r) Encryption Algorithm
18 // http://www.ietf.org/rfc/rfc2268.txt
20 public sealed class RC2CryptoServiceProvider : RC2 {
22 public RC2CryptoServiceProvider() {}
24 // included to (exactly) match corlib
25 public override int EffectiveKeySize {
26 get { return base.EffectiveKeySize; }
27 set { base.EffectiveKeySize = value; }
30 public override ICryptoTransform CreateDecryptor(byte[] rgbKey, byte[] rgbIV)
34 return new RC2Transform (this, false);
37 public override ICryptoTransform CreateEncryptor(byte[] rgbKey, byte[] rgbIV)
41 return new RC2Transform (this, true);
44 public override void GenerateIV ()
46 IVValue = KeyBuilder.IV (BlockSizeValue >> 3);
49 public override void GenerateKey ()
51 KeyValue = KeyBuilder.Key (KeySizeValue >> 3);
55 internal class RC2Transform : SymmetricTransform {
57 private UInt16 R0, R1, R2, R3; // state
58 private UInt16[] K; // expanded key
59 private int j; // Key indexer
61 public RC2Transform (RC2 rc2Algo, bool encryption) : base (rc2Algo, encryption, rc2Algo.IV)
63 byte[] key = rc2Algo.Key;
64 int t1 = rc2Algo.EffectiveKeySize;
65 // Expand key into a byte array, then convert to word
66 // array since we always access the key in 16bit chunks.
67 byte[] L = new byte [128];
70 int t8 = ((t1 + 7) >> 3); // divide by 8
71 int tm = 255 % (2 << (8 + t1 - (t8 << 3) - 1));
73 for (int i=0; i < t; i++)
75 for (int i=t; i < 128; i++)
76 L [i] = (byte) (pitable [(L [i-1] + L [i-t]) & 0xff]);
78 L [128-t8] = pitable [L [128-t8] & tm];
80 for (int i=127-t8; i >= 0; i--)
81 L [i] = pitable [L [i+1] ^ L [i+t8]];
85 for (int i=0; i < 64; i++)
86 K [i] = (UInt16) (L [pos++] + (L [pos++] << 8));
89 protected override void ECB (byte[] input, byte[] output)
91 // unrolled loop, eliminated mul
92 R0 = (UInt16) (input [0] | (input [1] << 8));
93 R1 = (UInt16) (input [2] | (input [3] << 8));
94 R2 = (UInt16) (input [4] | (input [5] << 8));
95 R3 = (UInt16) (input [6] | (input [7] << 8));
99 // inline, but looped, Mix(); Mix(); Mix(); Mix(); Mix();
101 R0 += (UInt16) (K[j++] + (R3 & R2) + ((~R3) & R1));
102 R0 = (UInt16) ((R0 << 1) | (R0 >> 15));
104 R1 += (UInt16) (K[j++] + (R0 & R3) + ((~R0) & R2));
105 R1 = (UInt16) ((R1 << 2) | (R1 >> 14));
107 R2 += (UInt16) (K[j++] + (R1 & R0) + ((~R1) & R3));
108 R2 = (UInt16) ((R2 << 3) | (R2 >> 13));
110 R3 += (UInt16) (K[j++] + (R2 & R1) + ((~R2) & R0));
111 R3 = (UInt16) ((R3 << 5) | (R3 >> 11));
114 // inline Mash(); j == 20
120 // inline, but looped, Mix(); Mix(); Mix(); Mix(); Mix(); Mix();
122 R0 += (UInt16) (K[j++] + (R3 & R2) + ((~R3) & R1));
123 R0 = (UInt16) ((R0 << 1) | (R0 >> 15));
125 R1 += (UInt16) (K[j++] + (R0 & R3) + ((~R0) & R2));
126 R1 = (UInt16) ((R1 << 2) | (R1 >> 14));
128 R2 += (UInt16) (K[j++] + (R1 & R0) + ((~R1) & R3));
129 R2 = (UInt16) ((R2 << 3) | (R2 >> 13));
131 R3 += (UInt16) (K[j++] + (R2 & R1) + ((~R2) & R0));
132 R3 = (UInt16) ((R3 << 5) | (R3 >> 11));
135 // inline Mash(); j == 44
141 // inline, but looped, Mix(); Mix(); Mix(); Mix(); Mix();
143 R0 += (UInt16) (K[j++] + (R3 & R2) + ((~R3) & R1));
144 R0 = (UInt16) ((R0 << 1) | (R0 >> 15));
146 R1 += (UInt16) (K[j++] + (R0 & R3) + ((~R0) & R2));
147 R1 = (UInt16) ((R1 << 2) | (R1 >> 14));
149 R2 += (UInt16) (K[j++] + (R1 & R0) + ((~R1) & R3));
150 R2 = (UInt16) ((R2 << 3) | (R2 >> 13));
152 R3 += (UInt16) (K[j++] + (R2 & R1) + ((~R2) & R0));
153 R3 = (UInt16) ((R3 << 5) | (R3 >> 11));
158 // inline, but looped, RMix(); RMix(); RMix(); RMix(); RMix();
160 R3 = (UInt16) ((R3 >> 5) | (R3 << 11));
161 R3 -= (UInt16) (K[j--] + (R2 & R1) + ((~R2) & R0));
163 R2 = (UInt16) ((R2 >> 3) | (R2 << 13));
164 R2 -= (UInt16) (K[j--] + (R1 & R0) + ((~R1) & R3));
166 R1 = (UInt16) ((R1 >> 2) | (R1 << 14));
167 R1 -= (UInt16) (K[j--] + (R0 & R3) + ((~R0) & R2));
169 R0 = (UInt16) ((R0 >> 1) | (R0 << 15));
170 R0 -= (UInt16) (K[j--] + (R3 & R2) + ((~R3) & R1));
179 // inline, but looped, RMix(); RMix(); RMix(); RMix(); RMix(); RMix();
181 R3 = (UInt16) ((R3 >> 5) | (R3 << 11));
182 R3 -= (UInt16) (K[j--] + (R2 & R1) + ((~R2) & R0));
184 R2 = (UInt16) ((R2 >> 3) | (R2 << 13));
185 R2 -= (UInt16) (K[j--] + (R1 & R0) + ((~R1) & R3));
187 R1 = (UInt16) ((R1 >> 2) | (R1 << 14));
188 R1 -= (UInt16) (K[j--] + (R0 & R3) + ((~R0) & R2));
190 R0 = (UInt16) ((R0 >> 1) | (R0 << 15));
191 R0 -= (UInt16) (K[j--] + (R3 & R2) + ((~R3) & R1));
200 // inline, but looped, RMix(); RMix(); RMix(); RMix(); RMix();
202 R3 = (UInt16) ((R3 >> 5) | (R3 << 11));
203 R3 -= (UInt16) (K[j--] + (R2 & R1) + ((~R2) & R0));
205 R2 = (UInt16) ((R2 >> 3) | (R2 << 13));
206 R2 -= (UInt16) (K[j--] + (R1 & R0) + ((~R1) & R3));
208 R1 = (UInt16) ((R1 >> 2) | (R1 << 14));
209 R1 -= (UInt16) (K[j--] + (R0 & R3) + ((~R0) & R2));
211 R0 = (UInt16) ((R0 >> 1) | (R0 << 15));
212 R0 -= (UInt16) (K[j--] + (R3 & R2) + ((~R3) & R1));
217 output[0] = (byte) R0;
218 output[1] = (byte) (R0 >> 8);
219 output[2] = (byte) R1;
220 output[3] = (byte) (R1 >> 8);
221 output[4] = (byte) R2;
222 output[5] = (byte) (R2 >> 8);
223 output[6] = (byte) R3;
224 output[7] = (byte) (R3 >> 8);
227 static private byte[] pitable = {
228 0xd9, 0x78, 0xf9, 0xc4, 0x19, 0xdd, 0xb5, 0xed,
229 0x28, 0xe9, 0xfd, 0x79, 0x4a, 0xa0, 0xd8, 0x9d,
230 0xc6, 0x7e, 0x37, 0x83, 0x2b, 0x76, 0x53, 0x8e,
231 0x62, 0x4c, 0x64, 0x88, 0x44, 0x8b, 0xfb, 0xa2,
232 0x17, 0x9a, 0x59, 0xf5, 0x87, 0xb3, 0x4f, 0x13,
233 0x61, 0x45, 0x6d, 0x8d, 0x09, 0x81, 0x7d, 0x32,
234 0xbd, 0x8f, 0x40, 0xeb, 0x86, 0xb7, 0x7b, 0x0b,
235 0xf0, 0x95, 0x21, 0x22, 0x5c, 0x6b, 0x4e, 0x82,
236 0x54, 0xd6, 0x65, 0x93, 0xce, 0x60, 0xb2, 0x1c,
237 0x73, 0x56, 0xc0, 0x14, 0xa7, 0x8c, 0xf1, 0xdc,
238 0x12, 0x75, 0xca, 0x1f, 0x3b, 0xbe, 0xe4, 0xd1,
239 0x42, 0x3d, 0xd4, 0x30, 0xa3, 0x3c, 0xb6, 0x26,
240 0x6f, 0xbf, 0x0e, 0xda, 0x46, 0x69, 0x07, 0x57,
241 0x27, 0xf2, 0x1d, 0x9b, 0xbc, 0x94, 0x43, 0x03,
242 0xf8, 0x11, 0xc7, 0xf6, 0x90, 0xef, 0x3e, 0xe7,
243 0x06, 0xc3, 0xd5, 0x2f, 0xc8, 0x66, 0x1e, 0xd7,
244 0x08, 0xe8, 0xea, 0xde, 0x80, 0x52, 0xee, 0xf7,
245 0x84, 0xaa, 0x72, 0xac, 0x35, 0x4d, 0x6a, 0x2a,
246 0x96, 0x1a, 0xd2, 0x71, 0x5a, 0x15, 0x49, 0x74,
247 0x4b, 0x9f, 0xd0, 0x5e, 0x04, 0x18, 0xa4, 0xec,
248 0xc2, 0xe0, 0x41, 0x6e, 0x0f, 0x51, 0xcb, 0xcc,
249 0x24, 0x91, 0xaf, 0x50, 0xa1, 0xf4, 0x70, 0x39,
250 0x99, 0x7c, 0x3a, 0x85, 0x23, 0xb8, 0xb4, 0x7a,
251 0xfc, 0x02, 0x36, 0x5b, 0x25, 0x55, 0x97, 0x31,
252 0x2d, 0x5d, 0xfa, 0x98, 0xe3, 0x8a, 0x92, 0xae,
253 0x05, 0xdf, 0x29, 0x10, 0x67, 0x6c, 0xba, 0xc9,
254 0xd3, 0x00, 0xe6, 0xcf, 0xe1, 0x9e, 0xa8, 0x2c,
255 0x63, 0x16, 0x01, 0x3f, 0x58, 0xe2, 0x89, 0xa9,
256 0x0d, 0x38, 0x34, 0x1b, 0xab, 0x33, 0xff, 0xb0,
257 0xbb, 0x48, 0x0c, 0x5f, 0xb9, 0xb1, 0xcd, 0x2e,
258 0xc5, 0xf3, 0xdb, 0x47, 0xe5, 0xa5, 0x9c, 0x77,
259 0x0a, 0xa6, 0x20, 0x68, 0xfe, 0x7f, 0xc1, 0xad