obgm / libcoap

A CoAP (RFC 7252) implementation in C
Other
777 stars 421 forks source link

coap-client binary PSK #1418

Closed dakhnod closed 1 month ago

dakhnod commented 1 month ago

I am trying to use the coap-client executable to send a request to an OpenThread border router.

All I am given from the router is a so-called PSKc, consisting of 16 bytes. No username or identity is involved.

Hence, my question:

How do I use the binary PSK with coap-client? Is the identity somehow relevant?

mrdeep1 commented 1 month ago

It would appear that the border router does not care about using the identity (which can be used to select alternative PSK keys when (D)TLS is starting up). I suspect it does not matter what you use - just something.

The coap-client in the examples directory uses the -k option to read in the ascii provided key - and then uses the binary equivalent of each character in sequence up to the ascii key length. This obviously does not work for you.

In the coap-client's setup_psk() function, dtls_psk.psk_info.key.s and dtls_psk.psk_info.key.length need to be set up to hold your binary PSKc value and length, which would be a code change specifically for you.

dakhnod commented 1 month ago

Would it be possible to somehow encode the binary PSK in the bash? Something like key=$(printf "\x00\xff, ...") and then use coap-client -k "$key" ...

mrdeep1 commented 1 month ago

Unfortunately no, as the (getopt) logic passes across the provided argument which is then scan for a trailing NUL character - so if one is embedded in the argument, then the incorrect value is passed in.

As with the -O option, which accepts a leading 0x to indicate that what follows is the hex representation of a binary value, it makes sense to add to this style of input for the -k option.

mrdeep1 commented 1 month ago

@dakhnod Please check #1419 for a solution that gives you the ability to specify a binary key by providing the hex equivalent of the binary value which is indicated by a leading 0x.

mrdeep1 commented 1 month ago

@dakhnod The develop branch now has the code in it to support the coap-client (and coap-server) defining a binary PSK.

-k 0x3132333435363738 is equivalent to -k 1234568 and both forms use the same PSK key for any communications.

dakhnod commented 1 month ago

Wow, great support! Thank you very much!

I am testing this just now, still having SSL handshake failures. Lets see...

dakhnod commented 1 month ago

The key encoding seems to work, thanks! the coap server is reporting got no ciphersuites in common, any idea what I could do here?

mrdeep1 commented 1 month ago

What TLS library are you using?

dakhnod commented 1 month ago

How can I find that out?

dakhnod commented 1 month ago

If I understand the commissioner code correctly, I need EC-JPAKE

mrdeep1 commented 1 month ago

How can I find that out?

examples/coap-client -? 2>&1 |head -10

EC-JPAKE

Not sure what TLS libraries support this - will need to check it out.

dakhnod commented 1 month ago

openssl and mbedtls don't, apparently...

mrdeep1 commented 1 month ago

Mbed TLS 3.4.0 or later appear to support ED-JPAKE. May require some tweaks to src/coap_mbedtls.c.

dakhnod commented 1 month ago

yep, had to uncomment MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED. Looking at coap_mbedtls.c...

mrdeep1 commented 1 month ago

This gets EC-PJAKE added to the client's cipher list (for MbedTLS < 3.6.0). Needs work to get this properly integrated, but worth checking out.

$ git diff
diff --git a/src/coap_mbedtls.c b/src/coap_mbedtls.c
index 6c70f4f8..cdd8a86c 100644
--- a/src/coap_mbedtls.c
+++ b/src/coap_mbedtls.c
@@ -1102,6 +1102,8 @@ coap_ssl_ciphersuite_uses_psk(const mbedtls_ssl_ciphersuite_t *info) {
     return 0;
   }
 #else /* MBEDTLS_VERSION_NUMBER < 0x03060000 */
+  if (info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECJPAKE)
+    return 1;
   return mbedtls_ssl_ciphersuite_uses_psk(info);
 #endif /* MBEDTLS_VERSION_NUMBER < 0x03060000 */
 }
@@ -1648,6 +1650,9 @@ coap_dtls_new_mbedtls_env(coap_session_t *c_session,
                           sizeof(cid));
     }
 #endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */
+const coap_bin_const_t *psk_key;
+psk_key = coap_get_session_server_psk_key(c_session);
+mbedtls_ssl_set_hs_ecjpake_password(&m_env->ssl, psk_key->s, psk_key->length);
   }
 #if !COAP_DISABLE_TCP
   else {
dakhnod commented 1 month ago

Thank you for your help!

I needed to rebuild and reinstall mbedtls with ECJPAKE enabled and apply the following patch:

diff --git a/src/coap_mbedtls.c b/src/coap_mbedtls.c
index 6c70f4f8..1811a46b 100644
--- a/src/coap_mbedtls.c
+++ b/src/coap_mbedtls.c
@@ -1089,6 +1089,7 @@ coap_ssl_ciphersuite_uses_psk(const mbedtls_ssl_ciphersuite_t *info) {
   case MBEDTLS_KEY_EXCHANGE_RSA_PSK:
   case MBEDTLS_KEY_EXCHANGE_DHE_PSK:
   case MBEDTLS_KEY_EXCHANGE_ECDHE_PSK:
+  case MBEDTLS_KEY_EXCHANGE_ECJPAKE:
     return 1;
   case MBEDTLS_KEY_EXCHANGE_NONE:
   case MBEDTLS_KEY_EXCHANGE_RSA:
@@ -1097,11 +1098,12 @@ coap_ssl_ciphersuite_uses_psk(const mbedtls_ssl_ciphersuite_t *info) {
   case MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA:
   case MBEDTLS_KEY_EXCHANGE_ECDH_RSA:
   case MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA:
-  case MBEDTLS_KEY_EXCHANGE_ECJPAKE:
   default:
     return 0;
   }
 #else /* MBEDTLS_VERSION_NUMBER < 0x03060000 */
+  if (info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECJPAKE)
+    return 1;
   return mbedtls_ssl_ciphersuite_uses_psk(info);
 #endif /* MBEDTLS_VERSION_NUMBER < 0x03060000 */
 }
@@ -1648,6 +1650,9 @@ coap_dtls_new_mbedtls_env(coap_session_t *c_session,
                           sizeof(cid));
     }
 #endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */
+const coap_bin_const_t *psk_key;
+psk_key = coap_get_session_server_psk_key(c_session);
+mbedtls_ssl_set_hs_ecjpake_password(&m_env->ssl, psk_key->s, psk_key->length);
   }
 #if !COAP_DISABLE_TCP
   else {
mrdeep1 commented 1 month ago

Thanks for the feedback. I assume that all is working now for when I look at best as to how to configure / integrate this functionality.