* roottypes.cs: Rename from tree.cs.
[mono.git] / mcs / class / System.Security / System.Security.Cryptography / ProtectedMemory.cs
1 //
2 // ProtectedMemory.cs: Protect (encrypt) memory without (user involved) key management
3 //
4 // Author:
5 //      Sebastien Pouliot  <sebastien@ximian.com>
6 //
7 // (C) 2003 Motus Technologies Inc. (http://www.motus.com)
8 // Copyright (C) 2004-2005 Novell, Inc (http://www.novell.com)
9 //
10 // Permission is hereby granted, free of charge, to any person obtaining
11 // a copy of this software and associated documentation files (the
12 // "Software"), to deal in the Software without restriction, including
13 // without limitation the rights to use, copy, modify, merge, publish,
14 // distribute, sublicense, and/or sell copies of the Software, and to
15 // permit persons to whom the Software is furnished to do so, subject to
16 // the following conditions:
17 // 
18 // The above copyright notice and this permission notice shall be
19 // included in all copies or substantial portions of the Software.
20 // 
21 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
22 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
23 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
24 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
25 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
26 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
27 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
28 //
29
30 #if NET_2_0
31
32 using System.Runtime.InteropServices;
33 using System.Security;
34 using System.Security.Permissions;
35
36 namespace System.Security.Cryptography {
37
38         // References:
39         // a.   Windows Data Protection
40         //      http://msdn.microsoft.com/library/en-us/dnsecure/html/windataprotection-dpapi.asp?frame=true
41
42         public sealed class ProtectedMemory {
43
44                 private ProtectedMemory ()
45                 {
46                 }
47
48                 [MonoTODO ("only supported on Windows 2000 SP3 and later")]\r
49 // FIXME        [DataProtectionPermission (SecurityAction.Demand, ProtectMemory = true)]\r
50                 public static void Protect (byte[] userData, MemoryProtectionScope scope) 
51                 {
52                         if (userData == null)
53                                 throw new ArgumentNullException ("userData");\r
54 \r
55                         Check (userData.Length, scope);\r
56                         try {\r
57                                 uint flags = (uint) scope;\r
58                                 uint length = (uint) userData.Length;\r
59 \r
60                                 switch (impl) {\r
61                                 case MemoryProtectionImplementation.Win32RtlEncryptMemory:\r
62                                         int err = RtlEncryptMemory (userData, length, flags);\r
63                                         if (err < 0) {\r
64                                                 string msg = Locale.GetText ("Error. NTSTATUS = {0}.", err);\r
65                                                 throw new CryptographicException (msg);\r
66                                         }\r
67                                         break;\r
68                                 case MemoryProtectionImplementation.Win32CryptoProtect:\r
69                                         bool result = CryptProtectMemory (userData, length, flags);\r
70                                         if (!result)\r
71                                                 throw new CryptographicException (Marshal.GetLastWin32Error ());\r
72                                         break;\r
73                                 default:\r
74                                         throw new PlatformNotSupportedException ();\r
75                                 }\r
76                         }\r
77                         catch {\r
78                                 // Windows 2000 before SP3 will throw\r
79                                 impl = MemoryProtectionImplementation.Unsupported;\r
80                                 throw new PlatformNotSupportedException ();\r
81                         }\r
82                 }\r
83 \r
84                 [MonoTODO ("only supported on Windows 2000 SP3 and later")]\r
85 // FIXME        [DataProtectionPermission (SecurityAction.Demand, UnprotectMemory = true)]\r
86                 public static void Unprotect (byte[] encryptedData, MemoryProtectionScope scope) 
87                 {
88                         if (encryptedData == null)
89                                 throw new ArgumentNullException ("encryptedData");\r
90 \r
91                         Check (encryptedData.Length, scope);\r
92                         try {\r
93                                 uint flags = (uint) scope;\r
94                                 uint length = (uint) encryptedData.Length;\r
95 \r
96                                 switch (impl) {\r
97                                 case MemoryProtectionImplementation.Win32RtlEncryptMemory:\r
98                                         int err = RtlDecryptMemory (encryptedData, length, flags);\r
99                                         if (err < 0) {\r
100                                                 string msg = Locale.GetText ("Error. NTSTATUS = {0}.", err);\r
101                                                 throw new CryptographicException (msg);\r
102                                         }\r
103                                         break;\r
104                                 case MemoryProtectionImplementation.Win32CryptoProtect:\r
105                                         bool result = CryptUnprotectMemory (encryptedData, length, flags);\r
106                                         if (!result)\r
107                                                 throw new CryptographicException (Marshal.GetLastWin32Error ());\r
108                                         break;\r
109                                 default:\r
110                                         throw new PlatformNotSupportedException ();\r
111                                 }\r
112                         }\r
113                         catch {\r
114                                 // Windows 2000 before SP3 will throw\r
115                                 impl = MemoryProtectionImplementation.Unsupported;\r
116                                 throw new PlatformNotSupportedException ();\r
117                         }\r
118                 }
119
120                 // private stuff\r
121 \r
122                 private const int BlockSize = 16;\r
123 \r
124                 enum MemoryProtectionImplementation {\r
125                         Unknown,\r
126                         Win32RtlEncryptMemory,\r
127                         Win32CryptoProtect,\r
128                         Unsupported = Int32.MinValue\r
129                 }\r
130 \r
131                 private static MemoryProtectionImplementation impl;\r
132 \r
133                 private static void Detect ()\r
134                 {\r
135                         OperatingSystem os = Environment.OSVersion;\r
136                         switch (os.Platform) {\r
137                         case PlatformID.Win32NT:\r
138                                 Version v = os.Version;\r
139                                 if (v.Major < 5) {\r
140                                         impl = MemoryProtectionImplementation.Unsupported;\r
141                                 } else if (v.Major == 5) {\r
142                                         if (v.Minor < 2) {\r
143                                                 // 2000 (5.0) Service Pack 3 and XP (5.1)\r
144                                                 impl = MemoryProtectionImplementation.Win32RtlEncryptMemory;\r
145                                         } else {\r
146                                                 impl = MemoryProtectionImplementation.Win32CryptoProtect;\r
147                                         }\r
148                                 } else {\r
149                                         // vista (6.0) and later\r
150                                         impl = MemoryProtectionImplementation.Win32CryptoProtect;\r
151                                 }\r
152                                 break;\r
153                         default:\r
154                                 impl = MemoryProtectionImplementation.Unsupported;\r
155                                 break;\r
156                         }\r
157                 }\r
158 \r
159                 private static void Check (int size, MemoryProtectionScope scope)
160                 {\r
161                         if (size % BlockSize != 0) {\r
162                                 string msg = Locale.GetText ("Not a multiple of {0} bytes.", BlockSize);\r
163                                 throw new CryptographicException (msg);\r
164                         }
165
166                         if ((scope < MemoryProtectionScope.SameProcess) || (scope > MemoryProtectionScope.SameLogon)) {
167                                 string msg = Locale.GetText ("Invalid enum value for '{0}'.", "MemoryProtectionScope");
168                                 throw new ArgumentException (msg, "scope");
169                         }\r
170 \r
171                         switch (impl) {\r
172                         case MemoryProtectionImplementation.Unknown:\r
173                                 Detect ();\r
174                                 break;\r
175                         case MemoryProtectionImplementation.Unsupported:\r
176                                 throw new PlatformNotSupportedException ();\r
177                         }
178                 }\r
179 \r
180                 // http://msdn.microsoft.com/library/en-us/dncode/html/secure06122003.asp\r
181                 // Summary: CryptProtectMemory and CryptUnprotectMemory exists only in Windows 2003 +\r
182                 // but they are available in advapi32.dll as RtlEncryptMemory (SystemFunction040) and\r
183                 // RtlDecryptMemory (SystemFunction041) since Windows 2000 SP 3. Sadly both can disappear\r
184                 // anytime with newer OS so we include support for Crypt[Unp|P]rotectMemory too.
185
186                 [SuppressUnmanagedCodeSecurity]
187                 [DllImport ("advapi32.dll", EntryPoint="SystemFunction040", SetLastError = true, CallingConvention = CallingConvention.StdCall, CharSet = CharSet.Auto)]\r
188                 private static extern int RtlEncryptMemory (byte[] pData, uint cbData, uint dwFlags);\r
189 \r
190                 [SuppressUnmanagedCodeSecurity]\r
191                 [DllImport ("advapi32.dll", EntryPoint = "SystemFunction041", SetLastError = true, CallingConvention = CallingConvention.StdCall, CharSet = CharSet.Auto)]\r
192                 private static extern int RtlDecryptMemory (byte[] pData, uint cbData, uint dwFlags);\r
193 \r
194                 [SuppressUnmanagedCodeSecurity]\r
195                 [DllImport ("crypt32.dll", SetLastError = true, CallingConvention = CallingConvention.StdCall, CharSet = CharSet.Auto)]\r
196                 private static extern bool CryptProtectMemory (byte[] pData, uint cbData, uint dwFlags);\r
197 \r
198                 [SuppressUnmanagedCodeSecurity]\r
199                 [DllImport ("crypt32.dll", SetLastError = true, CallingConvention = CallingConvention.StdCall, CharSet = CharSet.Auto)]\r
200                 private static extern bool CryptUnprotectMemory (byte[] pData, uint cbData, uint dwFlags);\r
201         } 
202 }
203
204 #endif