Provide instructions for TLS configuration (#20619)

Resolves #20199

Signed-off-by: Jacob Laursen <jacob-github@vindvejr.dk>
This commit is contained in:
Jacob Laursen
2026-04-22 16:30:54 +02:00
committed by GitHub
parent b926e4ce9d
commit 8672051ab2
3 changed files with 79 additions and 3 deletions
@@ -169,6 +169,42 @@ The easiest way to determine the pmapId, region_ids/zoneids and userPmapvId is t
1. Roomba's built-in MQTT server, used for communication, supports only a single local connection at a time. Bear this in mind when you want to do something that requires local connection from your phone, like reconfiguring the network. Disable openHAB Thing before doing this.
1. Sometimes during intensive testing Roomba just stopped communicating over the local connection. If this happens, try rebooting it. On my robot it's done by holding "Clean" button for about 10 seconds until all the LEDs come on. Release the button and the reboot tone will be played. It looks like there are some bugs in the firmware.
### TLS Compatibility Issue
The Thing may go OFFLINE (COMMUNICATION_ERROR) with:
> Required TLS cipher (TLS_RSA_WITH_AES_256_CBC_SHA) is disabled by your Java security settings.
Some Roomba models use an outdated TLS configuration and require the legacy cipher `TLS_RSA_WITH_AES_256_CBC_SHA`.
Starting with OpenJDK 21.0.10 (and corresponding distributions such as Eclipse Temurin 21.0.10), Java disables all `TLS_RSA_*` cipher suites by default via the `jdk.tls.disabledAlgorithms` setting.
As a result, connections to devices relying on these ciphers (such as some Roomba models) will fail.
To allow the connection, you must re-enable this cipher in Javas TLS configuration.
:::warning
Re-enabling `TLS_RSA_WITH_AES_256_CBC_SHA` has security implications:
- No forward secrecy (RSA key exchange)
- Uses older CBC-based cipher
- Considered deprecated in modern TLS standards
Only enable this on trusted/local networks.
:::
To proceed, modify the system Java configuration by editing (for example) `/usr/lib/jvm/temurin-21-jre-arm64/conf/security/java.security` and adjust the `jdk.tls.disabledAlgorithms` setting with the following contents:
```ini
jdk.tls.disabledAlgorithms=SSLv3, TLSv1, TLSv1.1, DTLSv1.0, RC4, DES, \
MD5withRSA, DH keySize < 1024, EC keySize < 224, 3DES_EDE_CBC, anon, NULL, \
ECDH, TLS_RSA_WITH_AES_128_*, TLS_RSA_WITH_AES_256_CBC_SHA256, TLS_RSA_WITH_AES_256_GCM_SHA384, rsa_pkcs1_sha1 usage HandshakeSignature, \
ecdsa_sha1 usage HandshakeSignature, dsa_sha1 usage HandshakeSignature
```
:::warning
This change affects all Java applications on the system and requires a restart of openHAB.
:::
## Example
### `irobot.things` Example
@@ -19,6 +19,7 @@ import static org.openhab.binding.irobot.internal.IRobotBindingConstants.TRUST_M
import java.io.IOException;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.security.Security;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
@@ -91,8 +92,16 @@ public abstract class IRobotConnectionHandler implements MqttConnectionObserver,
connectionStateChanged(MqttConnectionState.DISCONNECTED, exception);
return false;
}).thenAccept(successful -> {
MqttConnectionState state = successful ? MqttConnectionState.CONNECTED : MqttConnectionState.DISCONNECTED;
connectionStateChanged(state, successful ? null : new TimeoutException("Timeout"));
if (successful) {
connectionStateChanged(MqttConnectionState.CONNECTED, null);
} else {
if (isRsaAes256CbcShaAvailable()) {
connectionStateChanged(MqttConnectionState.DISCONNECTED, new TimeoutException("Timeout"));
} else {
connectionStateChanged(MqttConnectionState.DISCONNECTED, new SecurityException(
"Required TLS cipher (TLS_RSA_WITH_AES_256_CBC_SHA) is disabled by your Java security settings."));
}
}
});
this.connection = connection;
@@ -175,4 +184,30 @@ public abstract class IRobotConnectionHandler implements MqttConnectionObserver,
connection.publish(topic, payload.getBytes(UTF_8), connection.getQos(), false);
}
}
/**
* Check if the cipher suite <code>TLS_RSA_WITH_AES_256_CBC_SHA</code> is available.
*
* @return true if the cipher suite is available, false otherwise
*/
private boolean isRsaAes256CbcShaAvailable() {
String disabledAlgorithms = Security.getProperty("jdk.tls.disabledAlgorithms");
if (disabledAlgorithms == null || disabledAlgorithms.isBlank()) {
return true;
}
logger.debug("jdk.tls.disabledAlgorithms: {}", disabledAlgorithms);
for (String token : disabledAlgorithms.split(",")) {
token = token.trim();
switch (token) {
case "TLS_RSA_*":
case "TLS_RSA_*_SHA":
case "TLS_RSA_WITH_AES_256_*":
case "TLS_RSA_WITH_AES_256_CBC_SHA":
return false;
}
}
return true;
}
}
@@ -123,6 +123,11 @@ public class RoombaHandler extends BaseThingHandler {
} else {
String message = (error != null) ? error.getMessage() : "Unknown reason";
updateStatus(OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, message);
if (error instanceof SecurityException) {
logger.warn(
"TLS_RSA_WITH_AES_256_CBC_SHA is disabled by Java TLS policy (jdk.tls.disabledAlgorithms), canceling reconnection attempts. Please consult binding documentation.");
dispose();
}
}
}
};
@@ -148,7 +153,7 @@ public class RoombaHandler extends BaseThingHandler {
public void dispose() {
Future<?> requester = credentialRequester;
if (requester != null) {
requester.cancel(false);
requester.cancel(true);
credentialRequester = null;
}