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 #if !NET_2_1 || MONOTOUCH
33 using System
.Globalization
;
34 using System
.Runtime
.InteropServices
;
36 using Mono
.Security
.Cryptography
;
38 namespace System
.Security
.Cryptography
{
41 // a. IETF RFC2286: A Description of the RC2(r) Encryption Algorithm
42 // http://www.ietf.org/rfc/rfc2268.txt
47 public sealed class RC2CryptoServiceProvider
: RC2
{
50 private bool _useSalt
;
53 public RC2CryptoServiceProvider ()
57 public override int EffectiveKeySize
{
58 get { return base.EffectiveKeySize; }
60 if (value != KeySizeValue
) {
62 throw new CryptographicUnexpectedOperationException (
64 throw new CryptographicException (
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);
92 [MonoTODO ("Use salt in algorithm")]
95 get { return _useSalt; }
96 set { _useSalt = value; }
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
)
112 throw new ArgumentNullException ("key");
114 int t1
= rc2Algo
.EffectiveKeySize
;
116 key
= KeyBuilder
.Key (rc2Algo
.KeySize
>> 3);
118 key
= (byte[]) key
.Clone ();
119 t1
= Math
.Min (t1
, key
.Length
<< 3);
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.",
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
++)
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
]];
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));
162 // inline, but looped, Mix(); Mix(); Mix(); Mix(); Mix();
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
183 // inline, but looped, Mix(); Mix(); Mix(); Mix(); Mix(); Mix();
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
204 // inline, but looped, Mix(); Mix(); Mix(); Mix(); Mix();
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));
221 // inline, but looped, RMix(); RMix(); RMix(); RMix(); RMix();
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
));
242 // inline, but looped, RMix(); RMix(); RMix(); RMix(); RMix(); RMix();
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
));
263 // inline, but looped, RMix(); RMix(); RMix(); RMix(); RMix();
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
));
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