Jump to content
Martin Searancke

Attempting to implement DTLS with PSK

Recommended Posts

So I have been fighting with this little project for a couple of weeks on and off with varying success. Slowing putting together pieces of the puzzle from various community groups. 

 

To implement DTLS with PSK I have had to modify "OverbyteIcsSSLEAY.pas" to add several missing functions (e.g. SSL_CTX_set_psk_client_callback). 

Two important function to get this working are BIO_set_conn_hostname and BIO_get_ssl. Both of these are c++ macros that call "BIO_ctrl". This however is not located in "libssl-1_1.dll" but rather "libcrypto-1_1.dll".

 

In "OverbyteIcsSSLEAY.pas" I can see "GLIBEAY_110DLL_Name" defined (libcrypto-1_1.dll) but this is never used or referenced anywhere in the unit. I don't think I will have any trouble adding the appropriate code to load this and import "BIO_ctrl" but before doing so I wanted to check if there is another unit that already does this (couldn't find anything)?

 

Thanks in advance,

Martin

 

 

Share this post


Link to post

Beware when updating OverbyteIcsSSLEAY.pas and OverbyteIcsLIBEAY.pas they change when I'm adding new features to ICS, make sure you use the latest from SVN last week, there are minor changes not in SVN yet. 

 

We replicates macros as functions in OverbyteIcsLIBEAY which is where you should add any more you need, look at function f_BIO_get_ssl which calls f_BIO_ctrl, you need to add f_BIO_set_conn_hostname similarly, etc.,

 

Use of macros is horrible for those of us not using C++, even Google has turned them all into APIs in BoringSSL.  The main problem is when OpenSSL convert macros back into APIs, this is never documented clearly so we keep using our macro function which then usually fails. 

 

Angus

 

Share this post


Link to post

Thanks, for now I have just make a copy of OverbyteIcsSSLEAY.pas that I have edited. I didn't get a chance to get back into this today but once I have figured all of this out I will try to contribute back.

Highly likely there will be more questions.

Share this post


Link to post

I have managed to work out all of the missing functions that I think are needed but unfortunately SSL_connect is failing with SSL_ERROR_SSL. I also have a breakpoint on the PSK callback but this is never reached.

I realize that I am asking for something that has not been implemented in your components but any assistance would be appreciated. Below is my code that is based on these 2 posts that I have found:
An implementation of DTLS using OpenSSL but using a  certificate file rather than PSK:

https://chris-wood.github.io/2016/05/06/OpenSSL-DTLS.html

An implementation of PSK using OpenSSL but with a connected socket:

https://bitbucket.org/tiebingzhang/tls-psk-server-client-example/src/783092f802383421cfa1088b0e7b804b39d3cf7c/psk_client.c?at=default

 

2 lines I am least sure about is the call "f_SSL_CTX_set_cipher_list" as I have not found any documentation about the specific cipher that is required by Philips (TLS_PSK_WITH_AES_128_GCM_SHA256).

The other uncertainty is the call to "f_BIO_get_ssl" as the second parameter has to be the address of SSL for this function to not return an error. This seems inconsistent with the function definition but is consistent with the C++ example.

 

Thanks in advance,

Martin

  ICS_OPENSSL_VERSION_NUMBER := OSSL_VER_1100;
  SsleayLoad;
  LibeayLoad;

  // Create a new context using DTLS
  params.ctx := f_SSL_CTX_new(f_DTLSv1_2_client_method());
  if not assigned(params.ctx) then exit;

  f_SSL_CTX_set_psk_client_callback(params.ctx, @psk_client_cb);
  // Set our supported ciphers            // TLS_PSK_WITH_AES_128_GCM_SHA256
  var res := f_SSL_CTX_set_cipher_list(params.ctx, 'TLS-PSK-WITH-AES-128-GCM-SHA256'); // 'ALL:!ADH:!LOW:!EXP:!MD5:@STRENGTH');
  if res <> 1 then exit;

  params.bio := f_BIO_new_ssl_connect(params.ctx);

  res := f_BIO_set_conn_hostname(params.bio, PAnsiChar(AnsiString(ParamObj.HueBridgeIP+':2100')));
  if res <> 1 then exit;

  res := f_BIO_get_ssl(params.bio, @params.ssl);
  if res <> 1 then exit;

  f_SSL_set_connect_state(params.ssl);

  res := f_SSL_set_mode(params.ssl, SSL_MODE_AUTO_RETRY);
  if res <> SSL_MODE_AUTO_RETRY then exit;

  res := f_SSL_connect(params.ssl);
  if res = -1 then
  begin
    var error_code: integer;
    res := f_SSL_get_error(params.ssl, res);
    ShowMessage(Inttostr(res));
  end;

 

Share this post


Link to post

If you are trying to add support for DTLS and PSK to ICS using existing code, I might be able to help, but not to write a totally new SSL implementation using APIs, ignoring all our tested high level code.  I have no experience of DTLS or PSK.

 

Angus

 

Share this post


Link to post

I could not find anything in your higher level components that got me close to a DTLS implementation. 

I would love to contribute back and assist with adding DTLS to ICS but I figured I first needed to try to get something working. I guess my question is probably more suited for the openSSL mail list but to post my question there I need to convert what I have done back to c++. This will be my next step.

 

What I didn't think to try earlier was wireshark. I have since look into it and I cant see any packets (using both a port filter and a DTLS filter) so that tells me I do not have this setup correctly at all. 

 

Martin

Share this post


Link to post

The point I was making is ICS already has functions to correctly initialise an SSL context which work, but you chose to do it yourself probably based on old OpenSSL code and not reflecting changes made in recent years.  When OpenSSL functions fail, there is excellent error tracing available, which might help you narrow down what is failing.  I would not worry about ciphers or callbacks until the basics of your application are working, you'll get OpenSSL errors telling you what is wrong.

 

Angus

Share this post


Link to post

I will take a look at the higher level functions but because the first line of the initialization calls a openSSL function that's not implemented in ICS (DTLSv1_2_client_method) I guess I assumed I could not use those:

params.ctx := f_SSL_CTX_new(f_DTLSv1_2_client_method());

Martin

Share this post


Link to post

Your would simply add an extra line and condition in InitializeCtx after Meth := f_TLS_method; with Meth := f_DTLS_method; and set the versions later where TLS versions are set.  But there are probably other changes needed, our code was never tested with DTLS, it is also asyc (no blocking) in operation whereas most other SSL implementations are blocking. 

 

Angus

 

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
×