Note that there are some explanatory texts on larger screens.

plurals
  1. POHow to Call Schannel Functions from .Net/C#
    text
    copied!<p>I am trying to re-order/remove cipher suites due to compliance reasons (I want to use 256 bit AES and ephemeral keys) in .Net. However, using WCF TCP Transport Security, I cede all control over the security to Windows' TLS implementation and its preferred ciphers. I don't want to change the system-level ciphers.</p> <p>I found this <a href="http://msdn.microsoft.com/en-us/library/windows/desktop/bb870930%28v=vs.85%29.aspx" rel="nofollow">great Microsoft page</a> that lists how to do it at the application level using <a href="http://msdn.microsoft.com/en-us/library/windows/desktop/aa375426%28v=vs.85%29.aspx" rel="nofollow">BCryptEnumContextFunctions</a>, <a href="http://msdn.microsoft.com/en-us/library/windows/desktop/aa375360%28v=vs.85%29.aspx" rel="nofollow">BCryptAddContextFunction</a>, <a href="http://msdn.microsoft.com/en-us/library/windows/desktop/aa375492%28v=vs.85%29.aspx" rel="nofollow">BCryptRemoveContextFunction</a>, but it's all C and I don't have enough P/Invoke experience to even know where to begin. I googled but didn't find anyone doing it.</p> <p>The C++ code snippets on the MSDN page are below, and I need help converting them to .Net P/Invoke calls:</p> <p><strong>BCryptEnumContextFunctions</strong></p> <pre><code>#include &lt;stdio.h&gt; #include &lt;windows.h&gt; #include &lt;bcrypt.h&gt; void main() { HRESULT Status = ERROR_SUCCESS; DWORD cbBuffer = 0; PCRYPT_CONTEXT_FUNCTIONS pBuffer = NULL; Status = BCryptEnumContextFunctions( CRYPT_LOCAL, L"SSL", NCRYPT_SCHANNEL_INTERFACE, &amp;cbBuffer, &amp;pBuffer); if(FAILED(Status)) { printf_s("\n**** Error 0x%x returned by BCryptEnumContextFunctions\n", Status); goto Cleanup; } if(pBuffer == NULL) { printf_s("\n**** Error pBuffer returned from BCryptEnumContextFunctions is null"); goto Cleanup; } printf_s("\n\n Listing Cipher Suites "); for(UINT index = 0; index &lt; pBuffer-&gt;cFunctions; ++index) { printf_s("\n%S", pBuffer-&gt;rgpszFunctions[index]); } Cleanup: if (pBuffer != NULL) { BCryptFreeBuffer(pBuffer); } } </code></pre> <p><strong>BCryptAddContextFunction</strong></p> <pre><code>#include &lt;stdio.h&gt; #include &lt;windows.h&gt; #include &lt;bcrypt.h&gt; void main() { SECURITY_STATUS Status = ERROR_SUCCESS; LPWSTR wszCipher = (L"RSA_EXPORT1024_DES_CBC_SHA"); Status = BCryptAddContextFunction( CRYPT_LOCAL, L"SSL", NCRYPT_SCHANNEL_INTERFACE, wszCipher, CRYPT_PRIORITY_TOP); } </code></pre> <p><strong>BCryptRemoveContextFunction</strong></p> <pre><code>#include &lt;stdio.h&gt; #include &lt;windows.h&gt; #include &lt;bcrypt.h&gt; void main() { SECURITY_STATUS Status = ERROR_SUCCESS; LPWSTR wszCipher = (L"TLS_RSA_WITH_RC4_128_SHA"); Status = BCryptRemoveContextFunction( CRYPT_LOCAL, L"SSL", NCRYPT_SCHANNEL_INTERFACE, wszCipher); } </code></pre> <p>Could someone please help me convert these to .Net so I can call them from managed code to adjust the ciphers? Thanks!</p> <p><strong>Edit:</strong></p> <p>Later last night, I tried the following in a test program (still have no idea what I'm doing in P/Invoke):</p> <pre><code>// I found this in bcrypt.h const uint CRYPT_LOCAL = 0x00000001; // I can't find this anywhere in Microsoft's headers in my SDK, // but I found some random .c file with it in there. No idea // what this constant actually is according to Microsoft const uint NCRYPT_SCHANNEL_INTERFACE = 0x00010002; public static void DoStuff() { PCRYPT_CONTEXT_FUNCTIONS pBuffer = new PCRYPT_CONTEXT_FUNCTIONS(); pBuffer.rgpszFunctions = String.Empty.PadRight(1500); uint cbBuffer = (uint)Marshal.SizeOf(typeof(PCRYPT_CONTEXT_FUNCTIONS)); uint Status = BCryptEnumContextFunctions( CRYPT_LOCAL, "SSL", NCRYPT_SCHANNEL_INTERFACE, ref cbBuffer, ref pBuffer); Console.WriteLine(Status); Console.WriteLine(pBuffer); Console.WriteLine(cbBuffer); Console.WriteLine(pBuffer.cFunctions); Console.WriteLine(pBuffer.rgpszFunctions); } /* typedef struct _CRYPT_CONTEXT_FUNCTIONS { ULONG cFunctions; PWSTR rgpszFunctions; } CRYPT_CONTEXT_FUNCTIONS, *PCRYPT_CONTEXT_FUNCTIONS; */ [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)] public struct PCRYPT_CONTEXT_FUNCTIONS { public uint cFunctions; public string rgpszFunctions; } /* NTSTATUS WINAPI BCryptEnumContextFunctions( ULONG dwTable, LPCWSTR pszContext, ULONG dwInterface, ULONG *pcbBuffer, PCRYPT_CONTEXT_FUNCTIONS *ppBuffer ); */ [DllImport("Bcrypt.dll", CharSet = CharSet.Unicode, SetLastError = true)] static extern uint BCryptEnumContextFunctions(uint dwTable, string pszContext, uint dwInterface, ref uint pcbBuffer, ref PCRYPT_CONTEXT_FUNCTIONS ppBuffer); </code></pre> <p>The output right now of the only method I got even this far with is:</p> <pre><code>0 MyClass+PCRYPT_CONTEXT_FUNCTIONS 2400 8934576 [1500 spaces that I initialized rgpszFunctions with, not the cipher functions] </code></pre>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload