MG_TLS_BUILTIN: optional two-way auth [was: malformed empty Certificate message in TLS 1.3 (RFC 8446 violation)] #3446
Replies: 6 comments 1 reply
-
|
There is no reason for Mongoose to be sending a certificate unless you configured your server in two-way (mutual) TLS authentication. Lines 1839 to 1849 in 0ec1112 You are using Two-way (mutual) authentication but that is not mandatory, I don't think your setup is correct, and if is, please explain why and point to authoritative documentation. We currently do not support something like that, Mongoose currently works either with one-way or two-way auth, not what I think is your setup; you either don't configure a cert and are not requested for one, or if you will be requested a cert, then you configure one. https://mongoose.ws/documentation/tutorials/tls/ Please, instead of explaining us what we should fix and how, I suggest you tell us how you configure Mongoose and provide a TLS dialog capture, so we can see what the actual problem is, and, in case it were needed, can also fix our CI/CD tests that pass; or add new. your struct mg_tls_opts and where do you call mg_tls_initThank you. |
Beta Was this translation helpful? Give feedback.
-
|
Thank you for the quick response. My configuration: struct mg_tls_opts tls_opts;
memset(&tls_opts, 0, sizeof(tls_opts));
tls_opts.ca = mg_str(TLS_CA); // server CA certificate (PEM)
tls_opts.name = mg_url_host(url);
tls_opts.skip_verification = 1;
// NO cert or key set — one-way TLS, not mutual
mg_tls_init(c, &tls_opts);This is called inside the MQTT connect handler after The scenario: The server sends a Per RFC 8446 Section 4.4.2 (https://www.rfc-editor.org/rfc/rfc8446#section-4.4.2):
The keyword is MUST. In TLS 1.3, when the server sends Looking at the code you referenced: if (tls->cert_requested && tls->cert_der.len > 0) { // two-way authWhen |
Beta Was this translation helpful? Give feedback.
-
|
You are configuring one-way in Mongoose, but your server is requesting two-way. Said that, it doesn't seem too time consuming to add support for that. I'll mark this as a feature request and it will be handled in due time. If you're a paying customer, please contact us at Support and we'll speed up things for you. |
Beta Was this translation helpful? Give feedback.
-
|
Thanks a lot for the quick and detailed response —and for accepting this as a feature request! You asked about authoritative documentation for this configuration. It's part of the TLS 1.3 spec itself:
So the "ask but don't enforce" model is baked into TLS 1.3 by design it's not something specific to any broker. I totally understand it hasn't come up before from your users. I have a local workaround that works well for now, so there's no urgency at all on my side. Whenever you get to it is fine. Thanks again for maintaining such a great library — keep up the awesome work! |
Beta Was this translation helpful? Give feedback.
-
|
Added support for no certificates, hence sending empty lists. |
Beta Was this translation helpful? Give feedback.
-
|
Thanks for the quick update. I tested it on my side, and unfortunately it still does not work for my case. So for my environment, this branch does not fix the issue yet. |
Beta Was this translation helpful? Give feedback.
Uh oh!
There was an error while loading. Please reload this page.
-
My goal is: Connect to an MQTTS broker using
MG_TLS_BUILTINwithout providing a client certificate. The broker sends aCertificateRequestduring the TLS 1.3 handshake but does not require a client certificate (fail_if_no_peer_cert = false).My actions were: Configured
mg_tls_optswith only the server CA certificate andskip_verification = 1. No clientcertorkeywas set. Connected to a TLS 1.3 MQTT broker on port 8883.My expectation was: The TLS handshake should complete successfully with an empty Certificate message (no client cert), and the MQTT CONNECT should be accepted — the same way
mosquitto_pub(OpenSSL) connects to the same broker without a client certificate.The result I saw: The TLS handshake appears to complete on the client side (keys are derived, Certificate + Finished are sent, MQTT CONNECT is sent encrypted), but the server silently closes the connection every time. Logs:
The same broker works fine with
mosquitto_pubwithout a client cert:mg_tls_send_cert()function sends a malformed empty Certificate message whencert_der.len == 0. Instead of an empty certificate list (length 0), it sends a list with one entry containing 0-lengthcert_data, which violates RFC 8446 Section 4.4.2 (cert_dataminimum length is 1). Could this be fixed?Root Cause Analysis
In
mg_tls_send_cert(), whencert_der.len == 0:This creates a certificate list with one entry (3 bytes cert length + 0 bytes data + 2 bytes extensions = 5), but a 0-length
cert_datais invalid per RFC 8446.What Mongoose sends (wrong):
What RFC 8446 requires (empty list, no entries):
Suggested Fix
Add an early return at the top of
mg_tls_send_cert()for clients with no certificate:Environment
Beta Was this translation helpful? Give feedback.
All reactions