/mcs/class/referencesource/System.IdentityModel/System/IdentityModel/SafeCryptHandles.cs

https://github.com/pruiz/mono · C# · 122 lines · 101 code · 13 blank · 8 comment · 11 complexity · 3045dfb2d9b1249e25837ad171e0d465 MD5 · raw file

  1. //-----------------------------------------------------------------------------
  2. // Copyright (c) Microsoft Corporation. All rights reserved.
  3. //-----------------------------------------------------------------------------
  4. namespace System.IdentityModel
  5. {
  6. using System.ComponentModel;
  7. using System.Runtime.InteropServices;
  8. using System.Runtime.CompilerServices;
  9. using System.Runtime.ConstrainedExecution;
  10. using System.Security.Cryptography;
  11. using System.ServiceModel.Diagnostics;
  12. using Microsoft.Win32.SafeHandles;
  13. class SafeProvHandle : SafeHandleZeroOrMinusOneIsInvalid
  14. {
  15. SafeProvHandle() : base(true) { }
  16. // 0 is an Invalid Handle
  17. SafeProvHandle(IntPtr handle)
  18. : base(true)
  19. {
  20. DiagnosticUtility.DebugAssert(handle == IntPtr.Zero, "SafeProvHandle constructor can only be called with IntPtr.Zero.");
  21. SetHandle(handle);
  22. }
  23. internal static SafeProvHandle InvalidHandle
  24. {
  25. get { return new SafeProvHandle(IntPtr.Zero); }
  26. }
  27. protected override bool ReleaseHandle()
  28. {
  29. // PreSharp Bug: Call 'Marshal.GetLastWin32Error' or 'Marshal.GetHRForLastWin32Error' before any other interop call.
  30. #pragma warning suppress 56523 // We are not interested in throwing an exception here if CloseHandle fails.
  31. return NativeMethods.CryptReleaseContext(handle, 0);
  32. }
  33. }
  34. class SafeKeyHandle : SafeHandleZeroOrMinusOneIsInvalid
  35. {
  36. SafeProvHandle provHandle = null;
  37. SafeKeyHandle() : base(true) { }
  38. // 0 is an Invalid Handle
  39. SafeKeyHandle(IntPtr handle)
  40. : base(true)
  41. {
  42. DiagnosticUtility.DebugAssert(handle == IntPtr.Zero, "SafeKeyHandle constructor can only be called with IntPtr.Zero.");
  43. SetHandle(handle);
  44. }
  45. internal static SafeKeyHandle InvalidHandle
  46. {
  47. get { return new SafeKeyHandle(IntPtr.Zero); }
  48. }
  49. protected override bool ReleaseHandle()
  50. {
  51. // PreSharp Bug: Call 'Marshal.GetLastWin32Error' or 'Marshal.GetHRForLastWin32Error' before any other interop call.
  52. #pragma warning suppress 56523 // We are not interested in throwing an exception here if CloseHandle fails.
  53. bool ret = NativeMethods.CryptDestroyKey(handle);
  54. if (this.provHandle != null)
  55. {
  56. this.provHandle.DangerousRelease();
  57. this.provHandle = null;
  58. }
  59. return ret;
  60. }
  61. internal static unsafe SafeKeyHandle SafeCryptImportKey(SafeProvHandle provHandle, void* pbDataPtr, int cbData)
  62. {
  63. bool b = false;
  64. int err = 0;
  65. SafeKeyHandle keyHandle = null;
  66. RuntimeHelpers.PrepareConstrainedRegions();
  67. try
  68. {
  69. provHandle.DangerousAddRef(ref b);
  70. }
  71. catch (Exception e)
  72. {
  73. if (System.Runtime.Fx.IsFatal(e))
  74. throw;
  75. if (b)
  76. {
  77. provHandle.DangerousRelease();
  78. b = false;
  79. }
  80. if (!(e is ObjectDisposedException))
  81. throw;
  82. }
  83. finally
  84. {
  85. if (b)
  86. {
  87. b = NativeMethods.CryptImportKey(provHandle, pbDataPtr, (uint)cbData, IntPtr.Zero, 0, out keyHandle);
  88. if (!b)
  89. {
  90. err = Marshal.GetLastWin32Error();
  91. provHandle.DangerousRelease();
  92. }
  93. else
  94. {
  95. // Take ownership of AddRef. Will Release at Close.
  96. keyHandle.provHandle = provHandle;
  97. }
  98. }
  99. }
  100. if (!b)
  101. {
  102. Utility.CloseInvalidOutSafeHandle(keyHandle);
  103. string reason = (err != 0) ? new Win32Exception(err).Message : String.Empty;
  104. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new CryptographicException(SR.GetString(SR.AESCryptImportKeyFailed, reason)));
  105. }
  106. return keyHandle;
  107. }
  108. }
  109. }