Skip to content

Commit

Permalink
Add support for RFC5746.
Browse files Browse the repository at this point in the history
Provides minimal version, renegotiation is still not supported at all.

Signed-off-by: Achim Kraus <achim.kraus@cloudcoap.net>
  • Loading branch information
boaks committed Nov 3, 2022
1 parent 25a6d64 commit 0d741b2
Show file tree
Hide file tree
Showing 13 changed files with 461 additions and 30 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,17 @@ public class DtlsEndpointContext extends MapBasedEndpointContext {
*/
public static final Definition<InetSocketAddress> KEY_PREVIOUS_ADDRESS = new Definition<>(
KEY_PREFIX_NONE_CRITICAL + "DTLS_PREVIOUS_ADDRESS", InetSocketAddress.class, ATTRIBUTE_DEFINITIONS);
/**
* The name of the attribute that contains a marker for the secure renegotiationt
* (see <a href="https://tools.ietf.org/html/rfc5746" target="_blank">RFC 5746</a>).
*
* Californium doesn't support renegotiation at all, but RFC5746 requests to
* update to a minimal version of RFC 5746.
*
* @since 3.8
*/
public static final Definition<Boolean> KEY_SECURE_RENEGOTIATION = new Definition<>(
"DTLS_SECURE_RENEGOTIATION", Boolean.class, ATTRIBUTE_DEFINITIONS);
/**
* Force full handshake before send this message. Doesn't start a handshake,
* if the connector is configured to act as server only.
Expand Down
40 changes: 24 additions & 16 deletions scandium-core/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -241,16 +241,17 @@ Note: *SHA378* in the cipher suite names are typos. It must be *SHA384*. The str
Supported extensions:
- [RFC 4279 - Pre-Shared Key](https://tools.ietf.org/html/rfc4279) simple and light authentication.
- [RFC 4492 - Elliptic Curve Cryptography (ECC)](https://tools.ietf.org/html/rfc4492)
- [RFC 8422 - Elliptic Curve Cryptography (ECC) Update](https://tools.ietf.org/html/rfc8422)
- [RFC 5489 - ECDHE_PSK Cipher Suites](https://tools.ietf.org/html/rfc5489)
- [RFC 5746 - Transport Layer Security (TLS) Renegotiation Indication Extension](https://tools.ietf.org/html/rfc5746) only minimal version, renegotiation is not supported at all!
- [RFC 6066 - TLS Extensions](https://tools.ietf.org/html/rfc6066)
- [RFC 6066 - Server Name Indication](https://tools.ietf.org/html/rfc6066#section-3)
- [RFC 6066 - Maximum Fragment Length Negotiation](https://tools.ietf.org/html/rfc6066#section-4)
- [RFC 7627 - Extended Master Secret Extension](https://tools.ietf.org/html/rfc7627)
- [RFC 8449 - Record Size Limit Extension](https://tools.ietf.org/html/rfc8449)
- [RFC 9146 - Connection Identifiers for DTLS 1.2](https://www.rfc-editor.org/rfc/rfc9146.html)
- [RFC 7250 - Raw Public Keys](https://tools.ietf.org/html/rfc7250)
- [RFC 7627 - Extended Master Secret Extension](https://tools.ietf.org/html/rfc7627)
- [RFC 7748 - Elliptic Curves for Security](https://tools.ietf.org/html/rfc7748)
- [RFC 8422 - Elliptic Curve Cryptography (ECC) Update](https://tools.ietf.org/html/rfc8422)
- [RFC 8449 - Record Size Limit Extension](https://tools.ietf.org/html/rfc8449)
- [RFC 9146 - Connection Identifiers for DTLS 1.2](https://www.rfc-editor.org/rfc/rfc9146.html)

## Support for x25519 and ed25519

Expand All @@ -272,44 +273,40 @@ Starting with 3.0.0-RC1 an experimental support for using [Bouncy Castle](https:

```
<properties>
<bc.version>1.69</bc.version>
<slf4j.version>1.7.34</slf4j.version>
<bc.art>jdk18on</bc.art>
<bc.version>1.72</bc.version>
<slf4j.version>1.7.36</slf4j.version>
</properties>
<dependencies>
<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bcpkix-jdk15on</artifactId>
<artifactId>bcpkix-${bc.art}</artifactId>
<version>${bc.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bcprov-jdk15on</artifactId>
<artifactId>bcprov-${bc.art}</artifactId>
<version>${bc.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bctls-jdk15on</artifactId>
<artifactId>bctls-${bc.art}</artifactId>
<version>${bc.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bcutil-jdk15on</artifactId>
<artifactId>bcutil-${bc.art}</artifactId>
<version>${bc.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>jul-to-slf4j</artifactId>
<version>${slf4j.version}</version>
<scope>test</scope>
</dependency>
</dependencies>
```

(With 3.3 the tests are using the updated version 1.70 instead of the 1.69, with 3.8 it is 1.71.1).
(With 3.3 the tests are using the updated version 1.70 instead of the 1.69, with 3.8 it is 1.72).

And setup a environment variable `CALIFORNIUM_JCE_PROVIDER` using the value `BC` (see [JceProviderUtil](../element-connector/src/main/java/org/eclipse/californium/elements/util/JceProviderUtil.java) for more details) or use the java `System.property` `CALIFORNIUM_JCE_PROVIDER` to do so.

Expand Down Expand Up @@ -434,3 +431,14 @@ Additional configuration values:
- [DtlsConfig.DTLS_USE_MULTI_RECORD_MESSAGES](src/main/java/org/eclipse/californium/scandium/config/DtlsConfig.java#L393)
- [DtlsConfig.DTLS_USE_MULTI_HANDSHAKE_MESSAGE_RECORDS](src/main/java/org/eclipse/californium/scandium/config/DtlsConfig.java#L398)

## DTLS 1.2 - RFC 5746 - Transport Layer Security (TLS) Renegotiation Indication Extension

Californium doesn't support renegotiation at all. Please always use full- or abbreviated-handshake.
[RFC 5746](https://tools.ietf.org/html/rfc5746) requires even for implementations, which doesn't support renegotiation to implement a minimal version of RFC 5746. With version 3.8 Californium supports now such a minimal version of RFC 5746.

The feature is configured with `DTLS.SECURE_RENEGOTIATION_MODE`. The supported values are `NONE`, `WANTED`, and `NEEDED`. The default is set to `WANTED`.

Californium itself uses a different technique to protect from misaligned application data and security contexts. It provides a `EndpointContext` for each received or send record, which enables to access the security parameters, which are exactly valid for that record. That mitigates not only the vulnerability fixed by [RFC 5746](https://tools.ietf.org/html/rfc5746) for the peer itself, it mitigates that even for new handshakes on the same ip-address.

Even with that protection, RFC 5746 is required to protect the other peers from being redirect to an other vulnerable server. If such a scenario is realistic, depends also on the used mutual authentication.

Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,32 @@ public enum DtlsRole {
BOTH
}

/**
* DTLS secure renegotiation.
*
* Californium doesn't support renegotiation at all, but RFC5746 requests to
* update to a minimal version of RFC 5746.
*
* See <a href="https://tools.ietf.org/html/rfc5746" target="_blank">RFC
* 5746</a> for additional details.
*
* @since 3.8
*/
public enum DtlsSecureRenegotiation {
/**
* Don't use secure renegotiation.
*/
NONE,
/**
* Request secure renegotiation.
*/
WANTED,
/**
* Reject missing secure renegotiation.
*/
NEEDED
}

/**
* Definition for list of signature and hash algorithms.
*/
Expand Down Expand Up @@ -239,6 +265,12 @@ protected List<SignatureAndHashAlgorithm> parseValue(String value) {
* {@link #DTLS_VERIFY_PEERS_ON_RESUMPTION_THRESHOLD} property in percent.
*/
public static final int DEFAULT_VERIFY_PEERS_ON_RESUMPTION_THRESHOLD_IN_PERCENT = 30;
/**
* The default value for the {@link #DTLS_SECURE_RENEGOTIATION}.
*
* @since 3.8
*/
public static final DtlsSecureRenegotiation DEFAULT_SECURE_RENEGOTIATION = DtlsSecureRenegotiation.WANTED;

/**
* DTLS session timeout. Currently not supported!
Expand Down Expand Up @@ -956,6 +988,23 @@ protected List<SignatureAndHashAlgorithm> parseValue(String value) {
"Threshold of current MAC errors to block all traffic for an endpoint. 0 to disable the MAC error filter.",
0, 0);

/**
* Specify the secure renegotiation mode.
*
* Californium doesn't support renegotiation at all, but RFC5746 requests to
* update to a minimal version of RFC 5746.
*
* See <a href="https://tools.ietf.org/html/rfc5746" target="_blank">RFC
* 5746</a> for additional details.
*
* @since 3.8
*/
public static final EnumDefinition<DtlsSecureRenegotiation> DTLS_SECURE_RENEGOTIATION = new EnumDefinition<>(
MODULE + "SECURE_RENEGOTIATION_MODE",
"Use minimal version of RFC5746 to indicate secure renegotiation on initial handshake.\n"
+ "Renegotation handshakes are always rejected by Californium.",
DEFAULT_SECURE_RENEGOTIATION, DtlsSecureRenegotiation.values());

public static final ModuleDefinitionsProvider DEFINITIONS = new ModuleDefinitionsProvider() {

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@
import java.security.GeneralSecurityException;
import java.security.MessageDigest;
import java.security.PublicKey;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ScheduledExecutorService;

Expand All @@ -57,6 +58,7 @@
import org.eclipse.californium.elements.util.NoPublicAPI;
import org.eclipse.californium.elements.util.StringUtil;
import org.eclipse.californium.scandium.config.DtlsConfig;
import org.eclipse.californium.scandium.config.DtlsConfig.DtlsSecureRenegotiation;
import org.eclipse.californium.scandium.config.DtlsConnectorConfig;
import org.eclipse.californium.scandium.dtls.AlertMessage.AlertDescription;
import org.eclipse.californium.scandium.dtls.AlertMessage.AlertLevel;
Expand Down Expand Up @@ -195,6 +197,19 @@ public class ClientHandshaker extends Handshaker {
*/
private final List<CipherSuite> supportedCipherSuites;

/**
* Secure renegotiation mode.
*
* Californium doesn't support renegotiation at all, but RFC5746 requests to
* update to a minimal version.
*
* See <a href="https://tools.ietf.org/html/rfc5746" target="_blank">RFC
* 5746</a> for additional details.
*
* @since 3.8
*/
private final DtlsSecureRenegotiation secureRenegotiation;

/**
* the supported groups (curves) ordered by preference
*
Expand Down Expand Up @@ -271,7 +286,19 @@ public class ClientHandshaker extends Handshaker {
public ClientHandshaker(String hostname, RecordLayer recordLayer, ScheduledExecutorService timer,
Connection connection, DtlsConnectorConfig config, boolean probe) {
super(0, 0, recordLayer, timer, connection, config);
this.supportedCipherSuites = config.getSupportedCipherSuites();

List<CipherSuite> cipherSuites = config.getSupportedCipherSuites();
boolean scsv = cipherSuites.contains(CipherSuite.TLS_EMPTY_RENEGOTIATION_INFO_SCSV);
DtlsSecureRenegotiation secureRenegotiation = config.get(DtlsConfig.DTLS_SECURE_RENEGOTIATION);

if (scsv && secureRenegotiation == DtlsSecureRenegotiation.NONE) {
secureRenegotiation = DtlsSecureRenegotiation.WANTED;
} else if (!scsv && secureRenegotiation != DtlsSecureRenegotiation.NONE) {
cipherSuites = new ArrayList<>(cipherSuites);
cipherSuites.add(CipherSuite.TLS_EMPTY_RENEGOTIATION_INFO_SCSV);
}
this.secureRenegotiation = secureRenegotiation;
this.supportedCipherSuites = cipherSuites;
this.supportedGroups = config.getSupportedGroups();
this.maxFragmentLength = config.get(DtlsConfig.DTLS_MAX_FRAGMENT_LENGTH);
this.truncateCertificatePath = config.get(DtlsConfig.DTLS_TRUNCATE_CLIENT_CERTIFICATE_PATH);
Expand Down Expand Up @@ -454,6 +481,7 @@ protected void receivedConnectionIdExtension(ConnectionIdExtension extension) th
* initiated by the client or not supported by the client.
*/
protected void verifyServerHelloExtensions(ServerHello message) throws HandshakeException {
boolean hasRenegotiationInfoExtension = false;
HelloExtensions serverExtensions = message.getExtensions();
if (serverExtensions != null && !serverExtensions.isEmpty()) {
HelloExtensions clientExtensions = clientHello.getExtensions();
Expand All @@ -463,6 +491,12 @@ protected void verifyServerHelloExtensions(ServerHello message) throws Handshake
} else {
for (HelloExtension serverExtension : serverExtensions.getExtensions()) {
if (clientExtensions.getExtension(serverExtension.getType()) == null) {
if (serverExtension.getType() == HelloExtension.ExtensionType.RENEGOTIATION_INFO) {
hasRenegotiationInfoExtension = true;
if (secureRenegotiation != DtlsSecureRenegotiation.NONE) {
continue;
}
}
throw new HandshakeException(
"Server wants " + serverExtension.getType() + ", but client didn't propose it!",
new AlertMessage(AlertLevel.FATAL, AlertDescription.UNSUPPORTED_EXTENSION));
Expand Down Expand Up @@ -519,6 +553,12 @@ protected void verifyServerHelloExtensions(ServerHello message) throws Handshake
}
session.setSendCertificateType(clientCertificateType);
}
if (hasRenegotiationInfoExtension) {
session.setSecureRengotiation(true);
} else if (secureRenegotiation == DtlsSecureRenegotiation.NEEDED) {
throw new HandshakeException("Server doesn't support secure renegotiation!",
new AlertMessage(AlertLevel.FATAL, AlertDescription.HANDSHAKE_FAILURE));
}
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -448,4 +448,22 @@ public SupportedEllipticCurvesExtension getSupportedEllipticCurvesExtension() {
return extensions.getExtension(ExtensionType.ELLIPTIC_CURVES);
}

/**
* Checks, if either the {@link RenegotiationInfoExtension} or the
* {@link CipherSuite#TLS_EMPTY_RENEGOTIATION_INFO_SCSV} is available.
*
* Californium doesn't support renegotiation at all, but RFC5746 requests to
* update to a minimal version of RFC 5746.
*
* See <a href="https://tools.ietf.org/html/rfc5746" target="_blank">RFC
* 5746</a> for additional details.
*
* @return {@code true}, if available, {@code false}, if not.
* @since 3.8
*/
public boolean hasRenegotiationInfo() {
return hasRenegotiationInfoExtension()
|| supportedCipherSuites.contains(CipherSuite.TLS_EMPTY_RENEGOTIATION_INFO_SCSV);
}

}
Loading

0 comments on commit 0d741b2

Please sign in to comment.