private static void AssignFriendlyNameToContext(IntPtr context, string value) { if (string.IsNullOrWhiteSpace(value)) return; var dataPointer = IntPtr.Zero; try { using (var data = new NativeMethods.CryptAttributeBlob { data = Marshal.StringToHGlobalUni(value), dataSize = Encoding.Unicode.GetByteCount(value) }) { dataPointer = Marshal.AllocHGlobal(Marshal.SizeOf(data)); Marshal.StructureToPtr(data, dataPointer, false); if (NativeMethods.CertSetCertificateContextProperty( context, NativeMethods.CertFriendlyNamePropId, 0, dataPointer)) return; var issue = new Win32Exception(Marshal.GetLastWin32Error()); Log.WarnFormat("Could not set friendly name for certificate: {0}", issue.Message); } } finally { if (dataPointer != IntPtr.Zero) Marshal.FreeHGlobal(dataPointer); } }
public static BooleanReason ImportUserCertificateFromBuffer(byte[] buffer, SecureString password, string friendlyName) { var info = new NativeMethods.CryptAttributeBlob(); var temporaryStore = IntPtr.Zero; var context = IntPtr.Zero; var passwordPointer = IntPtr.Zero; try { if (buffer == null) return new BooleanReason(false, "The provided certificate buffer is empty."); info.data = Marshal.AllocHGlobal(buffer.Length); info.dataSize = buffer.Length; if (password != null) passwordPointer = Marshal.SecureStringToGlobalAllocUnicode(password); Marshal.Copy(buffer, 0, info.data, buffer.Length); temporaryStore = NativeMethods.PFXImportCertStore(ref info, passwordPointer, NativeMethods.UserKeyset); if (temporaryStore == IntPtr.Zero) { var issue = new Win32Exception(Marshal.GetLastWin32Error()); return new BooleanReason(false, "Could not import cert data: " + issue.Message); } context = GetFirstUsableContextFromStore(temporaryStore); if (context == IntPtr.Zero) return new BooleanReason(false, "Could not import cert data: no useable certificate in store"); AssignFriendlyNameToContext(context, friendlyName); var importInfo = new NativeMethods.ContextImportInfo { SubjectChoice = NativeMethods.ImportFromContext, context = context, Password = passwordPointer }; importInfo.Size = Marshal.SizeOf(importInfo); var result = NativeMethods.CryptUIWizImport(NativeMethods.NoUserInterface | NativeMethods.ImportToCurrentuser, IntPtr.Zero, IntPtr.Zero, ref importInfo, IntPtr.Zero); if (!result) { var issue = new Win32Exception(Marshal.GetLastWin32Error()); return new BooleanReason(false, issue.Message); } return new BooleanReason(true, ""); } finally { if (context != IntPtr.Zero) NativeMethods.CertFreeCertificateContext(context); if (info.data != IntPtr.Zero) Marshal.FreeHGlobal(info.data); if (temporaryStore != IntPtr.Zero) NativeMethods.CertCloseStore(temporaryStore, 0); if (passwordPointer != IntPtr.Zero) Marshal.ZeroFreeGlobalAllocUnicode(passwordPointer); } }