From: Rolf Bjarne Kvinge Date: Tue, 15 Mar 2016 11:01:48 +0000 (+0100) Subject: [bcl] Add CommonCrypto to corlib, Mono.Security and System.Core. X-Git-Url: http://wien.tomnetworks.com/gitweb/?p=mono.git;a=commitdiff_plain;h=437d77b5e764cb0955d417b4283b71c827720caf [bcl] Add CommonCrypto to corlib, Mono.Security and System.Core. List of original contributors: Sebastien Pouliot Rolf Bjarne Kvinge Marek Safar Miguel de Icaza --- diff --git a/mcs/class/Mono.Security/monotouch_Mono.Security.dll.sources b/mcs/class/Mono.Security/monotouch_Mono.Security.dll.sources index 513dc61bd4f..17f56e3c405 100644 --- a/mcs/class/Mono.Security/monotouch_Mono.Security.dll.sources +++ b/mcs/class/Mono.Security/monotouch_Mono.Security.dll.sources @@ -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 index e8464be185b..00000000000 --- a/mcs/class/Mono.Security/monotouch_opt_Mono.Security.dll.sources +++ /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 diff --git a/mcs/class/Mono.Security/xammac_Mono.Security.dll.sources b/mcs/class/Mono.Security/xammac_Mono.Security.dll.sources index 1379fa79d80..6c1b4dbef6f 100644 --- a/mcs/class/Mono.Security/xammac_Mono.Security.dll.sources +++ b/mcs/class/Mono.Security/xammac_Mono.Security.dll.sources @@ -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 index e8464be185b..00000000000 --- a/mcs/class/Mono.Security/xammac_opt_Mono.Security.dll.sources +++ /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 diff --git a/mcs/class/System.Core/monotouch_System.Core.dll.sources b/mcs/class/System.Core/monotouch_System.Core.dll.sources index 7d32d44a88b..6b6d96c25a2 100644 --- a/mcs/class/System.Core/monotouch_System.Core.dll.sources +++ b/mcs/class/System.Core/monotouch_System.Core.dll.sources @@ -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 diff --git a/mcs/class/System.Core/xammac_System.Core.dll.sources b/mcs/class/System.Core/xammac_System.Core.dll.sources index 882476b4b5e..6ab44f0f8c2 100644 --- a/mcs/class/System.Core/xammac_System.Core.dll.sources +++ b/mcs/class/System.Core/xammac_System.Core.dll.sources @@ -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 index 00000000000..1252b936471 --- /dev/null +++ b/mcs/class/corlib/CommonCrypto/.gitignore @@ -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 index 00000000000..c765b957352 --- /dev/null +++ b/mcs/class/corlib/CommonCrypto/CommonCrypto.cs @@ -0,0 +1,130 @@ +// CommonCrypto bindings for MonoMac and MonoTouch +// +// Authors: +// Sebastien Pouliot +// +// 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 index 00000000000..f177c17ef3a --- /dev/null +++ b/mcs/class/corlib/CommonCrypto/CommonCryptorGenerator.cs @@ -0,0 +1,104 @@ +// +// CommonCrypto code generator for symmetric block cipher algorithms +// +// Authors: +// Sebastien Pouliot +// +// 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 +// +// 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 index 00000000000..1b729e376bf --- /dev/null +++ b/mcs/class/corlib/CommonCrypto/CommonDigestGenerator.cs @@ -0,0 +1,167 @@ +// +// CommonCrypto code generator for digest algorithms +// +// Authors: +// Sebastien Pouliot +// +// 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 +// +// 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 +// +// 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 index 00000000000..5bdc69a215e --- /dev/null +++ b/mcs/class/corlib/CommonCrypto/CorlibExtras.cs @@ -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 index 00000000000..10ca6fad8f6 --- /dev/null +++ b/mcs/class/corlib/CommonCrypto/CryptorTransform.cs @@ -0,0 +1,60 @@ +// ICryptoTransform implementation on top of CommonCrypto and SymmetricTransform +// +// Authors: +// Sebastien Pouliot +// +// 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 index 00000000000..9ff7a5a8563 --- /dev/null +++ b/mcs/class/corlib/CommonCrypto/FastCryptorTransform.cs @@ -0,0 +1,348 @@ +// Fast, multi-block, ICryptoTransform implementation on top of CommonCrypto +// +// Authors: +// Sebastien Pouliot +// +// 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 index 00000000000..25e13794998 --- /dev/null +++ b/mcs/class/corlib/CommonCrypto/Makefile.include @@ -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 index 00000000000..1e5c4e2b29c --- /dev/null +++ b/mcs/class/corlib/CommonCrypto/RC4CommonCrypto.cs @@ -0,0 +1,212 @@ +// A CommonCrypto-based implementation of RC4(tm) +// +// Authors: +// Sebastien Pouliot +// +// (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 index 00000000000..3d528d33a7f --- /dev/null +++ b/mcs/class/corlib/CommonCrypto/RijndaelManaged.cs @@ -0,0 +1,119 @@ +// +// RijndaelManaged.cs: Use CommonCrypto AES when possible, +// fallback on RijndaelManagedTransform otherwise +// +// Authors: +// Sebastien Pouliot +// +// 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 index 00000000000..a112faf5570 --- /dev/null +++ b/mcs/class/corlib/CommonCrypto/SecRandom.cs @@ -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 index 00000000000..a7d13c8cb80 --- /dev/null +++ b/mcs/class/corlib/CommonCrypto/generator.cs @@ -0,0 +1,57 @@ +// +// CommonCrypto Code Generator +// +// Authors: +// Sebastien Pouliot +// +// 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 diff --git a/mcs/class/corlib/Makefile b/mcs/class/corlib/Makefile index 2540e236031..aff30966f5a 100644 --- a/mcs/class/corlib/Makefile +++ b/mcs/class/corlib/Makefile @@ -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 index 00000000000..72871935f28 --- /dev/null +++ b/mcs/class/corlib/monotouch_corlib.dll.exclude.sources @@ -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 diff --git a/mcs/class/corlib/monotouch_corlib.dll.sources b/mcs/class/corlib/monotouch_corlib.dll.sources index da77893bcc5..55b9d548f26 100644 --- a/mcs/class/corlib/monotouch_corlib.dll.sources +++ b/mcs/class/corlib/monotouch_corlib.dll.sources @@ -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 index 00000000000..53efeacceda --- /dev/null +++ b/mcs/class/corlib/monotouch_runtime_corlib.dll.exclude.sources @@ -0,0 +1 @@ +#include monotouch_corlib.dll.exclude.sources diff --git a/mcs/class/corlib/monotouch_runtime_corlib.dll.sources b/mcs/class/corlib/monotouch_runtime_corlib.dll.sources index da77893bcc5..55b9d548f26 100644 --- a/mcs/class/corlib/monotouch_runtime_corlib.dll.sources +++ b/mcs/class/corlib/monotouch_runtime_corlib.dll.sources @@ -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 index 00000000000..53efeacceda --- /dev/null +++ b/mcs/class/corlib/monotouch_tv_corlib.dll.exclude.sources @@ -0,0 +1 @@ +#include monotouch_corlib.dll.exclude.sources diff --git a/mcs/class/corlib/monotouch_tv_corlib.dll.sources b/mcs/class/corlib/monotouch_tv_corlib.dll.sources index da77893bcc5..55b9d548f26 100644 --- a/mcs/class/corlib/monotouch_tv_corlib.dll.sources +++ b/mcs/class/corlib/monotouch_tv_corlib.dll.sources @@ -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 index 00000000000..53efeacceda --- /dev/null +++ b/mcs/class/corlib/monotouch_tv_runtime_corlib.dll.exclude.sources @@ -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 index 00000000000..53efeacceda --- /dev/null +++ b/mcs/class/corlib/monotouch_watch_corlib.dll.exclude.sources @@ -0,0 +1 @@ +#include monotouch_corlib.dll.exclude.sources diff --git a/mcs/class/corlib/monotouch_watch_corlib.dll.sources b/mcs/class/corlib/monotouch_watch_corlib.dll.sources index da77893bcc5..55b9d548f26 100644 --- a/mcs/class/corlib/monotouch_watch_corlib.dll.sources +++ b/mcs/class/corlib/monotouch_watch_corlib.dll.sources @@ -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 index 00000000000..53efeacceda --- /dev/null +++ b/mcs/class/corlib/monotouch_watch_runtime_corlib.dll.exclude.sources @@ -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 index 00000000000..86bb4049f5e --- /dev/null +++ b/mcs/class/corlib/xammac_corlib.dll.exclude.sources @@ -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 diff --git a/mcs/class/corlib/xammac_corlib.dll.sources b/mcs/class/corlib/xammac_corlib.dll.sources index da77893bcc5..4d6428cc31b 100644 --- a/mcs/class/corlib/xammac_corlib.dll.sources +++ b/mcs/class/corlib/xammac_corlib.dll.sources @@ -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