mscorlib(4.0.0.0) API with additions
SecureString.cs
1 using Microsoft.Win32;
7 
8 namespace System.Security
9 {
11  public sealed class SecureString : IDisposable
12  {
13  [SecurityCritical]
14  private SafeBSTRHandle m_buffer;
15 
16  private int m_length;
17 
18  private bool m_readOnly;
19 
20  private bool m_encrypted;
21 
22  private static bool supportedOnCurrentPlatform;
23 
24  private const int BlockSize = 8;
25 
26  private const int MaxLength = 65536;
27 
28  private const uint ProtectionScope = 0u;
29 
33  public int Length
34  {
35  [MethodImpl(MethodImplOptions.Synchronized)]
36  [SecuritySafeCritical]
37  get
38  {
39  EnsureNotDisposed();
40  return m_length;
41  }
42  }
43 
44  private int BufferLength
45  {
46  [SecurityCritical]
47  get
48  {
49  return m_buffer.Length;
50  }
51  }
52 
53  [SecuritySafeCritical]
54  static SecureString()
55  {
56  supportedOnCurrentPlatform = EncryptionSupported();
57  }
58 
59  [SecurityCritical]
60  private static bool EncryptionSupported()
61  {
62  bool result = true;
63  try
64  {
65  Win32Native.SystemFunction041(SafeBSTRHandle.Allocate(null, 16u), 16u, 0u);
66  return result;
67  }
68  catch (EntryPointNotFoundException)
69  {
70  return false;
71  }
72  }
73 
74  [SecurityCritical]
75  internal SecureString(SecureString str)
76  {
77  AllocateBuffer(str.BufferLength);
78  SafeBSTRHandle.Copy(str.m_buffer, m_buffer);
79  m_length = str.m_length;
80  m_encrypted = str.m_encrypted;
81  }
82 
86  [SecuritySafeCritical]
87  public SecureString()
88  {
89  CheckSupportedOnCurrentPlatform();
90  AllocateBuffer(8);
91  m_length = 0;
92  }
93 
94  [SecurityCritical]
95  [HandleProcessCorruptedStateExceptions]
96  private unsafe void InitializeSecureString(char* value, int length)
97  {
98  CheckSupportedOnCurrentPlatform();
99  AllocateBuffer(length);
100  m_length = length;
101  byte* pointer = null;
103  try
104  {
105  m_buffer.AcquirePointer(ref pointer);
106  Buffer.Memcpy(pointer, (byte*)value, length * 2);
107  }
108  catch (Exception)
109  {
110  ProtectMemory();
111  throw;
112  }
113  finally
114  {
115  if (pointer != null)
116  {
117  m_buffer.ReleasePointer();
118  }
119  }
120  ProtectMemory();
121  }
122 
132  [SecurityCritical]
133  [CLSCompliant(false)]
134  public unsafe SecureString(char* value, int length)
135  {
136  if (value == null)
137  {
138  throw new ArgumentNullException("value");
139  }
140  if (length < 0)
141  {
142  throw new ArgumentOutOfRangeException("length", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
143  }
144  if (length > 65536)
145  {
146  throw new ArgumentOutOfRangeException("length", Environment.GetResourceString("ArgumentOutOfRange_Length"));
147  }
148  InitializeSecureString(value, length);
149  }
150 
157  [MethodImpl(MethodImplOptions.Synchronized)]
158  [SecuritySafeCritical]
159  [HandleProcessCorruptedStateExceptions]
160  public void AppendChar(char c)
161  {
162  EnsureNotDisposed();
163  EnsureNotReadOnly();
164  EnsureCapacity(m_length + 1);
166  try
167  {
168  UnProtectMemory();
169  m_buffer.Write((uint)(m_length * 2), c);
170  m_length++;
171  }
172  catch (Exception)
173  {
174  ProtectMemory();
175  throw;
176  }
177  finally
178  {
179  ProtectMemory();
180  }
181  }
182 
186  [MethodImpl(MethodImplOptions.Synchronized)]
187  [SecuritySafeCritical]
188  public void Clear()
189  {
190  EnsureNotDisposed();
191  EnsureNotReadOnly();
192  m_length = 0;
193  m_buffer.ClearBuffer();
194  m_encrypted = false;
195  }
196 
201  [MethodImpl(MethodImplOptions.Synchronized)]
202  [SecuritySafeCritical]
204  {
205  EnsureNotDisposed();
206  return new SecureString(this);
207  }
208 
210  [MethodImpl(MethodImplOptions.Synchronized)]
211  [SecuritySafeCritical]
212  public void Dispose()
213  {
214  if (m_buffer != null && !m_buffer.IsInvalid)
215  {
216  m_buffer.Close();
217  m_buffer = null;
218  }
219  }
220 
229  [MethodImpl(MethodImplOptions.Synchronized)]
230  [SecuritySafeCritical]
231  [HandleProcessCorruptedStateExceptions]
232  public unsafe void InsertAt(int index, char c)
233  {
234  if (index < 0 || index > m_length)
235  {
236  throw new ArgumentOutOfRangeException("index", Environment.GetResourceString("ArgumentOutOfRange_IndexString"));
237  }
238  EnsureNotDisposed();
239  EnsureNotReadOnly();
240  EnsureCapacity(m_length + 1);
241  byte* pointer = null;
243  try
244  {
245  UnProtectMemory();
246  m_buffer.AcquirePointer(ref pointer);
247  char* ptr = (char*)pointer;
248  for (int num = m_length; num > index; num--)
249  {
250  ptr[num] = ptr[num - 1];
251  }
252  ptr[index] = c;
253  m_length++;
254  }
255  catch (Exception)
256  {
257  ProtectMemory();
258  throw;
259  }
260  finally
261  {
262  ProtectMemory();
263  if (pointer != null)
264  {
265  m_buffer.ReleasePointer();
266  }
267  }
268  }
269 
274  [MethodImpl(MethodImplOptions.Synchronized)]
275  [SecuritySafeCritical]
276  public bool IsReadOnly()
277  {
278  EnsureNotDisposed();
279  return m_readOnly;
280  }
281 
284  [MethodImpl(MethodImplOptions.Synchronized)]
285  [SecuritySafeCritical]
286  public void MakeReadOnly()
287  {
288  EnsureNotDisposed();
289  m_readOnly = true;
290  }
291 
299  [MethodImpl(MethodImplOptions.Synchronized)]
300  [SecuritySafeCritical]
301  [HandleProcessCorruptedStateExceptions]
302  public unsafe void RemoveAt(int index)
303  {
304  EnsureNotDisposed();
305  EnsureNotReadOnly();
306  if (index < 0 || index >= m_length)
307  {
308  throw new ArgumentOutOfRangeException("index", Environment.GetResourceString("ArgumentOutOfRange_IndexString"));
309  }
310  byte* pointer = null;
312  try
313  {
314  UnProtectMemory();
315  m_buffer.AcquirePointer(ref pointer);
316  char* ptr = (char*)pointer;
317  for (int i = index; i < m_length - 1; i++)
318  {
319  ptr[i] = ptr[i + 1];
320  }
321  ptr[--m_length] = '\0';
322  }
323  catch (Exception)
324  {
325  ProtectMemory();
326  throw;
327  }
328  finally
329  {
330  ProtectMemory();
331  if (pointer != null)
332  {
333  m_buffer.ReleasePointer();
334  }
335  }
336  }
337 
346  [MethodImpl(MethodImplOptions.Synchronized)]
347  [SecuritySafeCritical]
348  [HandleProcessCorruptedStateExceptions]
349  public void SetAt(int index, char c)
350  {
351  if (index < 0 || index >= m_length)
352  {
353  throw new ArgumentOutOfRangeException("index", Environment.GetResourceString("ArgumentOutOfRange_IndexString"));
354  }
355  EnsureNotDisposed();
356  EnsureNotReadOnly();
358  try
359  {
360  UnProtectMemory();
361  m_buffer.Write((uint)(index * 2), c);
362  }
363  catch (Exception)
364  {
365  ProtectMemory();
366  throw;
367  }
368  finally
369  {
370  ProtectMemory();
371  }
372  }
373 
374  [SecurityCritical]
375  [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
376  private void AllocateBuffer(int size)
377  {
378  uint alignedSize = GetAlignedSize(size);
379  m_buffer = SafeBSTRHandle.Allocate(null, alignedSize);
380  if (m_buffer.IsInvalid)
381  {
382  throw new OutOfMemoryException();
383  }
384  }
385 
386  private void CheckSupportedOnCurrentPlatform()
387  {
388  if (!supportedOnCurrentPlatform)
389  {
390  throw new NotSupportedException(Environment.GetResourceString("Arg_PlatformSecureString"));
391  }
392  }
393 
394  [SecurityCritical]
395  private void EnsureCapacity(int capacity)
396  {
397  if (capacity > 65536)
398  {
399  throw new ArgumentOutOfRangeException("capacity", Environment.GetResourceString("ArgumentOutOfRange_Capacity"));
400  }
401  if (capacity > m_buffer.Length)
402  {
403  SafeBSTRHandle safeBSTRHandle = SafeBSTRHandle.Allocate(null, GetAlignedSize(capacity));
404  if (safeBSTRHandle.IsInvalid)
405  {
406  throw new OutOfMemoryException();
407  }
408  SafeBSTRHandle.Copy(m_buffer, safeBSTRHandle);
409  m_buffer.Close();
410  m_buffer = safeBSTRHandle;
411  }
412  }
413 
414  [SecurityCritical]
415  private void EnsureNotDisposed()
416  {
417  if (m_buffer == null)
418  {
419  throw new ObjectDisposedException(null);
420  }
421  }
422 
423  private void EnsureNotReadOnly()
424  {
425  if (m_readOnly)
426  {
427  throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_ReadOnly"));
428  }
429  }
430 
431  [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
432  private static uint GetAlignedSize(int size)
433  {
434  uint num = (uint)size / 8u * 8;
435  if (size % 8 != 0 || size == 0)
436  {
437  num += 8;
438  }
439  return num;
440  }
441 
442  [SecurityCritical]
443  private unsafe int GetAnsiByteCount()
444  {
445  uint flags = 1024u;
446  uint num = 63u;
447  byte* pointer = null;
449  try
450  {
451  m_buffer.AcquirePointer(ref pointer);
452  return Win32Native.WideCharToMultiByte(0u, flags, (char*)pointer, m_length, null, 0, IntPtr.Zero, new IntPtr(&num));
453  }
454  finally
455  {
456  if (pointer != null)
457  {
458  m_buffer.ReleasePointer();
459  }
460  }
461  }
462 
463  [SecurityCritical]
464  private unsafe void GetAnsiBytes(byte* ansiStrPtr, int byteCount)
465  {
466  uint flags = 1024u;
467  uint num = 63u;
468  byte* pointer = null;
470  try
471  {
472  m_buffer.AcquirePointer(ref pointer);
473  Win32Native.WideCharToMultiByte(0u, flags, (char*)pointer, m_length, ansiStrPtr, byteCount - 1, IntPtr.Zero, new IntPtr(&num));
474  *(ansiStrPtr + byteCount - 1) = 0;
475  }
476  finally
477  {
478  if (pointer != null)
479  {
480  m_buffer.ReleasePointer();
481  }
482  }
483  }
484 
485  [SecurityCritical]
486  [ReliabilityContract(Consistency.MayCorruptInstance, Cer.MayFail)]
487  private void ProtectMemory()
488  {
489  if (m_length != 0 && !m_encrypted)
490  {
492  try
493  {
494  }
495  finally
496  {
497  int num = Win32Native.SystemFunction040(m_buffer, (uint)(m_buffer.Length * 2), 0u);
498  if (num < 0)
499  {
500  throw new CryptographicException(Win32Native.LsaNtStatusToWinError(num));
501  }
502  m_encrypted = true;
503  }
504  }
505  }
506 
507  [MethodImpl(MethodImplOptions.Synchronized)]
508  [SecurityCritical]
509  [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
510  [HandleProcessCorruptedStateExceptions]
511  internal unsafe IntPtr ToBSTR()
512  {
513  EnsureNotDisposed();
514  int length = m_length;
515  IntPtr intPtr = IntPtr.Zero;
516  IntPtr intPtr2 = IntPtr.Zero;
517  byte* pointer = null;
519  try
520  {
522  try
523  {
524  }
525  finally
526  {
527  intPtr = Win32Native.SysAllocStringLen(null, length);
528  }
529  if (intPtr == IntPtr.Zero)
530  {
531  throw new OutOfMemoryException();
532  }
533  UnProtectMemory();
534  m_buffer.AcquirePointer(ref pointer);
535  Buffer.Memcpy((byte*)intPtr.ToPointer(), pointer, length * 2);
536  intPtr2 = intPtr;
537  return intPtr2;
538  }
539  catch (Exception)
540  {
541  ProtectMemory();
542  throw;
543  }
544  finally
545  {
546  ProtectMemory();
547  if (intPtr2 == IntPtr.Zero && intPtr != IntPtr.Zero)
548  {
549  Win32Native.ZeroMemory(intPtr, (UIntPtr)(ulong)(length * 2));
550  Win32Native.SysFreeString(intPtr);
551  }
552  if (pointer != null)
553  {
554  m_buffer.ReleasePointer();
555  }
556  }
557  }
558 
559  [MethodImpl(MethodImplOptions.Synchronized)]
560  [SecurityCritical]
561  [HandleProcessCorruptedStateExceptions]
562  internal unsafe IntPtr ToUniStr(bool allocateFromHeap)
563  {
564  EnsureNotDisposed();
565  int length = m_length;
566  IntPtr intPtr = IntPtr.Zero;
567  IntPtr intPtr2 = IntPtr.Zero;
568  byte* pointer = null;
570  try
571  {
573  try
574  {
575  }
576  finally
577  {
578  intPtr = ((!allocateFromHeap) ? Marshal.AllocCoTaskMem((length + 1) * 2) : Marshal.AllocHGlobal((length + 1) * 2));
579  }
580  if (intPtr == IntPtr.Zero)
581  {
582  throw new OutOfMemoryException();
583  }
584  UnProtectMemory();
585  m_buffer.AcquirePointer(ref pointer);
586  Buffer.Memcpy((byte*)intPtr.ToPointer(), pointer, length * 2);
587  char* ptr = (char*)intPtr.ToPointer();
588  ptr[length] = '\0';
589  intPtr2 = intPtr;
590  return intPtr2;
591  }
592  catch (Exception)
593  {
594  ProtectMemory();
595  throw;
596  }
597  finally
598  {
599  ProtectMemory();
600  if (intPtr2 == IntPtr.Zero && intPtr != IntPtr.Zero)
601  {
602  Win32Native.ZeroMemory(intPtr, (UIntPtr)(ulong)(length * 2));
603  if (allocateFromHeap)
604  {
605  Marshal.FreeHGlobal(intPtr);
606  }
607  else
608  {
609  Marshal.FreeCoTaskMem(intPtr);
610  }
611  }
612  if (pointer != null)
613  {
614  m_buffer.ReleasePointer();
615  }
616  }
617  }
618 
619  [MethodImpl(MethodImplOptions.Synchronized)]
620  [SecurityCritical]
621  [HandleProcessCorruptedStateExceptions]
622  internal unsafe IntPtr ToAnsiStr(bool allocateFromHeap)
623  {
624  EnsureNotDisposed();
625  IntPtr intPtr = IntPtr.Zero;
626  IntPtr intPtr2 = IntPtr.Zero;
627  int num = 0;
629  try
630  {
631  UnProtectMemory();
632  num = GetAnsiByteCount() + 1;
634  try
635  {
636  }
637  finally
638  {
639  intPtr = ((!allocateFromHeap) ? Marshal.AllocCoTaskMem(num) : Marshal.AllocHGlobal(num));
640  }
641  if (intPtr == IntPtr.Zero)
642  {
643  throw new OutOfMemoryException();
644  }
645  GetAnsiBytes((byte*)intPtr.ToPointer(), num);
646  intPtr2 = intPtr;
647  return intPtr2;
648  }
649  catch (Exception)
650  {
651  ProtectMemory();
652  throw;
653  }
654  finally
655  {
656  ProtectMemory();
657  if (intPtr2 == IntPtr.Zero && intPtr != IntPtr.Zero)
658  {
659  Win32Native.ZeroMemory(intPtr, (UIntPtr)(ulong)num);
660  if (allocateFromHeap)
661  {
662  Marshal.FreeHGlobal(intPtr);
663  }
664  else
665  {
666  Marshal.FreeCoTaskMem(intPtr);
667  }
668  }
669  }
670  }
671 
672  [SecurityCritical]
673  [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
674  private void UnProtectMemory()
675  {
676  if (m_length != 0)
677  {
679  try
680  {
681  }
682  finally
683  {
684  if (m_encrypted)
685  {
686  int num = Win32Native.SystemFunction041(m_buffer, (uint)(m_buffer.Length * 2), 0u);
687  if (num < 0)
688  {
689  throw new CryptographicException(Win32Native.LsaNtStatusToWinError(num));
690  }
691  m_encrypted = false;
692  }
693  }
694  }
695  }
696  }
697 }
The exception that is thrown when an error occurs during a cryptographic operation.
bool IsReadOnly()
Indicates whether this secure string is marked read-only.
unsafe SecureString(char *value, int length)
Initializes a new instance of the T:System.Security.SecureString class from a subarray of T:System....
The exception that is thrown when a null reference (Nothing in Visual Basic) is passed to a method th...
void SetAt(int index, char c)
Replaces the existing character at the specified index position with another character.
static void FreeHGlobal(IntPtr hglobal)
Frees memory previously allocated from the unmanaged memory of the process.
Definition: Marshal.cs:1458
static void FreeCoTaskMem(IntPtr ptr)
Frees a block of memory allocated by the unmanaged COM task memory allocator.
Definition: Marshal.cs:2147
Provides a mechanism for releasing unmanaged resources.To browse the .NET Framework source code for t...
Definition: IDisposable.cs:8
Definition: __Canon.cs:3
The exception that is thrown when the value of an argument is outside the allowable range of values a...
SecureString Copy()
Creates a copy of the current secure string.
Cer
Specifies a method's behavior when called within a constrained execution region.
Definition: Cer.cs:5
void AppendChar(char c)
Appends a character to the end of the current secure string.
Provides information about, and means to manipulate, the current environment and platform....
Definition: Environment.cs:21
unsafe void InsertAt(int index, char c)
Inserts a character in this secure string at the specified index position.
static IntPtr AllocCoTaskMem(int cb)
Allocates a block of memory of specified size from the COM task memory allocator.
Definition: Marshal.cs:2068
Represents text that should be kept confidential, such as by deleting it from computer memory when no...
Definition: SecureString.cs:11
static void PrepareConstrainedRegions()
Designates a body of code as a constrained execution region (CER).
SecureString()
Initializes a new instance of the T:System.Security.SecureString class.
Definition: SecureString.cs:87
The exception that is thrown when there is not enough memory to continue the execution of a program.
Provides a collection of methods for allocating unmanaged memory, copying unmanaged memory blocks,...
Definition: Marshal.cs:15
MethodImplOptions
Defines the details of how a method is implemented.
void Clear()
Deletes the value of the current secure string.
unsafe void RemoveAt(int index)
Removes the character at the specified index position from this secure string.
int Length
Gets the number of characters in the current secure string.
Definition: SecureString.cs:34
Represents errors that occur during application execution.To browse the .NET Framework source code fo...
Definition: Exception.cs:22
void Dispose()
Releases all resources used by the current T:System.Security.SecureString object.
static IntPtr AllocHGlobal(IntPtr cb)
Allocates memory from the unmanaged memory of the process by using the pointer to the specified numbe...
Definition: Marshal.cs:1432
Manipulates arrays of primitive types.
Definition: Buffer.cs:11
Consistency
Specifies a reliability contract.
Definition: Consistency.cs:5
void MakeReadOnly()
Makes the text value of this secure string read-only.
Provides a set of static methods and properties that provide support for compilers....