[bcl] Add CommonCrypto to corlib, Mono.Security and System.Core.
authorRolf Bjarne Kvinge <rolf@xamarin.com>
Tue, 15 Mar 2016 11:01:48 +0000 (12:01 +0100)
committerRodrigo Kumpera <kumpera@gmail.com>
Mon, 28 Mar 2016 22:51:33 +0000 (15:51 -0700)
List of original contributors:

Sebastien Pouliot <sebastien@xamarin.com>
Rolf Bjarne Kvinge <rolf@xamarin.com>
Marek Safar <marek.safar@gmail.com>
Miguel de Icaza <miguel@gnome.org>

31 files changed:
mcs/class/Mono.Security/monotouch_Mono.Security.dll.sources
mcs/class/Mono.Security/monotouch_opt_Mono.Security.dll.sources [deleted file]
mcs/class/Mono.Security/xammac_Mono.Security.dll.sources
mcs/class/Mono.Security/xammac_opt_Mono.Security.dll.sources [deleted file]
mcs/class/System.Core/monotouch_System.Core.dll.sources
mcs/class/System.Core/xammac_System.Core.dll.sources
mcs/class/corlib/CommonCrypto/.gitignore [new file with mode: 0644]
mcs/class/corlib/CommonCrypto/CommonCrypto.cs [new file with mode: 0644]
mcs/class/corlib/CommonCrypto/CommonCryptorGenerator.cs [new file with mode: 0644]
mcs/class/corlib/CommonCrypto/CommonDigestGenerator.cs [new file with mode: 0644]
mcs/class/corlib/CommonCrypto/CorlibExtras.cs [new file with mode: 0644]
mcs/class/corlib/CommonCrypto/CryptorTransform.cs [new file with mode: 0644]
mcs/class/corlib/CommonCrypto/FastCryptorTransform.cs [new file with mode: 0644]
mcs/class/corlib/CommonCrypto/Makefile.include [new file with mode: 0644]
mcs/class/corlib/CommonCrypto/RC4CommonCrypto.cs [new file with mode: 0644]
mcs/class/corlib/CommonCrypto/RijndaelManaged.cs [new file with mode: 0644]
mcs/class/corlib/CommonCrypto/SecRandom.cs [new file with mode: 0644]
mcs/class/corlib/CommonCrypto/generator.cs [new file with mode: 0644]
mcs/class/corlib/Makefile
mcs/class/corlib/monotouch_corlib.dll.exclude.sources [new file with mode: 0644]
mcs/class/corlib/monotouch_corlib.dll.sources
mcs/class/corlib/monotouch_runtime_corlib.dll.exclude.sources [new file with mode: 0644]
mcs/class/corlib/monotouch_runtime_corlib.dll.sources
mcs/class/corlib/monotouch_tv_corlib.dll.exclude.sources [new file with mode: 0644]
mcs/class/corlib/monotouch_tv_corlib.dll.sources
mcs/class/corlib/monotouch_tv_runtime_corlib.dll.exclude.sources [new file with mode: 0644]
mcs/class/corlib/monotouch_watch_corlib.dll.exclude.sources [new file with mode: 0644]
mcs/class/corlib/monotouch_watch_corlib.dll.sources
mcs/class/corlib/monotouch_watch_runtime_corlib.dll.exclude.sources [new file with mode: 0644]
mcs/class/corlib/xammac_corlib.dll.exclude.sources [new file with mode: 0644]
mcs/class/corlib/xammac_corlib.dll.sources

index 513dc61bd4fdea8fdd3c87a8df120f01c13ccd9d..17f56e3c4054885b5f5cf4477cef4bed1ff63c44 100644 (file)
@@ -1 +1,6 @@
 #include mobile_Mono.Security.dll.sources
+../corlib/CommonCrypto/CommonCrypto.cs
+../corlib/CommonCrypto/RC4CommonCrypto.cs
+../corlib/CommonCrypto/MD2Managed.g.cs
+../corlib/CommonCrypto/MD4Managed.g.cs
+../corlib/CommonCrypto/SHA224Managed.g.cs
diff --git a/mcs/class/Mono.Security/monotouch_opt_Mono.Security.dll.sources b/mcs/class/Mono.Security/monotouch_opt_Mono.Security.dll.sources
deleted file mode 100644 (file)
index e8464be..0000000
+++ /dev/null
@@ -1,4 +0,0 @@
-./Mono.Security.Cryptography/ARC4Managed.cs
-./Mono.Security.Cryptography/MD2Managed.cs
-./Mono.Security.Cryptography/MD4Managed.cs
-./Mono.Security.Cryptography/SHA224Managed.cs
index 1379fa79d8038df905a3a62f2e9bf124b648466d..6c1b4dbef6fda25d7d76612c984ad0776f33ee7f 100644 (file)
@@ -1,2 +1,7 @@
 #include monotouch_Mono.Security.dll.sources
+../corlib/CommonCrypto/CommonCrypto.cs
+../corlib/CommonCrypto/RC4CommonCrypto.cs
+../corlib/CommonCrypto/MD2Managed.g.cs
+../corlib/CommonCrypto/MD4Managed.g.cs
+../corlib/CommonCrypto/SHA224Managed.g.cs
 
diff --git a/mcs/class/Mono.Security/xammac_opt_Mono.Security.dll.sources b/mcs/class/Mono.Security/xammac_opt_Mono.Security.dll.sources
deleted file mode 100644 (file)
index e8464be..0000000
+++ /dev/null
@@ -1,4 +0,0 @@
-./Mono.Security.Cryptography/ARC4Managed.cs
-./Mono.Security.Cryptography/MD2Managed.cs
-./Mono.Security.Cryptography/MD4Managed.cs
-./Mono.Security.Cryptography/SHA224Managed.cs
index 7d32d44a88bd84c6036228fd2caebd01a9efbf7b..6b6d96c25a26397c17d3d29deeb327f14a235814 100644 (file)
@@ -1,2 +1,4 @@
 #include common_System.Core.dll.sources
 #include interpreter_System.Core.dll.sources
+../corlib/CommonCrypto/AesManaged.g.cs
+../corlib/CommonCrypto/AesCryptoServiceProvider.g.cs
index 882476b4b5e7308adf7bb8013f2c75a43f6c2d46..6ab44f0f8c2cb558e83d94f40731fe88409b4703 100644 (file)
@@ -1,4 +1,5 @@
 #include common_System.Core.dll.sources
 
 #include dynamic_System.Core.dll.sources
-
+../corlib/CommonCrypto/AesManaged.g.cs
+../corlib/CommonCrypto/AesCryptoServiceProvider.g.cs
diff --git a/mcs/class/corlib/CommonCrypto/.gitignore b/mcs/class/corlib/CommonCrypto/.gitignore
new file mode 100644 (file)
index 0000000..1252b93
--- /dev/null
@@ -0,0 +1,2 @@
+*.g.cs
+generator.exe
diff --git a/mcs/class/corlib/CommonCrypto/CommonCrypto.cs b/mcs/class/corlib/CommonCrypto/CommonCrypto.cs
new file mode 100644 (file)
index 0000000..c765b95
--- /dev/null
@@ -0,0 +1,130 @@
+// CommonCrypto bindings for MonoMac and MonoTouch
+//
+// Authors:
+//     Sebastien Pouliot  <sebastien@xamarin.com>
+//
+// Copyright 2012-2014 Xamarin Inc.
+
+using System;
+using System.Security.Cryptography;
+using System.Runtime.InteropServices;
+
+namespace Crimson.CommonCrypto {
+
+       // int32_t -> CommonCryptor.h
+       enum CCCryptorStatus {
+           Success                     = 0,
+       ParamError              = -4300,
+           BufferTooSmall      = -4301,
+       MemoryFailure   = -4302,
+       AlignmentError  = -4303,
+       DecodeError             = -4304,
+       Unimplemented   = -4305
+       }
+       
+       // uint32_t -> CommonCryptor.h
+       // note: not exposed publicly so it can stay signed
+       enum CCOperation {
+               Encrypt = 0, 
+               Decrypt,     
+       }
+
+       // uint32_t -> CommonCryptor.h
+       // note: not exposed publicly so it can stay signed
+       enum CCAlgorithm {
+               AES128 = 0,
+               DES,        
+               TripleDES,       
+               CAST,       
+               RC4,
+               RC2,   
+               Blowfish    
+       }
+       
+       // uint32_t -> CommonCryptor.h
+       // note: not exposed publicly so it can stay signed
+       [Flags]
+       enum CCOptions {
+               None                    = 0,
+               PKCS7Padding    = 1,
+               ECBMode                 = 2
+       }
+       
+       static class Cryptor {
+               
+               const string libSystem = "/usr/lib/libSystem.dylib";
+               
+               // size_t was changed to IntPtr for 32/64 bits size difference - even if mono is (moslty) used in 32bits only on OSX today
+               // not using `nint` to be able to resue this outside (if needed)
+               
+               [DllImport (libSystem)]
+               extern internal static CCCryptorStatus CCCryptorCreate (CCOperation op, CCAlgorithm alg, CCOptions options, /* const void* */ byte[] key, /* size_t */ IntPtr keyLength, /* const void* */ byte[] iv, /* CCCryptorRef* */ ref IntPtr cryptorRef);
+
+               [DllImport (libSystem)]
+               extern internal static CCCryptorStatus CCCryptorRelease (/* CCCryptorRef */ IntPtr cryptorRef);
+
+               [DllImport (libSystem)]
+               extern internal static CCCryptorStatus CCCryptorUpdate (/* CCCryptorRef */ IntPtr cryptorRef, /* const void* */ byte[] dataIn, /* size_t */ IntPtr dataInLength, /* void* */ byte[] dataOut, /* size_t */ IntPtr dataOutAvailable, /* size_t* */ ref IntPtr dataOutMoved);
+
+               [DllImport (libSystem)]
+               extern internal static CCCryptorStatus CCCryptorUpdate (/* CCCryptorRef */ IntPtr cryptorRef, /* const void* */ IntPtr dataIn, /* size_t */ IntPtr dataInLength, /* void* */ IntPtr dataOut, /* size_t */ IntPtr dataOutAvailable, /* size_t* */ ref IntPtr dataOutMoved);
+
+               [DllImport (libSystem)]
+               extern internal static CCCryptorStatus CCCryptorFinal (/* CCCryptorRef */ IntPtr cryptorRef, /* void* */ byte[] dataOut, /* size_t */ IntPtr dataOutAvailable, /* size_t* */ ref IntPtr dataOutMoved);
+
+               [DllImport (libSystem)]
+               extern internal static int CCCryptorGetOutputLength (/* CCCryptorRef */ IntPtr cryptorRef, /* size_t */ IntPtr inputLength, bool final);
+
+               [DllImport (libSystem)]
+               extern internal static CCCryptorStatus CCCryptorReset (/* CCCryptorRef */ IntPtr cryptorRef, /* const void* */ IntPtr iv);
+               
+               // helper method to reduce the amount of generate code for each cipher algorithm
+               static internal IntPtr Create (CCOperation operation, CCAlgorithm algorithm, CCOptions options, byte[] key, byte[] iv)
+               {
+                       if (key == null)
+                               throw new CryptographicException ("A null key was provided");
+                       
+                       // unlike the .NET framework CommonCrypto does not support two-keys triple-des (128 bits) ref: #6967
+                       if ((algorithm == CCAlgorithm.TripleDES) && (key.Length == 16)) {
+                               byte[] key3 = new byte [24];
+                               Buffer.BlockCopy (key, 0, key3, 0, 16);
+                               Buffer.BlockCopy (key, 0, key3, 16, 8);
+                               key = key3;
+                       }
+                       
+                       IntPtr cryptor = IntPtr.Zero;
+                       CCCryptorStatus status = Cryptor.CCCryptorCreate (operation, algorithm, options, key, (IntPtr) key.Length, iv, ref cryptor);
+                       if (status != CCCryptorStatus.Success)
+                               throw new CryptographicUnexpectedOperationException ();
+                       return cryptor;
+               }
+
+               // size_t was changed to IntPtr for 32/64 bits size difference - even if mono is (moslty) used in 32bits only on OSX today
+               [DllImport ("/System/Library/Frameworks/Security.framework/Security")]
+               extern internal static /* int */ int SecRandomCopyBytes (/* SecRandomRef */ IntPtr rnd, /* size_t */ IntPtr count, /* uint8_t* */ byte[] bytes);
+               
+               static internal void GetRandom (byte[] buffer)
+               {
+                       if (SecRandomCopyBytes (IntPtr.Zero, (IntPtr) buffer.Length, buffer) != 0)
+                               throw new CryptographicException (Marshal.GetLastWin32Error ()); // errno
+               }
+       }
+       
+#if !MONOTOUCH && !XAMMAC
+       static class KeyBuilder {
+               static public byte[] Key (int size) 
+               {
+                       byte[] buffer = new byte [size];
+                       Cryptor.GetRandom (buffer);
+                       return buffer;
+               }
+       
+               static public byte[] IV (int size) 
+               {
+                       byte[] buffer = new byte [size];
+                       Cryptor.GetRandom (buffer);
+                       return buffer;
+               }
+       }
+#endif
+}
diff --git a/mcs/class/corlib/CommonCrypto/CommonCryptorGenerator.cs b/mcs/class/corlib/CommonCrypto/CommonCryptorGenerator.cs
new file mode 100644 (file)
index 0000000..f177c17
--- /dev/null
@@ -0,0 +1,104 @@
+//
+// CommonCrypto code generator for symmetric block cipher algorithms
+//
+// Authors:
+//     Sebastien Pouliot  <sebastien@xamarin.com>
+//
+// Copyright 2012 Xamarin Inc.
+//
+
+using System;
+using System.IO;
+
+namespace Xamarin {
+
+       public static class CommonCryptor {
+               
+               static public void Generate (string namespaceName, string typeName, string baseTypeName, string ccAlgorithmName, string feedbackSize = "8", string ctorInitializers = null)
+               {
+                       string template = @"// Generated file to bind CommonCrypto cipher algorithms - DO NOT EDIT
+//
+// Authors:
+//     Sebastien Pouliot  <sebastien@xamarin.com>
+//
+// Copyright 2012-2014 Xamarin Inc.
+
+using System;
+using System.Security.Cryptography;
+
+using Mono.Security.Cryptography;
+using Crimson.CommonCrypto;
+
+namespace %NAMESPACE% {
+
+       public sealed partial class %TYPE% : %BASE% {
+               
+               public %TYPE% ()
+               {
+                       FeedbackSizeValue = %FEEDBACKSIZE%;
+                       %CTOR_INIT%
+               }
+               
+               public override void GenerateIV ()
+               {
+                       IVValue = KeyBuilder.IV (BlockSizeValue >> 3);
+               }
+               
+               public override void GenerateKey ()
+               {
+                       KeyValue = KeyBuilder.Key (KeySizeValue >> 3);
+               }
+               
+               public override ICryptoTransform CreateDecryptor (byte[] rgbKey, byte[] rgbIV) 
+               {
+                       IntPtr decryptor = IntPtr.Zero;
+                       switch (Mode) {
+                       case CipherMode.CBC:
+                               decryptor = Cryptor.Create (CCOperation.Decrypt, CCAlgorithm.%CCALGORITHM%, CCOptions.None, rgbKey, rgbIV);
+                               return new FastCryptorTransform (decryptor, this, false, rgbIV);
+                       case CipherMode.ECB:
+                               decryptor = Cryptor.Create (CCOperation.Decrypt, CCAlgorithm.%CCALGORITHM%, CCOptions.ECBMode, rgbKey, rgbIV);
+                               return new FastCryptorTransform (decryptor, this, false, rgbIV);
+                       case CipherMode.CFB:
+#if MONOTOUCH || XAMMAC
+                               IntPtr encryptor = Cryptor.Create (CCOperation.Encrypt, CCAlgorithm.%CCALGORITHM%, CCOptions.ECBMode, rgbKey, rgbIV);
+                               decryptor = Cryptor.Create (CCOperation.Decrypt, CCAlgorithm.%CCALGORITHM%, CCOptions.ECBMode, rgbKey, rgbIV);
+                               return new CryptorTransform (decryptor, encryptor, this, false, rgbIV);
+#else
+                               throw new CryptographicException (""CFB is not supported by Crimson.CommonCrypto"");
+#endif
+                       default:
+                               throw new CryptographicException (String.Format (""{0} is not supported by the .NET framework"", Mode));
+                       }
+               }
+               
+               public override ICryptoTransform CreateEncryptor (byte[] rgbKey, byte[] rgbIV) 
+               {
+                       IntPtr encryptor = IntPtr.Zero;
+                       switch (Mode) {
+                       case CipherMode.CBC:
+                               encryptor = Cryptor.Create (CCOperation.Encrypt, CCAlgorithm.%CCALGORITHM%, CCOptions.None, rgbKey, rgbIV);
+                               return new FastCryptorTransform (encryptor, this, true, rgbIV);
+                       case CipherMode.ECB:
+                               encryptor = Cryptor.Create (CCOperation.Encrypt, CCAlgorithm.%CCALGORITHM%, CCOptions.ECBMode, rgbKey, rgbIV);
+                               return new FastCryptorTransform (encryptor, this, true, rgbIV);
+                       case CipherMode.CFB:
+#if MONOTOUCH || XAMMAC
+                               encryptor = Cryptor.Create (CCOperation.Encrypt, CCAlgorithm.%CCALGORITHM%, CCOptions.ECBMode, rgbKey, rgbIV);
+                               return new CryptorTransform (encryptor, IntPtr.Zero, this, true, rgbIV);
+#else
+                               throw new CryptographicException (""CFB is not supported by Crimson.CommonCrypto"");
+#endif
+                       default:
+                               throw new CryptographicException (String.Format (""{0} is not supported by the .NET framework"", Mode));
+                       }
+               }
+       }
+}";
+                       
+                       File.WriteAllText (typeName + ".g.cs", template.Replace ("%NAMESPACE%", namespaceName).
+                               Replace ("%TYPE%", typeName).Replace ("%BASE%", baseTypeName).Replace("%FEEDBACKSIZE%", feedbackSize).Replace ("%CTOR_INIT%", ctorInitializers).
+                               Replace ("%CCALGORITHM%", ccAlgorithmName.ToString ()));
+               }
+       }
+}
diff --git a/mcs/class/corlib/CommonCrypto/CommonDigestGenerator.cs b/mcs/class/corlib/CommonCrypto/CommonDigestGenerator.cs
new file mode 100644 (file)
index 0000000..1b729e3
--- /dev/null
@@ -0,0 +1,167 @@
+//
+// CommonCrypto code generator for digest algorithms
+//
+// Authors:
+//     Sebastien Pouliot  <sebastien@xamarin.com>
+//
+// Copyright 2012-2014 Xamarin Inc.
+//
+
+using System;
+using System.IO;
+
+namespace Xamarin {
+
+       public static class CommonDigest {
+               
+#if !MONOTOUCH && !XAMMAC
+               // we do not add anything in MonoTouch, just replacing, so this is not needed
+               // however we can avoid a dependency on Mono.Security for Crimson.CommonCrypto.dll by including the base classes
+               static public void GenerateBaseClass (string namespaceName, string typeName, string baseTypeName, int hashSize,
+                       string visibilityStart = "", string visibilityEnd = "")
+               {
+                       string template = @"// Generated file to bind CommonCrypto/CommonDigest - DO NOT EDIT
+//
+// Authors:
+//     Sebastien Pouliot  <sebastien@xamarin.com>
+//
+// Copyright 2012-2014 Xamarin Inc.
+
+using System;
+using System.Security.Cryptography;
+using System.Runtime.InteropServices;
+
+namespace %NAMESPACE% {
+
+%VISIBILITY_START%
+       public
+%VISIBILITY_END%
+       abstract class %BASE% : HashAlgorithm {
+
+               protected %BASE% () 
+               {
+                       HashSizeValue = %HASHSIZE%; 
+               }
+
+               public static new %BASE% Create ()
+               {
+                       return Create (""%BASE%"");
+               }
+
+               public static new %BASE% Create (string hashName)
+               {
+                       object o = CryptoConfig.CreateFromName (hashName);
+                       return (%BASE%) o ?? new %TYPE% ();
+               }
+       }
+}";
+                       
+                       File.WriteAllText (baseTypeName + ".g.cs", template.Replace ("%NAMESPACE%", namespaceName).
+                               Replace ("%TYPE%", typeName).Replace ("%BASE%", baseTypeName).
+                               Replace ("%VISIBILITY_START%", visibilityStart).Replace ("%VISIBILITY_END%", visibilityEnd).
+                               Replace ("%HASHSIZE%", hashSize.ToString ()));
+               }
+#endif
+               static public void Generate (string namespaceName, string typeName, string baseTypeName, int contextSize,
+                       string visibilityStart = "", string visibilityEnd = "")
+               {
+                       string template = @"// Generated file to bind CommonCrypto/CommonDigest - DO NOT EDIT
+//
+// Authors:
+//     Sebastien Pouliot  <sebastien@xamarin.com>
+//
+// Copyright 2011-2014 Xamarin Inc.
+
+using System;
+using System.Security.Cryptography;
+using System.Runtime.InteropServices;
+
+using Mono.Security.Cryptography;
+
+namespace %NAMESPACE% {
+
+%VISIBILITY_START%
+       public
+%VISIBILITY_END%
+       sealed class %TYPE% : %BASE% {
+
+               IntPtr ctx;
+
+               [DllImport (""/usr/lib/libSystem.dylib"", EntryPoint=""CC_%BASE%_Init"")]
+               static extern int Init (/* CC_%BASE%_CTX */ IntPtr c);
+
+               [DllImport (""/usr/lib/libSystem.dylib"", EntryPoint=""CC_%BASE%_Update"")]
+               static extern int Update (/* CC_%BASE%_CTX */ IntPtr c, /* const void * */ IntPtr data, /* uint32_t */ uint len);
+
+               [DllImport (""/usr/lib/libSystem.dylib"", EntryPoint=""CC_%BASE%_Final"")]
+               static extern int Final (/* unsigned char * */ byte [] md, /* CC_%BASE%_CTX */ IntPtr c);
+
+               public %TYPE% ()
+               {
+                       ctx = IntPtr.Zero;
+               }
+
+               ~%TYPE% ()
+               {
+                       Dispose (false);
+               }
+
+               protected override void Dispose (bool disposing)
+               {
+                       if (ctx != IntPtr.Zero) {
+                               Marshal.FreeHGlobal (ctx);
+                               ctx = IntPtr.Zero;
+                       }
+                       base.Dispose (disposing);
+                       GC.SuppressFinalize (this);
+               }
+
+               public override void Initialize ()
+               {
+                       if (ctx == IntPtr.Zero)
+                               ctx = Marshal.AllocHGlobal (%CTX_SIZE%);
+                       
+                       int hr = Init (ctx);
+                       if (hr != 1)
+                               throw new CryptographicException (hr);
+               }
+
+               protected override void HashCore (byte[] data, int start, int length) 
+               {
+                       if (ctx == IntPtr.Zero)
+                               Initialize ();
+
+                       if (data.Length == 0)
+                               return;
+
+                       unsafe {
+                               fixed (byte* p = &data [0]) {
+                                       int hr = Update (ctx, (IntPtr) (p + start), (uint) length);
+                                       if (hr != 1)
+                                               throw new CryptographicException (hr);
+                               }
+                       }
+               }
+
+               protected override byte[] HashFinal () 
+               {
+                       if (ctx == IntPtr.Zero)
+                               Initialize ();
+                       
+                       byte[] data = new byte [HashSize >> 3];
+                       int hr = Final (data, ctx);
+                       if (hr != 1)
+                               throw new CryptographicException (hr);
+
+                       return data;
+               }
+       }
+}";
+                       
+                       File.WriteAllText (typeName + ".g.cs", template.Replace ("%NAMESPACE%", namespaceName).
+                               Replace ("%TYPE%", typeName).Replace ("%BASE%", baseTypeName).
+                               Replace ("%VISIBILITY_START%", visibilityStart).Replace ("%VISIBILITY_END%", visibilityEnd).
+                               Replace ("%CTX_SIZE%", contextSize.ToString ()));
+               }
+       }
+}
diff --git a/mcs/class/corlib/CommonCrypto/CorlibExtras.cs b/mcs/class/corlib/CommonCrypto/CorlibExtras.cs
new file mode 100644 (file)
index 0000000..5bdc69a
--- /dev/null
@@ -0,0 +1,24 @@
+//
+// CorlibExtras.cs: additional stuff not provided by autogenerated code
+//
+// Authors:
+//     Sebastien Pouliot (sebastien@xamarun.com)
+//
+// Copyright (C) 2012 Xamarin Inc. All rights reserved.
+//
+
+namespace System.Security.Cryptography {
+       
+       // required to ensure compatibility with MS implementation
+       public sealed partial class RC2CryptoServiceProvider : RC2 {
+               
+               public override int EffectiveKeySize {
+                       get { return base.EffectiveKeySize; }
+                       set {
+                               if (value != KeySizeValue)
+                                       throw new CryptographicUnexpectedOperationException ("Effective key size must match key size for compatibility");
+                               base.EffectiveKeySize = value; 
+                       }
+               }
+       }
+}
diff --git a/mcs/class/corlib/CommonCrypto/CryptorTransform.cs b/mcs/class/corlib/CommonCrypto/CryptorTransform.cs
new file mode 100644 (file)
index 0000000..10ca6fa
--- /dev/null
@@ -0,0 +1,60 @@
+// ICryptoTransform implementation on top of CommonCrypto and SymmetricTransform
+//
+// Authors:
+//     Sebastien Pouliot  <sebastien@xamarin.com>
+//
+// Copyright 2012 Xamarin Inc.
+
+using System;
+using System.Security.Cryptography;
+
+using Mono.Security.Cryptography;
+
+namespace Crimson.CommonCrypto {
+
+       class CryptorTransform : SymmetricTransform {
+               
+               IntPtr handle;
+               IntPtr handle_e;
+               bool encryption;
+               
+               public CryptorTransform (IntPtr cryptor, IntPtr special, SymmetricAlgorithm algo, bool encryption, byte[] iv)
+                       : base (algo, encryption, iv)
+               {
+                       handle = cryptor;
+                       // for CFB we need to encrypt data while decrypting
+                       handle_e = special;
+                       this.encryption = encryption;
+               }
+               
+               ~CryptorTransform ()
+               {
+                       Dispose (false);
+               }
+               
+               // PRO: doing this ensure all cipher modes and padding modes supported by .NET will be available with CommonCrypto (drop-in replacements)
+               // CON: doing this will only process one block at the time, so it's not ideal for performance, but still a lot better than managed
+               protected override void ECB (byte[] input, byte[] output)
+               {
+                       IntPtr len = IntPtr.Zero;
+                       CCCryptorStatus s = Cryptor.CCCryptorUpdate ((encrypt == encryption) ? handle : handle_e, 
+                               input, (IntPtr) input.Length, output, (IntPtr) output.Length, ref len);
+                       if (((int) len != output.Length) || (s != CCCryptorStatus.Success))
+                               throw new CryptographicUnexpectedOperationException (s.ToString ());
+               }
+               
+               protected override void Dispose (bool disposing)
+               {
+                       if (handle != IntPtr.Zero) {
+                               Cryptor.CCCryptorRelease (handle);
+                               handle = IntPtr.Zero;
+                       }
+                       if (handle_e != IntPtr.Zero) {
+                               Cryptor.CCCryptorRelease (handle_e);
+                               handle_e = IntPtr.Zero;
+                       }
+                       base.Dispose (disposing);
+                       GC.SuppressFinalize (this);
+               }
+       }
+}
\ No newline at end of file
diff --git a/mcs/class/corlib/CommonCrypto/FastCryptorTransform.cs b/mcs/class/corlib/CommonCrypto/FastCryptorTransform.cs
new file mode 100644 (file)
index 0000000..9ff7a5a
--- /dev/null
@@ -0,0 +1,348 @@
+// Fast, multi-block, ICryptoTransform implementation on top of CommonCrypto
+//
+// Authors:
+//     Sebastien Pouliot  <sebastien@xamarin.com>
+//
+// Copyright 2012 Xamarin Inc.
+
+using System;
+using System.Security.Cryptography;
+
+using Mono.Security.Cryptography;
+
+namespace Crimson.CommonCrypto {
+
+       unsafe class FastCryptorTransform : ICryptoTransform {
+               
+               IntPtr handle;
+               bool encrypt;
+               int BlockSizeByte;
+               byte[] workBuff;
+               bool lastBlock;
+               PaddingMode padding;
+               
+               public FastCryptorTransform (IntPtr cryptor, SymmetricAlgorithm algo, bool encryption, byte[] iv)
+               {
+                       BlockSizeByte = (algo.BlockSize >> 3);
+                       
+                       if (iv == null) {
+                               iv = KeyBuilder.IV (BlockSizeByte);
+                       } else if (iv.Length < BlockSizeByte) {
+                               string msg = String.Format ("IV is too small ({0} bytes), it should be {1} bytes long.",
+                                       iv.Length, BlockSizeByte);
+                               throw new CryptographicException (msg);
+                       }
+                       
+                       handle = cryptor;
+                       encrypt = encryption;
+                       padding = algo.Padding;
+                       // transform buffer
+                       workBuff = new byte [BlockSizeByte];
+               }
+               
+               ~FastCryptorTransform ()
+               {
+                       Dispose (false);
+               }
+               
+               public void Dispose ()
+               {
+                       Dispose (true);
+               }
+               
+               protected virtual void Dispose (bool disposing)
+               {
+                       if (handle != IntPtr.Zero) {
+                               Cryptor.CCCryptorRelease (handle);
+                               handle = IntPtr.Zero;
+                       }
+                       GC.SuppressFinalize (this);
+               }
+
+               public virtual bool CanTransformMultipleBlocks {
+                       get { return true; }
+               }
+
+               public virtual bool CanReuseTransform {
+                       get { return false; }
+               }
+
+               public virtual int InputBlockSize {
+                       get { return BlockSizeByte; }
+               }
+
+               public virtual int OutputBlockSize {
+                       get { return BlockSizeByte; }
+               }
+
+               int Transform (byte[] input, int inputOffset, byte[] output, int outputOffset, int length)
+               {
+                       IntPtr len = IntPtr.Zero;
+                       IntPtr in_len = (IntPtr) length;
+                       IntPtr out_len = (IntPtr) (output.Length - outputOffset);
+                       fixed (byte* inputBuffer = &input [0])
+                       fixed (byte* outputBuffer = &output [0]) {
+                               CCCryptorStatus s = Cryptor.CCCryptorUpdate (handle, (IntPtr) (inputBuffer + inputOffset), in_len, (IntPtr) (outputBuffer + outputOffset), out_len, ref len);
+                               if (s != CCCryptorStatus.Success)
+                                       throw new CryptographicException (s.ToString ());
+                       }
+                       return (int) len;
+               }
+
+               private void CheckInput (byte[] inputBuffer, int inputOffset, int inputCount)
+               {
+                       if (inputBuffer == null)
+                               throw new ArgumentNullException ("inputBuffer");
+                       if (inputOffset < 0)
+                               throw new ArgumentOutOfRangeException ("inputOffset", "< 0");
+                       if (inputCount < 0)
+                               throw new ArgumentOutOfRangeException ("inputCount", "< 0");
+                       // ordered to avoid possible integer overflow
+                       if (inputOffset > inputBuffer.Length - inputCount)
+                               throw new ArgumentException ("inputBuffer", "Overflow");
+               }
+
+               // this method may get called MANY times so this is the one to optimize
+               public virtual int TransformBlock (byte[] inputBuffer, int inputOffset, int inputCount, byte[] outputBuffer, int outputOffset) 
+               {
+                       CheckInput (inputBuffer, inputOffset, inputCount);
+                       // check output parameters
+                       if (outputBuffer == null)
+                               throw new ArgumentNullException ("outputBuffer");
+                       if (outputOffset < 0)
+                               throw new ArgumentOutOfRangeException ("outputOffset", "< 0");
+
+                       // ordered to avoid possible integer overflow
+                       int len = outputBuffer.Length - inputCount - outputOffset;
+                       if (!encrypt && (0 > len) && ((padding == PaddingMode.None) || (padding == PaddingMode.Zeros))) {
+                               throw new CryptographicException ("outputBuffer", "Overflow");
+                       } else if (KeepLastBlock) {
+                               if (0 > len + BlockSizeByte) {
+                                       throw new CryptographicException ("outputBuffer", "Overflow");
+                               }
+                       } else {
+                               if (0 > len) {
+                                       // there's a special case if this is the end of the decryption process
+                                       if (inputBuffer.Length - inputOffset - outputBuffer.Length == BlockSizeByte)
+                                               inputCount = outputBuffer.Length - outputOffset;
+                                       else
+                                               throw new CryptographicException ("outputBuffer", "Overflow");
+                               }
+                       }
+                       return InternalTransformBlock (inputBuffer, inputOffset, inputCount, outputBuffer, outputOffset);
+               }
+
+               private bool KeepLastBlock {
+                       get {
+                               return ((!encrypt) && (padding != PaddingMode.None) && (padding != PaddingMode.Zeros));
+                       }
+               }
+
+               private int InternalTransformBlock (byte[] inputBuffer, int inputOffset, int inputCount, byte[] outputBuffer, int outputOffset) 
+               {
+                       int offs = inputOffset;
+                       int full;
+
+                       // this way we don't do a modulo every time we're called
+                       // and we may save a division
+                       if (inputCount != BlockSizeByte) {
+                               if ((inputCount % BlockSizeByte) != 0)
+                                       throw new CryptographicException ("Invalid input block size.");
+
+                               full = inputCount / BlockSizeByte;
+                       } else
+                               full = 1;
+
+                       if (KeepLastBlock)
+                               full--;
+
+                       int total = 0;
+
+                       if (lastBlock) {
+                               Transform (workBuff, 0, outputBuffer, outputOffset, BlockSizeByte);
+                               outputOffset += BlockSizeByte;
+                               total += BlockSizeByte;
+                               lastBlock = false;
+                       }
+
+                       if (full > 0) {
+                               int length = full * BlockSizeByte;
+                               Transform (inputBuffer, offs, outputBuffer, outputOffset, length);
+                               offs += length;
+                               outputOffset += length;
+                               total += length;
+                       }
+
+                       if (KeepLastBlock) {
+                               Buffer.BlockCopy (inputBuffer, offs, workBuff, 0, BlockSizeByte);
+                               lastBlock = true;
+                       }
+
+                       return total;
+               }
+
+               private void Random (byte[] buffer, int start, int length)
+               {
+                       byte[] random = new byte [length];
+                       Cryptor.GetRandom (random);
+                       Buffer.BlockCopy (random, 0, buffer, start, length);
+               }
+
+               private void ThrowBadPaddingException (PaddingMode padding, int length, int position)
+               {
+                       string msg = String.Format ("Bad {0} padding.", padding);
+                       if (length >= 0)
+                               msg += String.Format (" Invalid length {0}.", length);
+                       if (position >= 0)
+                               msg += String.Format (" Error found at position {0}.", position);
+                       throw new CryptographicException (msg);
+               }
+
+               private byte[] FinalEncrypt (byte[] inputBuffer, int inputOffset, int inputCount) 
+               {
+                       // are there still full block to process ?
+                       int full = (inputCount / BlockSizeByte) * BlockSizeByte;
+                       int rem = inputCount - full;
+                       int total = full;
+
+                       switch (padding) {
+                       case PaddingMode.ANSIX923:
+                       case PaddingMode.ISO10126:
+                       case PaddingMode.PKCS7:
+                               // we need to add an extra block for padding
+                               total += BlockSizeByte;
+                               break;
+                       default:
+                               if (inputCount == 0)
+                                       return new byte [0];
+                               if (rem != 0) {
+                                       if (padding == PaddingMode.None)
+                                               throw new CryptographicException ("invalid block length");
+                                       // zero padding the input (by adding a block for the partial data)
+                                       byte[] paddedInput = new byte [full + BlockSizeByte];
+                                       Buffer.BlockCopy (inputBuffer, inputOffset, paddedInput, 0, inputCount);
+                                       inputBuffer = paddedInput;
+                                       inputOffset = 0;
+                                       inputCount = paddedInput.Length;
+                                       total = inputCount;
+                               }
+                               break;
+                       }
+
+                       byte[] res = new byte [total];
+                       int outputOffset = 0;
+
+                       // process all blocks except the last (final) block
+                       if (total > BlockSizeByte) {
+                               outputOffset = InternalTransformBlock (inputBuffer, inputOffset, total - BlockSizeByte, res, 0);
+                               inputOffset += outputOffset;
+                       }
+
+                       // now we only have a single last block to encrypt
+                       byte pad = (byte) (BlockSizeByte - rem);
+                       switch (padding) {
+                       case PaddingMode.ANSIX923:
+                               // XX 00 00 00 00 00 00 07 (zero + padding length)
+                               res [res.Length - 1] = pad;
+                               Buffer.BlockCopy (inputBuffer, inputOffset, res, full, rem);
+                               // the last padded block will be transformed in-place
+                               InternalTransformBlock (res, full, BlockSizeByte, res, full);
+                               break;
+                       case PaddingMode.ISO10126:
+                               // XX 3F 52 2A 81 AB F7 07 (random + padding length)
+                               Random (res, res.Length - pad, pad - 1);
+                               res [res.Length - 1] = pad;
+                               Buffer.BlockCopy (inputBuffer, inputOffset, res, full, rem);
+                               // the last padded block will be transformed in-place
+                               InternalTransformBlock (res, full, BlockSizeByte, res, full);
+                               break;
+                       case PaddingMode.PKCS7:
+                               // XX 07 07 07 07 07 07 07 (padding length)
+                               for (int i = res.Length; --i >= (res.Length - pad);) 
+                                       res [i] = pad;
+                               Buffer.BlockCopy (inputBuffer, inputOffset, res, full, rem);
+                               // the last padded block will be transformed in-place
+                               InternalTransformBlock (res, full, BlockSizeByte, res, full);
+                               break;
+                       default:
+                               InternalTransformBlock (inputBuffer, inputOffset, BlockSizeByte, res, outputOffset);
+                               break;
+                       }
+                       return res;
+               }
+
+               private byte[] FinalDecrypt (byte[] inputBuffer, int inputOffset, int inputCount) 
+               {
+                       if ((inputCount % BlockSizeByte) > 0)
+                               throw new CryptographicException ("Invalid input block size.");
+
+                       int total = inputCount;
+                       if (lastBlock)
+                               total += BlockSizeByte;
+
+                       byte[] res = new byte [total];
+                       int outputOffset = 0;
+
+                       if (inputCount > 0)
+                               outputOffset = InternalTransformBlock (inputBuffer, inputOffset, inputCount, res, 0);
+
+                       if (lastBlock) {
+                               Transform (workBuff, 0, res, outputOffset, BlockSizeByte);
+                               outputOffset += BlockSizeByte;
+                               lastBlock = false;
+                       }
+
+                       // total may be 0 (e.g. PaddingMode.None)
+                       byte pad = ((total > 0) ? res [total - 1] : (byte) 0);
+                       switch (padding) {
+                       case PaddingMode.ANSIX923:
+                               if ((pad == 0) || (pad > BlockSizeByte))
+                                       ThrowBadPaddingException (padding, pad, -1);
+                               for (int i = pad - 1; i > 0; i--) {
+                                       if (res [total - 1 - i] != 0x00)
+                                               ThrowBadPaddingException (padding, -1, i);
+                               }
+                               total -= pad;
+                               break;
+                       case PaddingMode.ISO10126:
+                               if ((pad == 0) || (pad > BlockSizeByte))
+                                       ThrowBadPaddingException (padding, pad, -1);
+                               total -= pad;
+                               break;
+                       case PaddingMode.PKCS7:
+                               if ((pad == 0) || (pad > BlockSizeByte))
+                                       ThrowBadPaddingException (padding, pad, -1);
+                               for (int i = pad - 1; i > 0; i--) {
+                                       if (res [total - 1 - i] != pad)
+                                               ThrowBadPaddingException (padding, -1, i);
+                               }
+                               total -= pad;
+                               break;
+                       case PaddingMode.None:  // nothing to do - it's a multiple of block size
+                       case PaddingMode.Zeros: // nothing to do - user must unpad himself
+                               break;
+                       }
+
+                       // return output without padding
+                       if (total > 0) {
+                               byte[] data = new byte [total];
+                               Buffer.BlockCopy (res, 0, data, 0, total);
+                               // zeroize decrypted data (copy with padding)
+                               Array.Clear (res, 0, res.Length);
+                               return data;
+                       }
+                       else
+                               return new byte [0];
+               }
+
+               public virtual byte[] TransformFinalBlock (byte[] inputBuffer, int inputOffset, int inputCount) 
+               {
+                       CheckInput (inputBuffer, inputOffset, inputCount);
+
+                       if (encrypt)
+                               return FinalEncrypt (inputBuffer, inputOffset, inputCount);
+                       else
+                               return FinalDecrypt (inputBuffer, inputOffset, inputCount);
+               }
+       }
+}
\ No newline at end of file
diff --git a/mcs/class/corlib/CommonCrypto/Makefile.include b/mcs/class/corlib/CommonCrypto/Makefile.include
new file mode 100644 (file)
index 0000000..25e1379
--- /dev/null
@@ -0,0 +1,5 @@
+CommonCrypto/%.g.cs: CommonCrypto/generator.exe
+       cd CommonCrypto && mono --debug generator.exe
+
+CommonCrypto/generator.exe: CommonCrypto/generator.cs CommonCrypto/CommonDigestGenerator.cs CommonCrypto/CommonCryptorGenerator.cs
+       mcs CommonCrypto/generator.cs CommonCrypto/CommonDigestGenerator.cs CommonCrypto/CommonCryptorGenerator.cs -o $@
diff --git a/mcs/class/corlib/CommonCrypto/RC4CommonCrypto.cs b/mcs/class/corlib/CommonCrypto/RC4CommonCrypto.cs
new file mode 100644 (file)
index 0000000..1e5c4e2
--- /dev/null
@@ -0,0 +1,212 @@
+// A CommonCrypto-based implementation of RC4(tm)
+//
+// Authors:
+//     Sebastien Pouliot  <sebastien@xamarin.com>
+//
+// (C) 2003 Motus Technologies Inc. (http://www.motus.com)
+// Copyright 2012-2014 Xamarin Inc.
+
+using System;
+using System.Security.Cryptography;
+
+using Crimson.CommonCrypto;
+
+#if MONOTOUCH || XAMMAC
+using Mono.Security.Cryptography;
+
+namespace Mono.Security.Cryptography {
+
+#if !INSIDE_CORLIB
+       public
+#endif
+       sealed partial class ARC4Managed : RC4, ICryptoTransform {
+               
+               IntPtr handle;
+               
+               public ARC4Managed ()
+               {
+               }
+               
+               ~ARC4Managed ()
+               {
+                       Dispose (false);
+               }
+#else
+namespace Crimson.Security.Cryptography {
+
+       public abstract class RC4 : SymmetricAlgorithm {
+
+               private static KeySizes[] s_legalBlockSizes = {
+                       new KeySizes (64, 64, 0)
+               };
+
+               private static KeySizes[] s_legalKeySizes = {
+                       new KeySizes (40, 512, 8)  
+               };
+       
+               public RC4 () 
+               {
+                       KeySizeValue = 128;
+                       BlockSizeValue = 64;
+                       FeedbackSizeValue = BlockSizeValue;
+                       LegalBlockSizesValue = s_legalBlockSizes;
+                       LegalKeySizesValue = s_legalKeySizes;
+               }
+
+               // required for compatibility with .NET 2.0
+               public override byte[] IV {
+                       get { return new byte [0]; }
+                       set { ; }
+               }
+
+               new static public RC4 Create() 
+               {
+                       return Create ("RC4");
+               }
+
+               new static public RC4 Create (string algName) 
+               {
+                       object o = CryptoConfig.CreateFromName (algName);
+                       return (RC4) o ?? new RC4CommonCrypto ();
+               }
+       }
+
+       public sealed class RC4CommonCrypto : RC4, ICryptoTransform {
+               
+               IntPtr handle;
+               
+               public RC4CommonCrypto ()
+               {
+               }
+               
+               ~RC4CommonCrypto ()
+               {
+                       Dispose (false);
+               }
+#endif
+               
+               public bool CanReuseTransform {
+                       get { return false; }
+               }
+
+               public bool CanTransformMultipleBlocks {
+                       get { return true; }
+               }
+               
+               public int InputBlockSize {
+                       get { return 1; }
+               }
+
+               public int OutputBlockSize {
+                       get { return 1; }
+               }
+               
+               public override byte[] Key {
+                       get {
+                               return base.Key;
+                       }
+                       set {
+                               if (value == null)
+                                       throw new ArgumentNullException ("Key");
+
+                               int length = (value.Length << 3);
+                               KeySizeValue = length;
+                               KeyValue = (byte[]) value.Clone ();
+                       }
+               }
+               
+               protected override void Dispose (bool disposing)
+               {
+                       if (handle != IntPtr.Zero) {
+                               Cryptor.CCCryptorRelease (handle);
+                               handle = IntPtr.Zero;
+                       }
+                       base.Dispose (disposing);
+                       GC.SuppressFinalize (this);
+               }
+               
+               public override void GenerateIV ()
+               {
+                       // not used for a stream cipher
+                       IVValue = new byte [0];
+               }
+               
+               public override void GenerateKey ()
+               {
+                       KeyValue = KeyBuilder.Key (KeySizeValue >> 3);
+               }
+               
+               public override ICryptoTransform CreateDecryptor (byte[] rgbKey, byte[] rgbIV) 
+               {
+                       KeyValue = rgbKey;
+                       IVValue = rgbIV;
+                       return this;
+               }
+               
+               public override ICryptoTransform CreateEncryptor (byte[] rgbKey, byte[] rgbIV) 
+               {
+                       KeyValue = rgbKey;
+                       IVValue = rgbIV;
+                       return this;
+               }
+
+               private void CheckInput (byte[] inputBuffer, int inputOffset, int inputCount)
+               {
+                       if (inputBuffer == null)
+                               throw new ArgumentNullException ("inputBuffer");
+                       if (inputOffset < 0)
+                               throw new ArgumentOutOfRangeException ("inputOffset", "< 0");
+                       if (inputCount < 0)
+                               throw new ArgumentOutOfRangeException ("inputCount", "< 0");
+                       // ordered to avoid possible integer overflow
+                       if (inputOffset > inputBuffer.Length - inputCount)
+                               throw new ArgumentException ("inputBuffer", "Overflow");
+               }
+
+               public unsafe int TransformBlock (byte[] inputBuffer, int inputOffset, int inputCount, byte[] outputBuffer, int outputOffset) 
+               {
+                       CheckInput (inputBuffer, inputOffset, inputCount);
+                       if (inputCount == 0)
+                               return 0;
+
+                       // check output parameters
+                       if (outputBuffer == null)
+                               throw new ArgumentNullException ("outputBuffer");
+                       if (outputOffset < 0)
+                               throw new ArgumentOutOfRangeException ("outputOffset", "< 0");
+                       // ordered to avoid possible integer overflow
+                       if (outputOffset > outputBuffer.Length - inputCount)
+                               throw new ArgumentException ("outputBuffer", "Overflow");
+                       if (outputBuffer.Length == 0)
+                               throw new CryptographicException ("output buffer too small");
+                       
+                       if (handle == IntPtr.Zero)
+                               handle = Cryptor.Create (CCOperation.Encrypt, CCAlgorithm.RC4, CCOptions.None, KeyValue, IVValue);
+
+                       IntPtr len = IntPtr.Zero;
+                       IntPtr in_len = (IntPtr) (inputBuffer.Length - inputOffset);
+                       IntPtr out_len = (IntPtr) (outputBuffer.Length - outputOffset);
+                       fixed (byte* input = &inputBuffer [0])
+                       fixed (byte* output = &outputBuffer [0]) {
+                               CCCryptorStatus s = Cryptor.CCCryptorUpdate (handle, (IntPtr) (input + inputOffset), in_len, (IntPtr) (output + outputOffset), out_len, ref len);
+                               if ((len != out_len) || (s != CCCryptorStatus.Success))
+                                       throw new CryptographicUnexpectedOperationException (s.ToString ());
+                       }
+                       return (int) out_len;
+               }
+               
+               public byte[] TransformFinalBlock (byte[] inputBuffer, int inputOffset, int inputCount)
+               {
+                       CheckInput (inputBuffer, inputOffset, inputCount);
+                       try {
+                               byte[] output = new byte [inputCount];
+                               TransformBlock (inputBuffer, inputOffset, inputCount, output, 0);
+                               return output;
+                       }
+                       finally {
+                               Cryptor.CCCryptorRelease (handle);
+                               handle = IntPtr.Zero;
+                       }
+               }
+       }
+}
\ No newline at end of file
diff --git a/mcs/class/corlib/CommonCrypto/RijndaelManaged.cs b/mcs/class/corlib/CommonCrypto/RijndaelManaged.cs
new file mode 100644 (file)
index 0000000..3d528d3
--- /dev/null
@@ -0,0 +1,119 @@
+//
+// RijndaelManaged.cs: Use CommonCrypto AES when possible, 
+//     fallback on RijndaelManagedTransform otherwise
+//
+// Authors:
+//     Sebastien Pouliot  <sebastien@xamarin.com>
+//
+// Copyright 2012 Xamarin Inc.
+//
+
+using System;
+using System.Security.Cryptography;
+
+using Mono.Security.Cryptography;
+using Crimson.CommonCrypto;
+
+namespace System.Security.Cryptography {
+       
+       public sealed class RijndaelManaged : Rijndael {
+               
+               public RijndaelManaged ()
+               {
+               }
+               
+               public override void GenerateIV ()
+               {
+                       IVValue = KeyBuilder.IV (BlockSizeValue >> 3);
+               }
+               
+               public override void GenerateKey ()
+               {
+                       KeyValue = KeyBuilder.Key (KeySizeValue >> 3);
+               }
+               
+               public override ICryptoTransform CreateDecryptor (byte[] rgbKey, byte[] rgbIV) 
+               {
+                       // AES is Rijndael with a 128 bits block size, so we can use CommonCrypto in this case
+                       if (BlockSize == 128) {
+                               IntPtr decryptor = IntPtr.Zero;
+                               switch (Mode) {
+                               case CipherMode.CBC:
+                                       decryptor = Cryptor.Create (CCOperation.Decrypt, CCAlgorithm.AES128, CCOptions.None, rgbKey, rgbIV);
+                                       return new FastCryptorTransform (decryptor, this, false, rgbIV);
+                               case CipherMode.ECB:
+                                       decryptor = Cryptor.Create (CCOperation.Decrypt, CCAlgorithm.AES128, CCOptions.ECBMode, rgbKey, rgbIV);
+                                       return new FastCryptorTransform (decryptor, this, false, rgbIV);
+                               default:
+                                       // CFB cipher mode is not supported by the (old) API we used (for compatibility) so we fallback for them
+                                       // FIXME: benchmark if we're better with RijndaelManagedTransform or CryptorTransform for CFB mode
+                                       break;
+                               }
+                       }
+
+            return NewEncryptor(rgbKey,
+                                ModeValue,
+                                rgbIV,
+                                FeedbackSizeValue,
+                                RijndaelManagedTransformMode.Decrypt);
+               }
+               
+               public override ICryptoTransform CreateEncryptor (byte[] rgbKey, byte[] rgbIV) 
+               {
+                       if (BlockSize == 128) {
+                               IntPtr encryptor = IntPtr.Zero;
+                               switch (Mode) {
+                               case CipherMode.CBC:
+                                       encryptor = Cryptor.Create (CCOperation.Encrypt, CCAlgorithm.AES128, CCOptions.None, rgbKey, rgbIV);
+                                       return new FastCryptorTransform (encryptor, this, true, rgbIV);
+                               case CipherMode.ECB:
+                                       encryptor = Cryptor.Create (CCOperation.Encrypt, CCAlgorithm.AES128, CCOptions.ECBMode, rgbKey, rgbIV);
+                                       return new FastCryptorTransform (encryptor, this, true, rgbIV);
+                               default:
+                                       // CFB cipher mode is not supported by the (old) API we used (for compatibility) so we fallback for them
+                                       // FIXME: benchmark if we're better with RijndaelManagedTransform or CryptorTransform for CFB mode
+                                       break;
+                               }
+                       }
+
+            return NewEncryptor(rgbKey,
+                                ModeValue,
+                                rgbIV,
+                                FeedbackSizeValue,
+                                RijndaelManagedTransformMode.Encrypt);
+        }
+
+
+        private ICryptoTransform NewEncryptor (byte[] rgbKey,
+                                               CipherMode mode,
+                                               byte[] rgbIV,
+                                               int feedbackSize,
+                                               RijndaelManagedTransformMode encryptMode) {
+            // Build the key if one does not already exist
+            if (rgbKey == null) {
+                rgbKey = Utils.GenerateRandom(KeySizeValue / 8);
+            }
+
+            // If not ECB mode, make sure we have an IV. In CoreCLR we do not support ECB, so we must have
+            // an IV in all cases.
+#if !FEATURE_CRYPTO
+            if (mode != CipherMode.ECB) {
+#endif // !FEATURE_CRYPTO
+                if (rgbIV == null) {
+                    rgbIV = Utils.GenerateRandom(BlockSizeValue / 8);
+                }
+#if !FEATURE_CRYPTO
+            }
+#endif // !FEATURE_CRYPTO
+
+            // Create the encryptor/decryptor object
+            return new RijndaelManagedTransform (rgbKey,
+                                                 mode,
+                                                 rgbIV,
+                                                 BlockSizeValue,
+                                                 feedbackSize,
+                                                 PaddingValue,
+                                                 encryptMode);
+        }                            
+       }
+}
\ No newline at end of file
diff --git a/mcs/class/corlib/CommonCrypto/SecRandom.cs b/mcs/class/corlib/CommonCrypto/SecRandom.cs
new file mode 100644 (file)
index 0000000..a112faf
--- /dev/null
@@ -0,0 +1,81 @@
+//
+// SecRandom.cs: based on Mono's System.Security.Cryptography.RNGCryptoServiceProvider
+//
+// Authors:
+//     Mark Crichton (crichton@gimp.org)
+//     Sebastien Pouliot (sebastien@xamarun.com)
+//
+// (C) 2002
+// Copyright (C) 2004-2005 Novell, Inc (http://www.novell.com)
+// Copyright (C) 2012-2014 Xamarin Inc.
+//
+// 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 Crimson.CommonCrypto;
+
+// http://developer.apple.com/library/ios/#DOCUMENTATION/Security/Reference/RandomizationReference/Reference/reference.html
+#if MONOTOUCH || XAMMAC
+namespace System.Security.Cryptography {
+       public class RNGCryptoServiceProvider : RandomNumberGenerator {
+               public RNGCryptoServiceProvider ()
+               {
+               }
+               
+               ~RNGCryptoServiceProvider () 
+               {
+               }
+#else
+using System;
+using System.Security.Cryptography;
+
+namespace Crimson.Security.Cryptography {
+                       
+       public class SecRandom : RandomNumberGenerator {
+#endif
+               
+               public override void GetBytes (byte[] data) 
+               {
+                       if (data == null)
+                               throw new ArgumentNullException ("data");
+                                       
+                       Cryptor.GetRandom (data);
+               }
+               
+               public override void GetNonZeroBytes (byte[] data) 
+               {
+                       if (data == null)
+                               throw new ArgumentNullException ("data");
+
+                       byte[] random = new byte [data.Length * 2];
+                       int i = 0;
+                       // one pass should be enough but hey this is random ;-)
+                       while (i < data.Length) {
+                               Cryptor.GetRandom (random);
+                               for (int j=0; j < random.Length; j++) {
+                                       if (i == data.Length)
+                                               break;
+                                       if (random [j] != 0)
+                                               data [i++] = random [j];
+                               }
+                       }
+               }
+       }
+}
\ No newline at end of file
diff --git a/mcs/class/corlib/CommonCrypto/generator.cs b/mcs/class/corlib/CommonCrypto/generator.cs
new file mode 100644 (file)
index 0000000..a7d13c8
--- /dev/null
@@ -0,0 +1,57 @@
+//
+// CommonCrypto Code Generator
+//
+// Authors:
+//     Sebastien Pouliot  <sebastien@xamarin.com>
+//
+// Copyright 2012 Xamarin Inc.
+//
+
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Text;
+
+namespace Xamarin {
+       
+       class Program {
+               static void Main (string [] args)
+               {
+                       // mscorlib replacements
+                       CommonDigest.Generate ("System.Security.Cryptography", "MD5CryptoServiceProvider", "MD5", 1000);
+                       CommonDigest.Generate ("System.Security.Cryptography", "SHA1CryptoServiceProvider", "SHA1", 1000);
+                       CommonDigest.Generate ("System.Security.Cryptography", "SHA1Managed", "SHA1", 1000);
+                       CommonDigest.Generate ("System.Security.Cryptography", "SHA256Managed", "SHA256", 1000);
+                       CommonDigest.Generate ("System.Security.Cryptography", "SHA384Managed", "SHA384", 1000);
+                       CommonDigest.Generate ("System.Security.Cryptography", "SHA512Managed", "SHA512", 1000);
+                       
+                       // System.Core replacements - not yet in MT profile (4.0 - functional dupes anyway)
+                       //CommonDigest.Generate ("System.Security.Cryptography", "MD5Cng", "MD5", 1000);
+                       //CommonDigest.Generate ("System.Security.Cryptography", "SHA256Cng", "SHA256", 1000);
+                       //CommonDigest.Generate ("System.Security.Cryptography", "SHA384Cng", "SHA384", 1000);
+                       //CommonDigest.Generate ("System.Security.Cryptography", "SHA512Cng", "SHA512", 1000);
+                       //CommonDigest.Generate ("System.Security.Cryptography", "SHA256CryptoServiceProvider", "SHA256", 1000);
+                       //CommonDigest.Generate ("System.Security.Cryptography", "SHA384CryptoServiceProvider", "SHA384", 1000);
+                       //CommonDigest.Generate ("System.Security.Cryptography", "SHA512CryptoServiceProvider", "SHA512", 1000);
+                       
+                       // Mono.Security replacements
+                       CommonDigest.Generate ("Mono.Security.Cryptography", "MD2Managed", "MD2", 1000, "#if !INSIDE_CORLIB", "#endif");
+                       CommonDigest.Generate ("Mono.Security.Cryptography", "MD4Managed", "MD4", 1000, "#if !INSIDE_CORLIB", "#endif");
+                       CommonDigest.Generate ("Mono.Security.Cryptography", "SHA224Managed", "SHA224", 1000);
+
+                       // mscorlib replacements
+                       CommonCryptor.Generate ("System.Security.Cryptography", "DESCryptoServiceProvider", "DES", "DES");
+                       CommonCryptor.Generate ("System.Security.Cryptography", "TripleDESCryptoServiceProvider", "TripleDES", "TripleDES");
+                       CommonCryptor.Generate ("System.Security.Cryptography", "RC2CryptoServiceProvider", "RC2", "RC2", ctorInitializers: "LegalKeySizesValue = new[] { new KeySizes(40, 128, 8) };");
+                       // Rijndael supports block sizes that are not available in AES - as such it does not use the same generated code
+                       // but has it's own version, using AES (128 bits block size) and falling back to managed (192/256 bits block size)
+
+                       // System.Core replacements
+                       CommonCryptor.Generate ("System.Security.Cryptography", "AesManaged", "Aes", "AES128", "128");
+                       CommonCryptor.Generate ("System.Security.Cryptography", "AesCryptoServiceProvider", "Aes", "AES128");
+
+                       // Mono.Security replacements
+                       // RC4 is a stream (not a block) cipher so it can not reuse the generated code
+               }
+       }
+}
\ No newline at end of file
index 2540e23603143f4999cba59f4c9b11cdc42d6a09..aff30966f5a5a3555c898dfa1bf8223a3202559f 100644 (file)
@@ -1,6 +1,7 @@
 thisdir = class/corlib
 SUBDIRS =
 include ../../build/rules.make
+include CommonCrypto/Makefile.include
 export __SECURITY_BOOTSTRAP_DB=$(topdir)/class/corlib
 
 LIBRARY = corlib.dll
diff --git a/mcs/class/corlib/monotouch_corlib.dll.exclude.sources b/mcs/class/corlib/monotouch_corlib.dll.exclude.sources
new file mode 100644 (file)
index 0000000..7287193
--- /dev/null
@@ -0,0 +1,15 @@
+System.Security.Cryptography/MD5CryptoServiceProvider.cs
+System.Security.Cryptography/SHA1CryptoServiceProvider.cs
+System.Security.Cryptography/SHA1CryptoServiceProvider.cs
+../../../external/referencesource/mscorlib/system/security/cryptography/descryptoserviceprovider.cs
+../../../external/referencesource/mscorlib/system/security/cryptography/rc2cryptoserviceprovider.cs
+../../../external/referencesource/mscorlib/system/security/cryptography/rijndaelmanaged.cs
+../../../external/referencesource/mscorlib/system/security/cryptography/sha1managed.cs
+../../../external/referencesource/mscorlib/system/security/cryptography/sha256managed.cs
+../../../external/referencesource/mscorlib/system/security/cryptography/sha384managed.cs
+../../../external/referencesource/mscorlib/system/security/cryptography/sha512managed.cs
+../../../external/referencesource/mscorlib/system/security/cryptography/tripledescryptoserviceprovider.cs
+System.Security.Cryptography/RNGCryptoServiceProvider.cs
+../Mono.Security/Mono.Security.Cryptography/ARC4Managed.cs
+../Mono.Security/Mono.Security.Cryptography/MD2Managed.cs
+../Mono.Security/Mono.Security.Cryptography/MD4Managed.cs
index da77893bcc50c66f173571e43a57595448b44e27..55b9d548f268ed10350a13e3debc791bb4c3c233 100644 (file)
@@ -1 +1,20 @@
 #include corlib.dll.sources
+CommonCrypto/CommonCrypto.cs
+CommonCrypto/CryptorTransform.cs
+CommonCrypto/FastCryptorTransform.cs
+CommonCrypto/CorlibExtras.cs
+CommonCrypto/MD5CryptoServiceProvider.g.cs
+CommonCrypto/SHA1CryptoServiceProvider.g.cs
+CommonCrypto/SHA1CryptoServiceProvider.g.cs
+CommonCrypto/SHA1Managed.g.cs
+CommonCrypto/SHA256Managed.g.cs
+CommonCrypto/SHA384Managed.g.cs
+CommonCrypto/SHA512Managed.g.cs
+CommonCrypto/TripleDESCryptoServiceProvider.g.cs
+CommonCrypto/DESCryptoServiceProvider.g.cs
+CommonCrypto/RC2CryptoServiceProvider.g.cs
+CommonCrypto/RijndaelManaged.cs
+CommonCrypto/SecRandom.cs
+CommonCrypto/RC4CommonCrypto.cs
+CommonCrypto/MD2Managed.g.cs
+CommonCrypto/MD4Managed.g.cs
diff --git a/mcs/class/corlib/monotouch_runtime_corlib.dll.exclude.sources b/mcs/class/corlib/monotouch_runtime_corlib.dll.exclude.sources
new file mode 100644 (file)
index 0000000..53efeac
--- /dev/null
@@ -0,0 +1 @@
+#include monotouch_corlib.dll.exclude.sources
index da77893bcc50c66f173571e43a57595448b44e27..55b9d548f268ed10350a13e3debc791bb4c3c233 100644 (file)
@@ -1 +1,20 @@
 #include corlib.dll.sources
+CommonCrypto/CommonCrypto.cs
+CommonCrypto/CryptorTransform.cs
+CommonCrypto/FastCryptorTransform.cs
+CommonCrypto/CorlibExtras.cs
+CommonCrypto/MD5CryptoServiceProvider.g.cs
+CommonCrypto/SHA1CryptoServiceProvider.g.cs
+CommonCrypto/SHA1CryptoServiceProvider.g.cs
+CommonCrypto/SHA1Managed.g.cs
+CommonCrypto/SHA256Managed.g.cs
+CommonCrypto/SHA384Managed.g.cs
+CommonCrypto/SHA512Managed.g.cs
+CommonCrypto/TripleDESCryptoServiceProvider.g.cs
+CommonCrypto/DESCryptoServiceProvider.g.cs
+CommonCrypto/RC2CryptoServiceProvider.g.cs
+CommonCrypto/RijndaelManaged.cs
+CommonCrypto/SecRandom.cs
+CommonCrypto/RC4CommonCrypto.cs
+CommonCrypto/MD2Managed.g.cs
+CommonCrypto/MD4Managed.g.cs
diff --git a/mcs/class/corlib/monotouch_tv_corlib.dll.exclude.sources b/mcs/class/corlib/monotouch_tv_corlib.dll.exclude.sources
new file mode 100644 (file)
index 0000000..53efeac
--- /dev/null
@@ -0,0 +1 @@
+#include monotouch_corlib.dll.exclude.sources
index da77893bcc50c66f173571e43a57595448b44e27..55b9d548f268ed10350a13e3debc791bb4c3c233 100644 (file)
@@ -1 +1,20 @@
 #include corlib.dll.sources
+CommonCrypto/CommonCrypto.cs
+CommonCrypto/CryptorTransform.cs
+CommonCrypto/FastCryptorTransform.cs
+CommonCrypto/CorlibExtras.cs
+CommonCrypto/MD5CryptoServiceProvider.g.cs
+CommonCrypto/SHA1CryptoServiceProvider.g.cs
+CommonCrypto/SHA1CryptoServiceProvider.g.cs
+CommonCrypto/SHA1Managed.g.cs
+CommonCrypto/SHA256Managed.g.cs
+CommonCrypto/SHA384Managed.g.cs
+CommonCrypto/SHA512Managed.g.cs
+CommonCrypto/TripleDESCryptoServiceProvider.g.cs
+CommonCrypto/DESCryptoServiceProvider.g.cs
+CommonCrypto/RC2CryptoServiceProvider.g.cs
+CommonCrypto/RijndaelManaged.cs
+CommonCrypto/SecRandom.cs
+CommonCrypto/RC4CommonCrypto.cs
+CommonCrypto/MD2Managed.g.cs
+CommonCrypto/MD4Managed.g.cs
diff --git a/mcs/class/corlib/monotouch_tv_runtime_corlib.dll.exclude.sources b/mcs/class/corlib/monotouch_tv_runtime_corlib.dll.exclude.sources
new file mode 100644 (file)
index 0000000..53efeac
--- /dev/null
@@ -0,0 +1 @@
+#include monotouch_corlib.dll.exclude.sources
diff --git a/mcs/class/corlib/monotouch_watch_corlib.dll.exclude.sources b/mcs/class/corlib/monotouch_watch_corlib.dll.exclude.sources
new file mode 100644 (file)
index 0000000..53efeac
--- /dev/null
@@ -0,0 +1 @@
+#include monotouch_corlib.dll.exclude.sources
index da77893bcc50c66f173571e43a57595448b44e27..55b9d548f268ed10350a13e3debc791bb4c3c233 100644 (file)
@@ -1 +1,20 @@
 #include corlib.dll.sources
+CommonCrypto/CommonCrypto.cs
+CommonCrypto/CryptorTransform.cs
+CommonCrypto/FastCryptorTransform.cs
+CommonCrypto/CorlibExtras.cs
+CommonCrypto/MD5CryptoServiceProvider.g.cs
+CommonCrypto/SHA1CryptoServiceProvider.g.cs
+CommonCrypto/SHA1CryptoServiceProvider.g.cs
+CommonCrypto/SHA1Managed.g.cs
+CommonCrypto/SHA256Managed.g.cs
+CommonCrypto/SHA384Managed.g.cs
+CommonCrypto/SHA512Managed.g.cs
+CommonCrypto/TripleDESCryptoServiceProvider.g.cs
+CommonCrypto/DESCryptoServiceProvider.g.cs
+CommonCrypto/RC2CryptoServiceProvider.g.cs
+CommonCrypto/RijndaelManaged.cs
+CommonCrypto/SecRandom.cs
+CommonCrypto/RC4CommonCrypto.cs
+CommonCrypto/MD2Managed.g.cs
+CommonCrypto/MD4Managed.g.cs
diff --git a/mcs/class/corlib/monotouch_watch_runtime_corlib.dll.exclude.sources b/mcs/class/corlib/monotouch_watch_runtime_corlib.dll.exclude.sources
new file mode 100644 (file)
index 0000000..53efeac
--- /dev/null
@@ -0,0 +1 @@
+#include monotouch_corlib.dll.exclude.sources
diff --git a/mcs/class/corlib/xammac_corlib.dll.exclude.sources b/mcs/class/corlib/xammac_corlib.dll.exclude.sources
new file mode 100644 (file)
index 0000000..86bb404
--- /dev/null
@@ -0,0 +1,14 @@
+System.Security.Cryptography/MD5CryptoServiceProvider.cs
+System.Security.Cryptography/SHA1CryptoServiceProvider.cs
+System.Security.Cryptography/SHA1CryptoServiceProvider.cs
+../../../external/referencesource/mscorlib/system/security/cryptography/descryptoserviceprovider.cs
+../../../external/referencesource/mscorlib/system/security/cryptography/rc2cryptoserviceprovider.cs
+../../../external/referencesource/mscorlib/system/security/cryptography/rijndaelmanaged.cs
+../../../external/referencesource/mscorlib/system/security/cryptography/sha1managed.cs
+../../../external/referencesource/mscorlib/system/security/cryptography/sha256managed.cs
+../../../external/referencesource/mscorlib/system/security/cryptography/sha384managed.cs
+../../../external/referencesource/mscorlib/system/security/cryptography/sha512managed.cs
+../../../external/referencesource/mscorlib/system/security/cryptography/tripledescryptoserviceprovider.cs
+../Mono.Security/Mono.Security.Cryptography/ARC4Managed.cs
+../Mono.Security/Mono.Security.Cryptography/MD2Managed.cs
+../Mono.Security/Mono.Security.Cryptography/MD4Managed.cs
index da77893bcc50c66f173571e43a57595448b44e27..4d6428cc31b39deae9f5286e32460c52b843331b 100644 (file)
@@ -1 +1,19 @@
 #include corlib.dll.sources
+CommonCrypto/CommonCrypto.cs
+CommonCrypto/CryptorTransform.cs
+CommonCrypto/FastCryptorTransform.cs
+CommonCrypto/CorlibExtras.cs
+CommonCrypto/MD5CryptoServiceProvider.g.cs
+CommonCrypto/SHA1CryptoServiceProvider.g.cs
+CommonCrypto/SHA1CryptoServiceProvider.g.cs
+CommonCrypto/SHA1Managed.g.cs
+CommonCrypto/SHA256Managed.g.cs
+CommonCrypto/SHA384Managed.g.cs
+CommonCrypto/SHA512Managed.g.cs
+CommonCrypto/TripleDESCryptoServiceProvider.g.cs
+CommonCrypto/DESCryptoServiceProvider.g.cs
+CommonCrypto/RC2CryptoServiceProvider.g.cs
+CommonCrypto/RijndaelManaged.cs
+CommonCrypto/RC4CommonCrypto.cs
+CommonCrypto/MD2Managed.g.cs
+CommonCrypto/MD4Managed.g.cs