private void RebuildExtensions() { if (_frozen) { return; } Marshal.FreeHGlobal(_blob); var structSize = Marshal.SizeOf(typeof(CERT_EXTENSION)); _blob = Marshal.AllocHGlobal(structSize * _marshaledExtensions.Count); for (int index = 0, offset = 0; index < _marshaledExtensions.Count; index++, offset += structSize) { var marshalX509Extension = _marshaledExtensions[index]; Marshal.StructureToPtr(marshalX509Extension.Value, IntPtrArithmetic.Add(_blob, offset), false); } }
private static byte[] EncodeExtension(IList <X509AlternativeName> altNames) { var certAltName = new CERT_ALT_NAME_INFO(); certAltName.cAltEntry = (uint)altNames.Count; var structSize = Marshal.SizeOf(typeof(CERT_ALT_NAME_ENTRY)); var altNamesBuffer = Marshal.AllocHGlobal(structSize * altNames.Count); var unionValues = new List <IntPtr>(); try { for (int index = 0, offset = 0; index < altNames.Count; index++, offset += structSize) { var altName = new CERT_ALT_NAME_ENTRY(); altName.dwAltNameChoice = (CertAltNameChoice)altNames[index].Type; switch (altName.dwAltNameChoice) { case CertAltNameChoice.CERT_ALT_NAME_DNS_NAME: altName.Value = new CERT_ALT_NAME_ENTRY_UNION { pwszDNSName = Marshal.StringToHGlobalUni((string)altNames[index].Value) }; unionValues.Add(altName.Value.pwszDNSName); break; case CertAltNameChoice.CERT_ALT_NAME_URL: altName.Value = new CERT_ALT_NAME_ENTRY_UNION { pwszURL = Marshal.StringToHGlobalUni((string)altNames[index].Value) }; unionValues.Add(altName.Value.pwszURL); break; case CertAltNameChoice.CERT_ALT_NAME_IP_ADDRESS: var ip = (IPAddress)altNames[index].Value; var addressBytes = ip.GetAddressBytes(); var ipBytes = Marshal.AllocHGlobal(addressBytes.Length); Marshal.Copy(addressBytes, 0, ipBytes, addressBytes.Length); altName.Value = new CERT_ALT_NAME_ENTRY_UNION { IPAddress = new CRYPTOAPI_BLOB { cbData = (uint)addressBytes.Length, pbData = ipBytes } }; unionValues.Add(ipBytes); break; } Marshal.StructureToPtr(altName, IntPtrArithmetic.Add(altNamesBuffer, offset), false); } certAltName.rgAltEntry = altNamesBuffer; uint dataSize = 0; LocalBufferSafeHandle data; if (!Crypt32.CryptEncodeObjectEx(EncodingType.X509_ASN_ENCODING, OIDs.szOID_SUBJECT_ALT_NAME2, ref certAltName, 0x8000, IntPtr.Zero, out data, ref dataSize)) { throw new Win32Exception(Marshal.GetLastWin32Error()); } using (data) { var buffer = new byte[dataSize]; Marshal.Copy(data.DangerousGetHandle(), buffer, 0, (int)dataSize); return(buffer); } } finally { Marshal.FreeHGlobal(altNamesBuffer); unionValues.ForEach(Marshal.FreeHGlobal); } }