2010-03-24 Jérémie Laval <jeremie.laval@gmail.com>
[mono.git] / mcs / class / corlib / System.Security.Cryptography / MACTripleDES.cs
index 5a051af481cc592c9dbf75eac80a10029947c2d5..89089707fdf385ee3e807cde56ef0c4ff9e574b3 100644 (file)
 // MACTripleDES.cs: Handles MAC with TripleDES
 //
 // Author:
-//     Sebastien Pouliot (spouliot@motus.com)
+//     Sebastien Pouliot (sebastien@ximian.com)
 //
-// (C) 2002 Motus Technologies Inc. (http://www.motus.com)
+// (C) 2002, 2003 Motus Technologies Inc. (http://www.motus.com)
+// Copyright (C) 2004-2005 Novell, Inc (http://www.novell.com)
+//
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+// 
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+// 
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 //
 
-using System;
-using System.IO;
-using System.Security.Cryptography;
-
-namespace System.Security.Cryptography {
-
-// References:
-// a.  FIPS PUB 81: DES MODES OF OPERATION 
-//     MAC: Appendix F (MACDES not MACTripleDES but close enough ;-)
-//     http://www.itl.nist.gov/fipspubs/fip81.htm
-
-// Generic MAC mechanims - most of the work is done in here
-// It should work with any symmetric algorithm function e.g. DES for MACDES (fips81)
-internal class MACAlgorithm {
-       protected SymmetricAlgorithm algo;
-       private ICryptoTransform enc;
-       private CryptoStream stream;
-       private MemoryStream ms;
-       private int BlockSize;  // in bytes (not in bits)
-
-       public MACAlgorithm (string algoName, CipherMode algoMode) 
-       {
-               if ((algoMode != CipherMode.CBC) && (algoMode != CipherMode.CFB))
-                       throw new CryptographicException();
-
-               algo = (SymmetricAlgorithm) CryptoConfig.CreateFromName (algoName);
-               algo.Mode = algoMode;
-               algo.Padding = PaddingMode.Zeros;
-               BlockSize = (algo.BlockSize >> 3);
-       }
-
-       ~MACAlgorithm () 
-       {
-               Dispose ();
-       }
+#if !MOONLIGHT
 
-       public void Dispose () 
-       {
-               ZeroizeKey ();
-               // algo.Clear (); not yet present in SymmetricAlgorithm
-       }
+using System.Runtime.InteropServices;
 
-       public SymmetricAlgorithm Algo {
-               get { return algo; }
-       }
+using Mono.Security.Cryptography;
 
-       public byte[] Key {
-               get { return algo.Key; }
-               set { algo.Key = value; }
-       }
-
-       public byte[] IV {
-               get { return algo.IV; }
-               set { algo.IV = value; }
-       }
+namespace System.Security.Cryptography {
 
-       [MonoTODO()]
-       public void Initialize () 
-       {
-               if (algo.Mode == CipherMode.CBC)
-                       algo.IV = new Byte [BlockSize];
-               enc = algo.CreateEncryptor();
-               // TODO Change MemoryStream (unrealistic for big continuous streams)
-               ms = new MemoryStream ();
-               stream = new CryptoStream (ms, enc, CryptoStreamMode.Write);
-       }
+       // References:
+       // a.   FIPS PUB 81: DES MODES OF OPERATION 
+       //      MAC: Appendix F (MACDES not MACTripleDES but close enough ;-)
+       //      http://www.itl.nist.gov/fipspubs/fip81.htm
        
-       [MonoTODO("")]
-       public void Core (byte[] rgb, int ib, int cb) 
-       {
-               if (enc == null)
-                       Initialize ();
-
-               stream.Write (rgb, ib, cb);
-       }
-
-       [MonoTODO("How should it finish? encrypting the last block?")]
-       public byte[] Final () 
-       {
-               stream.FlushFinalBlock ();
-               byte[] mac = new byte [BlockSize];
-               ms.Position -= BlockSize;
-               ms.Read (mac, 0, BlockSize);
-               return mac;
-       }
-
-       public void ZeroizeKey () 
-       {
-               // well maybe the algo did it - but better twice than none
-               if (algo.Key != null)
-                       Array.Clear (algo.Key, 0, algo.Key.Length);
+       // LAMESPEC: MACTripleDES == MAC-CBC using TripleDES (not MAC-CFB).
+       [ComVisible (true)]
+       public class MACTripleDES: KeyedHashAlgorithm {
+       
+               private TripleDES tdes;
+               private MACAlgorithm mac;
+               private bool m_disposed;
+       
+               public MACTripleDES ()
+               {
+                       Setup ("TripleDES", null);
+               }
+       
+               public MACTripleDES (byte[] rgbKey)
+               {
+                       if (rgbKey == null)
+                               throw new ArgumentNullException ("rgbKey");
+                       Setup ("TripleDES", rgbKey);
+               }
+       
+               public MACTripleDES (string strTripleDES, byte[] rgbKey) 
+               {
+                       if (rgbKey == null)
+                               throw new ArgumentNullException ("rgbKey");
+                       if (strTripleDES == null)
+                               Setup ("TripleDES", rgbKey);
+                       else
+                               Setup (strTripleDES, rgbKey);
+               }
+       
+               private void Setup (string strTripleDES, byte[] rgbKey) 
+               {
+                       tdes = TripleDES.Create (strTripleDES);
+                       // default padding (as using in Fx 1.0 and 1.1)
+                       tdes.Padding = PaddingMode.Zeros;
+                       // if rgbKey is null we keep the randomly generated key
+                       if (rgbKey != null) {
+                               // this way we get the TripleDES key validation (like weak
+                               // and semi-weak keys)
+                               tdes.Key = rgbKey;
+                       }
+                       HashSizeValue = tdes.BlockSize;
+                       // we use Key property to get the additional validations 
+                       // (from KeyedHashAlgorithm ancestor)
+                       Key = tdes.Key;
+                       mac = new MACAlgorithm (tdes);
+                       m_disposed = false;
+               }
+       
+               ~MACTripleDES () 
+               {
+                       Dispose (false);
+               }
+
+               [ComVisible (false)]
+               public PaddingMode Padding {
+                       get { return tdes.Padding; }
+                       set { tdes.Padding = value; }
+               }
+
+               protected override void Dispose (bool disposing) 
+               {
+                       if (!m_disposed) {
+                               // note: we ALWAYS zeroize keys (disposing or not)
+       
+                               // clear our copy of the secret key
+                               if (KeyValue != null)
+                                       Array.Clear (KeyValue, 0, KeyValue.Length);
+                               // clear the secret key (inside TripleDES)
+                               if (tdes != null)
+                                       tdes.Clear ();
+       
+                               if (disposing) {
+                                       // disposed managed stuff
+                                       KeyValue = null;
+                                       tdes = null;
+                               }
+                               // ancestor
+                               base.Dispose (disposing);
+                               m_disposed = true;
+                       }
+               }
+       
+               public override void Initialize () 
+               {
+                       if (m_disposed)
+                               throw new ObjectDisposedException ("MACTripleDES");
+                       State = 0;
+                       mac.Initialize (KeyValue);
+               }
+       
+               protected override void HashCore (byte[] rgbData, int ibStart, int cbSize) 
+               {
+                       if (m_disposed)
+                               throw new ObjectDisposedException ("MACTripleDES");
+                       if (State == 0) {
+                               Initialize ();
+                               State = 1;
+                       }
+                       mac.Core (rgbData, ibStart, cbSize);
+               }
+       
+               protected override byte[] HashFinal () 
+               {
+                       if (m_disposed)
+                               throw new ObjectDisposedException ("MACTripleDES");
+                       State = 0;
+                       return mac.Final ();
+               }
        }
 }
 
-// LAMESPEC: MACTripleDES == MAC-CBC using TripleDES (not MAC-CFB).
-// LAMESPEC: Unlike FIPS81 or FIPS113 the result is encrypted twice (ANSI like?)
-public class MACTripleDES: KeyedHashAlgorithm {
-       private MACAlgorithm mac;
-
-       public MACTripleDES () 
-       {
-               mac = new MACAlgorithm ("TripleDES", CipherMode.CBC);
-               HashSizeValue = mac.Algo.BlockSize;
-       }
-
-       public MACTripleDES (byte[] rgbKey)
-       {
-               MACAlgorithm mac = new MACAlgorithm ("TripleDES", CipherMode.CBC);
-               HashSizeValue = mac.Algo.BlockSize;
-               mac.Key = rgbKey;
-       }
-
-       public MACTripleDES (string strTripleDES, byte[] rgbKey)
-       {
-               MACAlgorithm mac = new MACAlgorithm (strTripleDES, CipherMode.CBC);
-               HashSizeValue = mac.Algo.BlockSize;
-               mac.Key = rgbKey;
-       }
-
-       ~MACTripleDES () 
-       {
-               Dispose (false);
-       }
-
-       protected override void Dispose (bool disposing) 
-       {
-               if (mac != null)
-                       mac.Dispose();
-               base.Dispose (disposing);
-       }
-
-       public override void Initialize () 
-       {
-               State = 0;
-               mac.Initialize ();
-       }
-
-       protected override void HashCore (byte[] rgb, int ib, int cb) 
-       {
-               State = 1;
-               mac.Core (rgb, ib, cb);
-       }
-
-       protected override byte[] HashFinal () 
-       {
-               State = 0;
-               return mac.Final ();
-       }
-}
+#endif
 
-}
\ No newline at end of file