private ArrayList _list;
public CryptographicAttributeObjectCollection ()
- {
+ {\r
_list = new ArrayList ();
}
public CryptographicAttributeObjectCollection (CryptographicAttributeObject attribute)
: this ()
- {
+ {\r
_list.Add (attribute);
}
}
public object SyncRoot {
- get { return _list.SyncRoot; }
+ get { return this; }
}
// methods
public int Add (AsnEncodedData asnEncodedData)
{
if (asnEncodedData == null)
- throw new ArgumentNullException ("asnEncodedData");
-
- return _list.Add (asnEncodedData);
+ throw new ArgumentNullException ("asnEncodedData");\r
+\r
+ AsnEncodedDataCollection coll = new AsnEncodedDataCollection (asnEncodedData);\r
+ return Add (new CryptographicAttributeObject (asnEncodedData.Oid, coll));
}
public int Add (CryptographicAttributeObject attribute)
{
if (attribute == null)
- throw new ArgumentNullException ("attribute");
-
- return _list.Add (attribute);
+ throw new ArgumentNullException ("attribute");\r
+\r
+ int existing = -1;\r
+ string oid = attribute.Oid.Value;\r
+ for (int i=0; i < _list.Count; i++) {\r
+ if ((_list[i] as CryptographicAttributeObject).Oid.Value == oid) {\r
+ existing = i;\r
+ break;\r
+ }\r
+ }\r
+ if (existing >= 0) {\r
+ CryptographicAttributeObject cao = this[existing];\r
+ foreach (AsnEncodedData value in attribute.Values) {\r
+ cao.Values.Add (value);\r
+ }\r
+ return existing;\r
+ } else {\r
+ return _list.Add (attribute);\r
+ }
}
public void CopyTo (CryptographicAttributeObject[] array, int index)
}
public void Remove (CryptographicAttributeObject attribute)
- {
+ {\r
+ if (attribute == null)\r
+ throw new ArgumentNullException ("attribute");\r
+\r
_list.Remove (attribute);
}
}
//
// ProtectedData.cs: Protect (encrypt) data without (user involved) key management
//
-// Author:
-// Sebastien Pouliot (spouliot@motus.com)
+// Author:\r
+// Sebastien Pouliot <sebastien@ximian.com>\r
//
-// (C) 2003 Motus Technologies Inc. (http://www.motus.com)
-// Copyright (C) 2004 Novell, Inc (http://www.novell.com)
+// (C) 2003 Motus Technologies Inc. (http://www.motus.com)\r
+// Copyright (C) 2004-2005 Novell, Inc (http://www.novell.com)\r
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
-#if NET_2_0
+#if NET_2_0\r
+\r
+using System.Runtime.InteropServices;\r
+using System.Security.Permissions;
-using System;
+using Mono.Security.Cryptography;
namespace System.Security.Cryptography {
{
}
- // FIXME: interop could be important under windows - if one application protect some data using
- // mono and another one unprotects it using ms.net
-
- [MonoTODO ("interop with MS implementation ?")]
+ [MonoTODO ("not (yet) supported on Windows")]\r
+// FIXME [DataProtectionPermission (SecurityAction.Demand, ProtectData = true)]\r
public static byte[] Protect (byte[] userData, byte[] optionalEntropy, DataProtectionScope scope)
{
if (userData == null)
throw new ArgumentNullException ("userData");
- // on Windows this is supported only under 2000 and later OS
- throw new PlatformNotSupportedException ();
- }
-
- [MonoTODO ("interop with MS implementation ?")]
+ // on Windows this is supported only under 2000 and later OS\r
+ Check (scope);\r
+\r
+ switch (impl) {\r
+ case DataProtectionImplementation.ManagedProtection:\r
+ try {\r
+ return ManagedProtection.Protect (userData, optionalEntropy, scope);\r
+ }\r
+ catch (Exception e) {\r
+ string msg = Locale.GetText ("Data protection failed.");\r
+ throw new CryptographicException (msg, e);\r
+ }\r
+ case DataProtectionImplementation.Win32CryptoProtect:\r
+ default:\r
+ throw new PlatformNotSupportedException ();\r
+ }\r
+ }\r
+\r
+ [MonoTODO ("not (yet) supported on Windows")]\r
+// FIXME [DataProtectionPermission (SecurityAction.Demand, UnprotectData = true)]\r
public static byte[] Unprotect (byte[] encryptedData, byte[] optionalEntropy, DataProtectionScope scope)
{
if (encryptedData == null)
throw new ArgumentNullException ("encryptedData");
- // on Windows this is supported only under 2000 and later OS
- throw new PlatformNotSupportedException ();
+ // on Windows this is supported only under 2000 and later OS\r
+ Check (scope);\r
+\r
+ switch (impl) {\r
+ case DataProtectionImplementation.ManagedProtection:\r
+ try {\r
+ return ManagedProtection.Unprotect (encryptedData, optionalEntropy, scope);\r
+ }\r
+ catch (Exception e) {\r
+ string msg = Locale.GetText ("Data unprotection failed.");\r
+ throw new CryptographicException (msg, e);\r
+ }\r
+ case DataProtectionImplementation.Win32CryptoProtect:\r
+ default:\r
+ throw new PlatformNotSupportedException ();\r
+ }\r
}
- }
+
+ // private stuff\r
+\r
+ enum DataProtectionImplementation {\r
+ Unknown,\r
+ Win32CryptoProtect,\r
+ ManagedProtection,\r
+ Unsupported = Int32.MinValue\r
+ }\r
+\r
+ private static DataProtectionImplementation impl;\r
+\r
+ private static void Detect ()\r
+ {\r
+ OperatingSystem os = Environment.OSVersion;\r
+ switch (os.Platform) {\r
+ case PlatformID.Win32NT:\r
+ Version v = os.Version;\r
+ if (v.Major < 5) {\r
+ impl = DataProtectionImplementation.Unsupported;\r
+ } else {\r
+ // Windows 2000 (5.0) and later\r
+ impl = DataProtectionImplementation.Win32CryptoProtect;\r
+ }\r
+ break;\r
+ case PlatformID.Unix:\r
+ impl = DataProtectionImplementation.ManagedProtection;\r
+ break;\r
+ default:\r
+ impl = DataProtectionImplementation.Unsupported;\r
+ break;\r
+ }\r
+ }\r
+\r
+ private static void Check (DataProtectionScope scope)\r
+ {\r
+ if ((scope < DataProtectionScope.CurrentUser) || (scope > DataProtectionScope.LocalMachine)) {\r
+ string msg = Locale.GetText ("Invalid enum value '{0}' for '{1}'.", \r
+ scope, "DataProtectionScope");\r
+ throw new ArgumentException (msg, "scope");\r
+ }\r
+\r
+ switch (impl) {\r
+ case DataProtectionImplementation.Unknown:\r
+ Detect ();\r
+ break;\r
+ case DataProtectionImplementation.Unsupported:\r
+ throw new PlatformNotSupportedException ();\r
+ }\r
+ }\r
+ }
}
#endif
// ProtectedMemory.cs: Protect (encrypt) memory without (user involved) key management
//
// Author:
-// Sebastien Pouliot (spouliot@motus.com)
+// Sebastien Pouliot <sebastien@ximian.com>
//
// (C) 2003 Motus Technologies Inc. (http://www.motus.com)
-// Copyright (C) 2004 Novell, Inc (http://www.novell.com)
+// Copyright (C) 2004-2005 Novell, Inc (http://www.novell.com)
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
#if NET_2_0
-using System;
+using System.Runtime.InteropServices;
+using System.Security;
+using System.Security.Permissions;
namespace System.Security.Cryptography {
{
}
- [MonoTODO]
+ [MonoTODO ("only supported on Windows 2000 SP3 and later")]\r
+// FIXME [DataProtectionPermission (SecurityAction.Demand, ProtectMemory = true)]\r
public static void Protect (byte[] userData, MemoryProtectionScope scope)
{
if (userData == null)
- throw new ArgumentNullException ("userData");
- if (userData.Length % 16 != 0)
- throw new CryptographicException ("not a multiple of 16 bytes");
-
- // on Windows this is supported only under XP and later OS
- throw new PlatformNotSupportedException ();
- }
-
- [MonoTODO]
+ throw new ArgumentNullException ("userData");\r
+\r
+ Check (userData.Length, scope);\r
+ try {\r
+ uint flags = (uint) scope;\r
+ uint length = (uint) userData.Length;\r
+\r
+ switch (impl) {\r
+ case MemoryProtectionImplementation.Win32RtlEncryptMemory:\r
+ int err = RtlEncryptMemory (userData, length, flags);\r
+ if (err < 0) {\r
+ string msg = Locale.GetText ("Error. NTSTATUS = {0}.", err);\r
+ throw new CryptographicException (msg);\r
+ }\r
+ break;\r
+ case MemoryProtectionImplementation.Win32CryptoProtect:\r
+ bool result = CryptProtectMemory (userData, length, flags);\r
+ if (!result)\r
+ throw new CryptographicException (Marshal.GetLastWin32Error ());\r
+ break;\r
+ default:\r
+ throw new PlatformNotSupportedException ();\r
+ }\r
+ }\r
+ catch {\r
+ // Windows 2000 before SP3 will throw\r
+ impl = MemoryProtectionImplementation.Unsupported;\r
+ throw new PlatformNotSupportedException ();\r
+ }\r
+ }\r
+\r
+ [MonoTODO ("only supported on Windows 2000 SP3 and later")]\r
+// FIXME [DataProtectionPermission (SecurityAction.Demand, UnprotectMemory = true)]\r
public static void Unprotect (byte[] encryptedData, MemoryProtectionScope scope)
{
if (encryptedData == null)
- throw new ArgumentNullException ("encryptedData");
- if (encryptedData.Length % 16 != 0)
- throw new CryptographicException ("not a multiple of 16 bytes");
-
- // on Windows this is supported only under XP and later OS
- throw new PlatformNotSupportedException ();
+ throw new ArgumentNullException ("encryptedData");\r
+\r
+ Check (encryptedData.Length, scope);\r
+ try {\r
+ uint flags = (uint) scope;\r
+ uint length = (uint) encryptedData.Length;\r
+\r
+ switch (impl) {\r
+ case MemoryProtectionImplementation.Win32RtlEncryptMemory:\r
+ int err = RtlDecryptMemory (encryptedData, length, flags);\r
+ if (err < 0) {\r
+ string msg = Locale.GetText ("Error. NTSTATUS = {0}.", err);\r
+ throw new CryptographicException (msg);\r
+ }\r
+ break;\r
+ case MemoryProtectionImplementation.Win32CryptoProtect:\r
+ bool result = CryptUnprotectMemory (encryptedData, length, flags);\r
+ if (!result)\r
+ throw new CryptographicException (Marshal.GetLastWin32Error ());\r
+ break;\r
+ default:\r
+ throw new PlatformNotSupportedException ();\r
+ }\r
+ }\r
+ catch {\r
+ // Windows 2000 before SP3 will throw\r
+ impl = MemoryProtectionImplementation.Unsupported;\r
+ throw new PlatformNotSupportedException ();\r
+ }\r
}
+
+ // private stuff\r
+\r
+ private const int BlockSize = 16;\r
+\r
+ enum MemoryProtectionImplementation {\r
+ Unknown,\r
+ Win32RtlEncryptMemory,\r
+ Win32CryptoProtect,\r
+ Unsupported = Int32.MinValue\r
+ }\r
+\r
+ private static MemoryProtectionImplementation impl;\r
+\r
+ private static void Detect ()\r
+ {\r
+ OperatingSystem os = Environment.OSVersion;\r
+ switch (os.Platform) {\r
+ case PlatformID.Win32NT:\r
+ Version v = os.Version;\r
+ if (v.Major < 5) {\r
+ impl = MemoryProtectionImplementation.Unsupported;\r
+ } else if (v.Major == 5) {\r
+ if (v.Minor < 2) {\r
+ // 2000 (5.0) Service Pack 3 and XP (5.1)\r
+ impl = MemoryProtectionImplementation.Win32RtlEncryptMemory;\r
+ } else {\r
+ impl = MemoryProtectionImplementation.Win32CryptoProtect;\r
+ }\r
+ } else {\r
+ // vista (6.0) and later\r
+ impl = MemoryProtectionImplementation.Win32CryptoProtect;\r
+ }\r
+ break;\r
+ default:\r
+ impl = MemoryProtectionImplementation.Unsupported;\r
+ break;\r
+ }\r
+ }\r
+\r
+ private static void Check (int size, MemoryProtectionScope scope)
+ {\r
+ if (size % BlockSize != 0) {\r
+ string msg = Locale.GetText ("Not a multiple of {0} bytes.", BlockSize);\r
+ throw new CryptographicException (msg);\r
+ }
+
+ if ((scope < MemoryProtectionScope.SameProcess) || (scope > MemoryProtectionScope.SameLogon)) {
+ string msg = Locale.GetText ("Invalid enum value for '{0}'.", "MemoryProtectionScope");
+ throw new ArgumentException (msg, "scope");
+ }\r
+\r
+ switch (impl) {\r
+ case MemoryProtectionImplementation.Unknown:\r
+ Detect ();\r
+ break;\r
+ case MemoryProtectionImplementation.Unsupported:\r
+ throw new PlatformNotSupportedException ();\r
+ }
+ }\r
+\r
+ // http://msdn.microsoft.com/library/en-us/dncode/html/secure06122003.asp\r
+ // Summary: CryptProtectMemory and CryptUnprotectMemory exists only in Windows 2003 +\r
+ // but they are available in advapi32.dll as RtlEncryptMemory (SystemFunction040) and\r
+ // RtlDecryptMemory (SystemFunction041) since Windows 2000 SP 3. Sadly both can disappear\r
+ // anytime with newer OS so we include support for Crypt[Unp|P]rotectMemory too.
+
+ [SuppressUnmanagedCodeSecurity]
+ [DllImport ("advapi32.dll", EntryPoint="SystemFunction040", SetLastError = true, CallingConvention = CallingConvention.StdCall, CharSet = CharSet.Auto)]\r
+ private static extern int RtlEncryptMemory (byte[] pData, uint cbData, uint dwFlags);\r
+\r
+ [SuppressUnmanagedCodeSecurity]\r
+ [DllImport ("advapi32.dll", EntryPoint = "SystemFunction041", SetLastError = true, CallingConvention = CallingConvention.StdCall, CharSet = CharSet.Auto)]\r
+ private static extern int RtlDecryptMemory (byte[] pData, uint cbData, uint dwFlags);\r
+\r
+ [SuppressUnmanagedCodeSecurity]\r
+ [DllImport ("crypt32.dll", SetLastError = true, CallingConvention = CallingConvention.StdCall, CharSet = CharSet.Auto)]\r
+ private static extern bool CryptProtectMemory (byte[] pData, uint cbData, uint dwFlags);\r
+\r
+ [SuppressUnmanagedCodeSecurity]\r
+ [DllImport ("crypt32.dll", SetLastError = true, CallingConvention = CallingConvention.StdCall, CharSet = CharSet.Auto)]\r
+ private static extern bool CryptUnprotectMemory (byte[] pData, uint cbData, uint dwFlags);\r
}
}