Jump to content
Fr0sT.Brutal

SChannel TLS - perform TLS communication with WinAPI

Recommended Posts

Posted (edited)

Project reached somewhat usable state. Check it here.

 

SChannel is Windows built-in implementation of TLS protocols. This allows supporting secure connections without any external library.

Repo contains:

  • unit with transport-agnostic helper functions for easy implementation of TLS communication by means of Windows SChannel.

  • sample of transport-agnostic synchronous TLS handshake using callback functions for real communication

  • API declarations borrowed from JEDI project

  • ICS TWSocket descendant that performs TLS communication

  • demo project for performing any textual (mainly HTTPS) requests via secure connection

 

Note. I first started learning what TLS is a couple of weeks ago :) So units contain only a necessary minimum to interact with TLS server. Certs and other advanced stuff are in TODO.

Thanks to author of TLS-Sample from http://www.coastrd.com/c-schannel-smtp and JEDI for WinAPI headers.

Edited by Fr0sT.Brutal
  • Thanks 2

Share this post


Link to post

Interesting, it does work with modern compilers, not with Delphi 2007, too many new language features. 

 

At least the sync request returns a full page, the async request only returns one buffer load of data. 

 

While SChannel avoids the need for OpenSSL DLLs, it does mean encryption protocols and ciphers are determined by Microsoft, and they don't really care about keeping up to date, particularly with older operation systems, it took years for Windows Vista and 7 to get TLS/1,2 and probably only because anything older is becoming obsolete soon.  TLS/1,3 is still not supported by Windows 10/2019 a year after everyone else started using it, including ICS. 

 

If you take this further, ICS already has soon functions to interact with the Windows certificate store for checking certificate chains, it's one of our options, using them will save you a lot of effort.

 

Angus

 

 

Share this post


Link to post
Posted (edited)

For information, our Open Source https://github.com/synopse/mORMot/blob/master/SynCrtSock.pas supports SChannel as TLS layer since some time, for its raw socket layer.
Of course, there is the additional WinInet/WinHTTP API for HTTP requests, which supports proper Proxy detection.

 

Its SChannel implementation is more concise that your propose, and it works from Delphi 6 and up, and also for FPC.

See https://github.com/synopse/mORMot/blob/5777f00d17fcbe0378522ceddceb0abece1dd0e3/SynWinSock.pas#L847

Edited by Arnaud Bouchez
  • Like 1

Share this post


Link to post
15 hours ago, Angus Robertson said:

Interesting, it does work with modern compilers, not with Delphi 2007, too many new language features.

 

Hmm, this is possible though I tried to keep close to classic feature set. Exception is for Default() use, I like it so much I can't return to ugly FillChar.

 

Quote

At least the sync request returns a full page, the async request only returns one buffer load of data. 

That's weird. Could you post log? I have no problems requesting GET / from google.

Quote

While SChannel avoids the need for OpenSSL DLLs, it does mean encryption protocols and ciphers are determined by Microsoft, and they don't really care about keeping up to date, particularly with older operation systems, it took years for Windows Vista and 7 to get TLS/1,2 and probably only because anything older is becoming obsolete soon.  TLS/1,3 is still not supported by Windows 10/2019 a year after everyone else started using it, including ICS. 

Well, that's philosophic question. I hate tons of DLLs around my app; if OpenSLL could be compiled statically I'd prefer this option. But this requires too much C++ kung-fu to build them static and much more cross-compiler-fu to make Delphi eat these obj-s. I don't brave enough to start this battle. Anyway, f.ex., cURL uses SChannel by default.

 

Quote

If you take this further, ICS already has soon functions to interact with the Windows certificate store for checking certificate chains, it's one of our options, using them will save you a lot of effort.

Thanks, I'll have a look.

 

10 hours ago, Arnaud Bouchez said:

For information, our Open Source https://github.com/synopse/mORMot/blob/master/SynCrtSock.pas supports SChannel as TLS layer since some time, for its raw socket layer.

Thanks, I'll have a look. My functions could be bound with ANY socket lib - Indy, Synapse, etc, even inter-process pipes. Anyway my purpose was to make TLS-enabled my app that uses ICS.

Edited by Fr0sT.Brutal
  • Like 1

Share this post


Link to post

I started fixing errors with Delphi 2007 to get it to build, but there were too many.  Simple things like type LONG missing.  Does not matter for personal projects, but is important if the code is ever to incorporated into libraries.

 

The issue with async requests seems to relate to most of the content not being returned until the connection is closed.  This URL works fine:

 

www.magsys.co.uk

GET /delphi/ddservice.asp HTTP/1.1
Connection: close
Host: www.magsys.co.uk
 

While this does not, the end of the page only appears after the server closes the connection on a 60 second timeout:

 

www.telecom-tariffs.co.uk
GET /serverinfo.htm HTTP/1.1
Connection: close
 

The first server is IIS. the second the ICS web server, so it seems we have aggressive Keep-Alive that is ignoring the Close command, another ICS bug for me to fix.  But it shows up a bug in your code as well. 

 

I chose that page because it shows the SSL/TLS connection parameters selected by the server, useful to check browser capabilities, and the poor range of ciphers supported by SChannel on older versions of Windows. 

 

Angus

 

 

 

Share this post


Link to post

Angus, I have no D2007 at hand but I'll try to keep compatibility. At least 2007 already has Default so it's worth to support :)))

Well, the code is just a demo 😉 it's tuned for connect-request-response-close scheme, I have another setup where a data stream is received as well.

As for cipher suites, Windows seems to have plenty - at least for me.

Share this post


Link to post

Not sure when Default() was added, but it gave an error in Delphi 2007.   The keep-alive issue was not in the ICS server, but in my application. 

 

But you still need to fix data being received correctly, if you remove the close line for your google example, it takes four minutes for the window to become responsive and display the received data, which is the Google timeout.

 

The Microsoft page actually shows how poor the ciphers are in older Windows versions, it says there are none for TLS/1,2 in Windows 7, although a couple have now been added. but not nearly as good as OpenSSL supports on Windows 7. 

 

Angus

 

Share this post


Link to post
1 hour ago, Angus Robertson said:

But you still need to fix data being received correctly, if you remove the close line for your google example, it takes four minutes for the window to become responsive and display the received data, which is the Google timeout.

Yeah, it's buffering issue... AsyncReceive calls ioctl and breaks loop when there are no data in socket left but they are in internal buffer decrypted already. And dummy Recv(0) didn't launch a new FD_READ. I'm now trying posting FMsg_WM_ASYNCSELECT just like in HTTPTunnelSocket.

Edited by Fr0sT.Brutal

Share this post


Link to post
On 10/10/2019 at 5:01 AM, Angus Robertson said:

Not sure when Default() was added, but it gave an error in Delphi 2007.

It was introduced in Delphi 2007 for .NET, so it might not have been available on the Win32 side yet.

Share this post


Link to post

ICS support Delphi 7 onwards so we avoid any language features or libraries added after that, or have our own versions of them, such as ANSI or Wide5tring functions.   Users tell me quickly if I accidentally do something that Delphi 7 does not support so it is still used. 

 

Angus

 

Share this post


Link to post

Well, I won't reject PR's adding compatibility with ancient compilers but unlikely will do that myself. Some of introduced language features are too nice to ignore them.

Edited by Fr0sT.Brutal

Share this post


Link to post

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

×