Repository: eclipse/leshan
Pull request #932 (2020-11-18 17:54:32)

Integrate Californium 2.5.0


Patch:
diff --git a/leshan-client-cf/src/main/java/org/eclipse/leshan/client/californium/CaliforniumEndpointsManager.java b/leshan-client-cf/src/main/java/org/eclipse/leshan/client/californium/CaliforniumEndpointsManager.java
index 88497817..0c3b1d8d 100644
--- a/leshan-client-cf/src/main/java/org/eclipse/leshan/client/californium/CaliforniumEndpointsManager.java
+++ b/leshan-client-cf/src/main/java/org/eclipse/leshan/client/californium/CaliforniumEndpointsManager.java
@@ -33,8 +33,9 @@ import org.eclipse.californium.elements.auth.RawPublicKeyIdentity;
 import org.eclipse.californium.scandium.DTLSConnector;
 import org.eclipse.californium.scandium.config.DtlsConnectorConfig.Builder;
 import org.eclipse.californium.scandium.dtls.cipher.CipherSuite;
-import org.eclipse.californium.scandium.dtls.pskstore.StaticPskStore;
-import org.eclipse.californium.scandium.dtls.rpkstore.TrustedRpkStore;
+import org.eclipse.californium.scandium.dtls.pskstore.AdvancedSinglePskStore;
+import org.eclipse.californium.scandium.dtls.x509.NewAdvancedCertificateVerifier;
+import org.eclipse.californium.scandium.dtls.x509.StaticNewAdvancedCertificateVerifier;
 import org.eclipse.leshan.client.EndpointsManager;
 import org.eclipse.leshan.client.servers.ServerIdentity;
 import org.eclipse.leshan.client.servers.ServerIdentity.Role;
@@ -102,8 +103,8 @@ public class CaliforniumEndpointsManager implements EndpointsManager {
 
             // Support PSK
             if (serverInfo.secureMode == SecurityMode.PSK) {
-                StaticPskStore staticPskStore = new StaticPskStore(serverInfo.pskId, serverInfo.pskKey);
-                newBuilder.setPskStore(staticPskStore);
+                AdvancedSinglePskStore staticPskStore = new AdvancedSinglePskStore(serverInfo.pskId, serverInfo.pskKey);
+                newBuilder.setAdvancedPskStore(staticPskStore);
                 serverIdentity = Identity.psk(serverInfo.getAddress(), serverInfo.pskId);
                 filterCipherSuites(newBuilder, dtlsConfigbuilder.getIncompleteConfig().getSupportedCipherSuites(), true,
                         false);
@@ -112,23 +113,9 @@ public class CaliforniumEndpointsManager implements EndpointsManager {
                 newBuilder.setIdentity(serverInfo.privateKey, serverInfo.publicKey);
                 // set RPK truststore
                 final PublicKey expectedKey = serverInfo.serverPublicKey;
-                newBuilder.setRpkTrustStore(new TrustedRpkStore() {
-                    @Override
-                    public boolean isTrusted(RawPublicKeyIdentity id) {
-                        PublicKey receivedKey = id.getKey();
-                        if (receivedKey == null) {
-                            LOG.warn("The server public key is null {}", id);
-                            return false;
-                        }
-                        if (!receivedKey.equals(expectedKey)) {
-                            LOG.debug(
-                                    "Server public key received does match with the expected one.\nReceived: {}\nExpected: {}",
-                                    receivedKey, expectedKey);
-                            return false;
-                        }
-                        return true;
-                    }
-                });
+                NewAdvancedCertificateVerifier rpkVerifier = new StaticNewAdvancedCertificateVerifier.Builder()
+                        .setTrustedRPKs(new RawPublicKeyIdentity(expectedKey)).build();
+                newBuilder.setAdvancedCertificateVerifier(rpkVerifier);
                 serverIdentity = Identity.rpk(serverInfo.getAddress(), expectedKey);
                 filterCipherSuites(newBuilder, dtlsConfigbuilder.getIncompleteConfig().getSupportedCipherSuites(),
                         false, true);
@@ -137,7 +124,8 @@ public class CaliforniumEndpointsManager implements EndpointsManager {
                 newBuilder.setIdentity(serverInfo.privateKey, new Certificate[] { serverInfo.clientCertificate });
 
                 // set X509 verifier
-                newBuilder.setCertificateVerifier(new DefaultLeshanCertificateVerifier(serverInfo.serverCertificate));
+                newBuilder.setAdvancedCertificateVerifier(
+                        new DefaultLeshanCertificateVerifier(serverInfo.serverCertificate));
                 serverIdentity = Identity.x509(serverInfo.getAddress(), EndpointContextUtil.extractCN(
                         ((X509Certificate) serverInfo.serverCertificate).getSubjectX500Principal().getName()));
                 filterCipherSuites(newBuilder, dtlsConfigbuilder.getIncompleteConfig().getSupportedCipherSuites(),
diff --git a/leshan-client-cf/src/main/java/org/eclipse/leshan/client/californium/DefaultLeshanCertificateVerifier.java b/leshan-client-cf/src/main/java/org/eclipse/leshan/client/californium/DefaultLeshanCertificateVerifier.java
index a0d6d634..f785c9c5 100644
--- a/leshan-client-cf/src/main/java/org/eclipse/leshan/client/californium/DefaultLeshanCertificateVerifier.java
+++ b/leshan-client-cf/src/main/java/org/eclipse/leshan/client/californium/DefaultLeshanCertificateVerifier.java
@@ -1,35 +1,58 @@
 package org.eclipse.leshan.client.californium;
 
+import java.security.cert.Certificate;
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.security.auth.x500.X500Principal;
+
 import org.eclipse.californium.scandium.dtls.AlertMessage;
 import org.eclipse.californium.scandium.dtls.AlertMessage.AlertDescription;
 import org.eclipse.californium.scandium.dtls.AlertMessage.AlertLevel;
 import org.eclipse.californium.scandium.dtls.CertificateMessage;
+import org.eclipse.californium.scandium.dtls.CertificateType;
+import org.eclipse.californium.scandium.dtls.CertificateVerificationResult;
+import org.eclipse.californium.scandium.dtls.ConnectionId;
 import org.eclipse.californium.scandium.dtls.DTLSSession;
 import org.eclipse.californium.scandium.dtls.HandshakeException;
-import org.eclipse.californium.scandium.dtls.x509.CertificateVerifier;
+import org.eclipse.californium.scandium.dtls.HandshakeResultHandler;
+import org.eclipse.californium.scandium.dtls.x509.NewAdvancedCertificateVerifier;
+import org.eclipse.californium.scandium.util.ServerNames;
 
-import java.security.cert.Certificate;
-import java.security.cert.X509Certificate;
+public class DefaultLeshanCertificateVerifier implements NewAdvancedCertificateVerifier {
 
-public class DefaultLeshanCertificateVerifier implements CertificateVerifier {
     private final Certificate expectedServerCertificate;
+    private final List<CertificateType> supportedCertificateType;
 
     public DefaultLeshanCertificateVerifier(Certificate expectedServerCertificate) {
         this.expectedServerCertificate = expectedServerCertificate;
+        this.supportedCertificateType = new ArrayList<>(1);
+        this.supportedCertificateType.add(CertificateType.X_509);
     }
 
     @Override
-    public void verifyCertificate(CertificateMessage message, DTLSSession session)
-            throws HandshakeException {
+    public List<X500Principal> getAcceptedIssuers() {
+        return null;
+    }
+
+    @Override
+    public List<CertificateType> getSupportedCertificateType() {
+        return supportedCertificateType;
+    }
+
+    @Override
+    public CertificateVerificationResult verifyCertificate(ConnectionId cid, ServerNames serverName,
+            Boolean clientUsage, boolean truncateCertificatePath, CertificateMessage message, DTLSSession session) {
         // As specify in the LWM2M spec 1.0, we only support "domain-issued certificate" usage
         // Defined in : https://tools.ietf.org/html/rfc6698#section-2.1.1 (3 -- Certificate usage 3)
 
         // Get server certificate from certificate message
-        if (message.getCertificateChain().getCertificates().size() == 0) {
+        if (message.getCertificateChain() == null || message.getCertificateChain().getCertificates().size() == 0) {
             AlertMessage alert = new AlertMessage(AlertLevel.FATAL, AlertDescription.BAD_CERTIFICATE,
                     session.getPeer());
-            throw new HandshakeException(
+            HandshakeException handshakeException = new HandshakeException(
                     "Certificate chain could not be validated : server cert chain is empty", alert);
+            return new CertificateVerificationResult(cid, handshakeException, null);
         }
         Certificate receivedServerCertificate = message.getCertificateChain().getCertificates().get(0);
 
@@ -37,14 +60,17 @@ public class DefaultLeshanCertificateVerifier implements CertificateVerifier {
         if (!expectedServerCertificate.equals(receivedServerCertificate)) {
             AlertMessage alert = new AlertMessage(AlertLevel.FATAL, AlertDescription.BAD_CERTIFICATE,
                     session.getPeer());
-            throw new HandshakeException(
+            HandshakeException handshakeException = new HandshakeException(
                     "Certificate chain could not be validated: server certificate does not match expected one ('domain-issue certificate' usage)",
                     alert);
+            return new CertificateVerificationResult(cid, handshakeException, null);
         }
+
+        return new CertificateVerificationResult(cid, message.getCertificateChain(), null);
     }
 
     @Override
-    public X509Certificate[] getAcceptedIssuers() {
-        return null;
+    public void setResultHandler(HandshakeResultHandler resultHandler) {
+        // we don't use async mode.
     }
 }
diff --git a/leshan-client-cf/src/main/java/org/eclipse/leshan/client/californium/SecurityObjectPskStore.java b/leshan-client-cf/src/main/java/org/eclipse/leshan/client/californium/SecurityObjectPskStore.java
deleted file mode 100644
index 2d763265..00000000
--- a/leshan-client-cf/src/main/java/org/eclipse/leshan/client/californium/SecurityObjectPskStore.java
+++ /dev/null
@@ -1,127 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2015 Sierra Wireless and others.
- * 
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v2.0
- * and Eclipse Distribution License v1.0 which accompany this distribution.
- * 
- * The Eclipse Public License is available at
- *    http://www.eclipse.org/legal/epl-v20.html
- * and the Eclipse Distribution License is available at
- *    http://www.eclipse.org/org/documents/edl-v10.html.
- * 
- * Contributors:
- *     Sierra Wireless - initial API and implementation
- *     Achim Kraus (Bosch Software Innovations GmbH) - use ServerIdentity.SYSTEM
- *******************************************************************************/
-package org.eclipse.leshan.client.californium;
-
-import static org.eclipse.leshan.client.servers.ServerIdentity.SYSTEM;
-import static org.eclipse.leshan.core.LwM2mId.*;
-
-import java.net.InetSocketAddress;
-import java.net.URI;
-import java.net.URISyntaxException;
-import java.util.Arrays;
-
-import javax.crypto.SecretKey;
-
-import org.eclipse.californium.scandium.dtls.PskPublicInformation;
-import org.eclipse.californium.scandium.dtls.pskstore.PskStore;
-import org.eclipse.californium.scandium.util.SecretUtil;
-import org.eclipse.californium.scandium.util.ServerNames;
-import org.eclipse.leshan.client.resource.LwM2mObjectEnabler;
-import org.eclipse.leshan.client.servers.ServerInfo;
-import org.eclipse.leshan.core.SecurityMode;
-import org.eclipse.leshan.core.node.LwM2mObject;
-import org.eclipse.leshan.core.node.LwM2mObjectInstance;
-import org.eclipse.leshan.core.request.ReadRequest;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-/**
- * a {@link PskStore} which search PSK credentials in Lwm2m Security object.
- */
-public class SecurityObjectPskStore implements PskStore {
-    private static final Logger LOG = LoggerFactory.getLogger(SecurityObjectPskStore.class);
-
-    protected final LwM2mObjectEnabler securityEnabler;
-
-    /**
-     * Warning : The securityEnabler should not contains 2 or more entries with the same identity. This is not a LWM2M
-     * specification constraint but an implementation limitation.
-     */
-    public SecurityObjectPskStore(LwM2mObjectEnabler securityEnabler) {
-        this.securityEnabler = securityEnabler;
-    }
-
-    @Override
-    public SecretKey getKey(PskPublicInformation identity) {
-        if (identity == null)
-            return null;
-
-        byte[] res = null;
-
-        LwM2mObject securities = (LwM2mObject) securityEnabler.read(SYSTEM, new ReadRequest(SECURITY)).getContent();
-        for (LwM2mObjectInstance security : securities.getInstances().values()) {
-            long securityMode = (long) security.getResource(SEC_SECURITY_MODE).getValue();
-            if (securityMode == SecurityMode.PSK.code) // psk
-            {
-                byte[] pskIdentity = (byte[]) security.getResource(SEC_PUBKEY_IDENTITY).getValue();
-                if (Arrays.equals(identity.getBytes(), pskIdentity)) {
-                    if (res == null) {
-                        // we continue to check if the is duplication
-                        res = (byte[]) security.getResource(SEC_SECRET_KEY).getValue();
-                    } else {
-                        LOG.warn("There is several security object instance with the same psk identity : '{}'",
-                                identity);
-                        // we find 1 duplication and warn for it no need to continue.
-                        return SecretUtil.create(res, "PSK");
-                    }
-                }
-            }
-        }
-        if (res != null) {
-            return SecretUtil.create(res, "PSK");
-        } else {
-            return null;
-        }
-
-    }
-
-    @Override
-    public SecretKey getKey(ServerNames serverNames, PskPublicInformation identity) {
-        // serverNames is not supported
-        return getKey(identity);
-    }
-
-    @Override
-    public PskPublicInformation getIdentity(InetSocketAddress inetAddress) {
-        if (inetAddress == null)
-            return null;
-
-        LwM2mObject securities = (LwM2mObject) securityEnabler.read(SYSTEM, new ReadRequest(SECURITY)).getContent();
-        for (LwM2mObjectInstance security : securities.getInstances().values()) {
-            long securityMode = (long) security.getResource(SEC_SECURITY_MODE).getValue();
-            if (securityMode == SecurityMode.PSK.code) {
-                try {
-                    URI uri = new URI((String) security.getResource(SEC_SERVER_URI).getValue());
-                    if (inetAddress.equals(ServerInfo.getAddress(uri))) {
-                        byte[] pskIdentity = (byte[]) security.getResource(SEC_PUBKEY_IDENTITY).getValue();
-                        return new PskPublicInformation(new String(pskIdentity));
-                    }
-                } catch (URISyntaxException e) {
-                    LOG.error(String.format("Invalid URI %s", (String) security.getResource(SEC_SERVER_URI).getValue()),
-                            e);
-                }
-            }
-        }
-        return null;
-    }
-
-    @Override
-    public PskPublicInformation getIdentity(InetSocketAddress peerAddress, ServerNames virtualHost) {
-        // TODO should we support SNI ?
-        throw new UnsupportedOperationException();
-    }
-}
diff --git a/leshan-server-cf/src/main/java/org/eclipse/leshan/server/californium/LeshanServerBuilder.java b/leshan-server-cf/src/main/java/org/eclipse/leshan/server/californium/LeshanServerBuilder.java
index 81c4ad78..11a97d7d 100644
--- a/leshan-server-cf/src/main/java/org/eclipse/leshan/server/californium/LeshanServerBuilder.java
+++ b/leshan-server-cf/src/main/java/org/eclipse/leshan/server/californium/LeshanServerBuilder.java
@@ -34,6 +34,7 @@ import org.eclipse.californium.scandium.DTLSConnector;
 import org.eclipse.californium.scandium.config.DtlsConnectorConfig;
 import org.eclipse.californium.scandium.config.DtlsConnectorConfig.Builder;
 import org.eclipse.californium.scandium.dtls.CertificateType;
+import org.eclipse.californium.scandium.dtls.x509.BridgeCertificateVerifier;
 import org.eclipse.leshan.core.LwM2m;
 import org.eclipse.leshan.core.californium.DefaultEndpointFactory;
 import org.eclipse.leshan.core.californium.EndpointFactory;
@@ -401,6 +402,7 @@ public class LeshanServerBuilder {
      * @return the LWM2M server.
      * @throws IllegalStateException if builder configuration is not consistent.
      */
+    @SuppressWarnings("deprecation")
     public LeshanServer build() {
         if (localAddress == null)
             localAddress = new InetSocketAddress(LwM2m.DEFAULT_COAP_PORT);
@@ -446,7 +448,7 @@ public class LeshanServerBuilder {
                 LOG.warn(
                         "PskStore should be automatically set by Leshan. Using a custom implementation is not advised.");
             } else if (securityStore != null) {
-                dtlsConfigBuilder.setPskStore(new LwM2mPskStore(this.securityStore, registrationStore));
+                dtlsConfigBuilder.setAdvancedPskStore(new LwM2mPskStore(this.securityStore, registrationStore));
             }
 
             // Handle secure address
@@ -467,20 +469,6 @@ public class LeshanServerBuilder {
             if (incompleteConfig.getStaleConnectionThreshold() == null)
                 dtlsConfigBuilder.setStaleConnectionThreshold(coapConfig.getLong(Keys.MAX_PEER_INACTIVITY_PERIOD));
 
-            // handle trusted certificates
-            if (trustedCertificates != null) {
-                if (incompleteConfig.getCertificateVerifier() == null) {
-                    if (incompleteConfig.getTrustStore() == null) {
-                        dtlsConfigBuilder.setTrustStore(trustedCertificates);
-                    } else if (!Arrays.equals(trustedCertificates, incompleteConfig.getTrustStore())) {
-                        throw new IllegalStateException(String.format(
-                                "Configuration conflict between LeshanBuilder and DtlsConnectorConfig.Builder for trusted Certificates (trustStore) : \n%s != \n%s",
-                                Arrays.toString(trustedCertificates),
-                                Arrays.toString(incompleteConfig.getTrustStore())));
-                    }
-                }
-            }
-
             // check conflict for private key
             if (privateKey != null) {
                 if (incompleteConfig.getPrivateKey() != null && !incompleteConfig.getPrivateKey().equals(privateKey)) {
@@ -497,10 +485,6 @@ public class LeshanServerBuilder {
                                 publicKey, incompleteConfig.getPublicKey()));
                     }
 
-                    // by default trust all RPK
-                    if (incompleteConfig.getRpkTrustStore() == null) {
-                        dtlsConfigBuilder.setRpkTrustAll();
-                    }
                     dtlsConfigBuilder.setIdentity(privateKey, publicKey);
                 }
                 // if in X.509 mode set the private key, certificate chain, public key is extracted from the certificate
@@ -512,13 +496,47 @@ public class LeshanServerBuilder {
                                 Arrays.toString(certificateChain), incompleteConfig.getCertificateChain()));
                     }
 
-                    // by default trust all RPK
-                    if (incompleteConfig.getRpkTrustStore() == null) {
-                        dtlsConfigBuilder.setRpkTrustAll();
-                    }
                     dtlsConfigBuilder.setIdentity(privateKey, certificateChain, CertificateType.X_509,
                             CertificateType.RAW_PUBLIC_KEY);
                 }
+
+                // handle trusted certificates or RPK
+                if (incompleteConfig.getAdvancedCertificateVerifier() != null) {
+                    if (trustedCertificates != null) {
+                        throw new IllegalStateException(
+                                "Configuration conflict between LeshanBuilder and DtlsConnectorConfig.Builder: if a AdvancedCertificateVerifier is set, trustedCertificates must not be set.");
+                    }
+                } else {
+                    BridgeCertificateVerifier.Builder verifierBuilder = new BridgeCertificateVerifier.Builder();
+                    if (incompleteConfig.getRpkTrustStore() != null) {
+                        verifierBuilder.setTrustedRPKs(incompleteConfig.getRpkTrustStore());
+                    } else {
+                        // by default trust all RPK
+                        verifierBuilder.setTrustAllRPKs();
+                    }
+                    if (incompleteConfig.getTrustStore() != null) {
+                        if (trustedCertificates != null
+                                && !Arrays.equals(trustedCertificates, incompleteConfig.getTrustStore())) {
+                            throw new IllegalStateException(String.format(
+                                    "Configuration conflict between LeshanBuilder and DtlsConnectorConfig.Builder for trusted Certificates (trustStore) : \n%s != \n%s",
+                                    Arrays.toString(trustedCertificates),
+                                    Arrays.toString(incompleteConfig.getTrustStore())));
+                        }
+                        verifierBuilder.setTrustedCertificates(incompleteConfig.getTrustStore());
+                    } else {
+                        if (trustedCertificates != null) {
+                            verifierBuilder.setTrustedCertificates(trustedCertificates);
+                        }
+                    }
+                    if (incompleteConfig.getCertificateVerifier() != null) {
+                        if (trustedCertificates != null) {
+                            throw new IllegalStateException(
+                                    "Configuration conflict between LeshanBuilder and DtlsConnectorConfig.Builder: if a CertificateVerifier is set, trustedCertificates must not be set.");
+                        }
+                        verifierBuilder.setCertificateVerifier(incompleteConfig.getCertificateVerifier());
+                    }
+                    dtlsConfigBuilder.setAdvancedCertificateVerifier(verifierBuilder.build());
+                }
             }
 
             // Deactivate SNI by default
diff --git a/leshan-server-cf/src/main/java/org/eclipse/leshan/server/californium/LwM2mPskStore.java b/leshan-server-cf/src/main/java/org/eclipse/leshan/server/californium/LwM2mPskStore.java
index a26de87a..0edff11a 100644
--- a/leshan-server-cf/src/main/java/org/eclipse/leshan/server/californium/LwM2mPskStore.java
+++ b/leshan-server-cf/src/main/java/org/eclipse/leshan/server/californium/LwM2mPskStore.java
@@ -19,8 +19,10 @@ import java.net.InetSocketAddress;
 
 import javax.crypto.SecretKey;
 
+import org.eclipse.californium.scandium.dtls.ConnectionId;
 import org.eclipse.californium.scandium.dtls.PskPublicInformation;
-import org.eclipse.californium.scandium.dtls.pskstore.PskStore;
+import org.eclipse.californium.scandium.dtls.PskSecretResult;
+import org.eclipse.californium.scandium.dtls.pskstore.AdvancedPskStore;
 import org.eclipse.californium.scandium.util.SecretUtil;
 import org.eclipse.californium.scandium.util.ServerNames;
 import org.eclipse.leshan.server.registration.Registration;
@@ -29,9 +31,9 @@ import org.eclipse.leshan.server.security.SecurityInfo;
 import org.eclipse.leshan.server.security.SecurityStore;
 
 /**
- * A {@link PskStore} which retrieve PSK information from Leshan {@link SecurityStore}.
+ * A {@link AdvancedPskStore} which retrieve PSK information from Leshan {@link SecurityStore}.
  */
-public class LwM2mPskStore implements PskStore {
+public class LwM2mPskStore implements AdvancedPskStore {
 
     private SecurityStore securityStore;
     private RegistrationStore registrationStore;
@@ -46,31 +48,37 @@ public class LwM2mPskStore implements PskStore {
     }
 
     @Override
-    public SecretKey getKey(PskPublicInformation identity) {
+    public boolean hasEcdhePskSupported() {
+        return true;
+    }
+
+    @Override
+    public PskSecretResult requestPskSecretResult(ConnectionId cid, ServerNames serverName,
+            PskPublicInformation identity, String hmacAlgorithm, SecretKey otherSecret, byte[] seed) {
         if (securityStore == null)
             return null;
 
         SecurityInfo info = securityStore.getByIdentity(identity.getPublicInfoAsString());
         if (info == null || info.getPreSharedKey() == null) {
-            return null;
+            return new PskSecretResult(cid, identity, null);
         } else {
             // defensive copy
-            return SecretUtil.create(info.getPreSharedKey(), "PSK");
+            return new PskSecretResult(cid, identity, SecretUtil.create(info.getPreSharedKey(), "PSK"));
         }
     }
 
     @Override
-    public SecretKey getKey(ServerNames serverNames, PskPublicInformation identity) {
-        // serverNames is not supported
-        return getKey(identity);
+    public void setResultHandler(
+            @SuppressWarnings("deprecation") org.eclipse.californium.scandium.dtls.PskSecretResultHandler resultHandler) {
+        // we don't use async mode.
     }
 
     @Override
-    public PskPublicInformation getIdentity(InetSocketAddress inetAddress) {
+    public PskPublicInformation getIdentity(InetSocketAddress peerAddress, ServerNames virtualHost) {
         if (registrationStore == null)
             return null;
 
-        Registration registration = registrationStore.getRegistrationByAdress(inetAddress);
+        Registration registration = registrationStore.getRegistrationByAdress(peerAddress);
         if (registration != null) {
             SecurityInfo securityInfo = securityStore.getByEndpoint(registration.getEndpoint());
             if (securityInfo != null) {
@@ -80,10 +88,4 @@ public class LwM2mPskStore implements PskStore {
         }
         return null;
     }
-
-    @Override
-    public PskPublicInformation getIdentity(InetSocketAddress peerAddress, ServerNames virtualHost) {
-        // TODO should we support SNI ?
-        throw new UnsupportedOperationException();
-    }
 }
diff --git a/leshan-server-cf/src/main/java/org/eclipse/leshan/server/californium/bootstrap/LeshanBootstrapServerBuilder.java b/leshan-server-cf/src/main/java/org/eclipse/leshan/server/californium/bootstrap/LeshanBootstrapServerBuilder.java
index c63cad23..67337e12 100644
--- a/leshan-server-cf/src/main/java/org/eclipse/leshan/server/californium/bootstrap/LeshanBootstrapServerBuilder.java
+++ b/leshan-server-cf/src/main/java/org/eclipse/leshan/server/californium/bootstrap/LeshanBootstrapServerBuilder.java
@@ -31,6 +31,7 @@ import org.eclipse.californium.scandium.DTLSConnector;
 import org.eclipse.californium.scandium.config.DtlsConnectorConfig;
 import org.eclipse.californium.scandium.config.DtlsConnectorConfig.Builder;
 import org.eclipse.californium.scandium.dtls.CertificateType;
+import org.eclipse.californium.scandium.dtls.x509.BridgeCertificateVerifier;
 import org.eclipse.leshan.core.LwM2m;
 import org.eclipse.leshan.core.californium.DefaultEndpointFactory;
 import org.eclipse.leshan.core.californium.EndpointFactory;
@@ -398,6 +399,7 @@ public class LeshanBootstrapServerBuilder {
      * @return the LWM2M Bootstrap server.
      * @throws IllegalStateException if builder configuration is not consistent.
      */
+    @SuppressWarnings("deprecation")
     public LeshanBootstrapServer build() {
         if (localAddress == null)
             localAddress = new InetSocketAddress(LwM2m.DEFAULT_COAP_PORT);
@@ -441,7 +443,7 @@ public class LeshanBootstrapServerBuilder {
                 LOG.warn(
                         "PskStore should be automatically set by Leshan. Using a custom implementation is not advised.");
             } else if (securityStore != null) {
-                dtlsConfigBuilder.setPskStore(new LwM2mBootstrapPskStore(securityStore));
+                dtlsConfigBuilder.setAdvancedPskStore(new LwM2mBootstrapPskStore(securityStore));
             }
 
             // Handle secure address
@@ -462,23 +464,6 @@ public class LeshanBootstrapServerBuilder {
             if (incompleteConfig.getStaleConnectionThreshold() == null)
                 dtlsConfigBuilder.setStaleConnectionThreshold(coapConfig.getLong(Keys.MAX_PEER_INACTIVITY_PERIOD));
 
-            // handle trusted certificates
-            if (trustedCertificates != null) {
-                if (incompleteConfig.getCertificateVerifier() == null) {
-                    if (incompleteConfig.getTrustStore() == null) {
-                        dtlsConfigBuilder.setTrustStore(trustedCertificates);
-                    } else if (!Arrays.equals(trustedCertificates, incompleteConfig.getTrustStore())) {
-                        throw new IllegalStateException(String.format(
-                                "Configuration conflict between LeshanBuilder and DtlsConnectorConfig.Builder for trusted Certificates (trustStore) : \n%s != \n%s",
-                                Arrays.toString(trustedCertificates),
-                                Arrays.toString(incompleteConfig.getTrustStore())));
-                    }
-                } else if (trustedCertificates != null) {
-                    throw new IllegalStateException(
-                            "Configuration conflict between LeshanBuilder and DtlsConnectorConfig.Builder: if a CertificateVerifier is set, trustedCertificates must not be set.");
-                }
-            }
-
             if (privateKey != null) {
                 // check conflict for private key
                 if (incompleteConfig.getPrivateKey() != null && !incompleteConfig.getPrivateKey().equals(privateKey)) {
@@ -494,10 +479,6 @@ public class LeshanBootstrapServerBuilder {
                                 "Configuration conflict between LeshanBuilder and DtlsConnectorConfig.Builder for public key: %s != %s",
                                 publicKey, incompleteConfig.getPublicKey()));
                     }
-                    // by default trust all RPK
-                    if (incompleteConfig.getRpkTrustStore() == null) {
-                        dtlsConfigBuilder.setRpkTrustAll();
-                    }
                     dtlsConfigBuilder.setIdentity(privateKey, publicKey);
                 }
                 // if in X.509 mode set the private key, certificate chain, public key is extracted from the certificate
@@ -509,13 +490,47 @@ public class LeshanBootstrapServerBuilder {
                                 Arrays.toString(certificateChain), incompleteConfig.getCertificateChain()));
                     }
 
-                    // by default trust all RPK
-                    if (incompleteConfig.getRpkTrustStore() == null) {
-                        dtlsConfigBuilder.setRpkTrustAll();
-                    }
                     dtlsConfigBuilder.setIdentity(privateKey, certificateChain, CertificateType.X_509,
                             CertificateType.RAW_PUBLIC_KEY);
                 }
+
+                // handle trusted certificates or RPK
+                if (incompleteConfig.getAdvancedCertificateVerifier() != null) {
+                    if (trustedCertificates != null) {
+                        throw new IllegalStateException(
+                                "Configuration conflict between LeshanBuilder and DtlsConnectorConfig.Builder: if a AdvancedCertificateVerifier is set, trustedCertificates must not be set.");
+                    }
+                } else {
+                    BridgeCertificateVerifier.Builder verifierBuilder = new BridgeCertificateVerifier.Builder();
+                    if (incompleteConfig.getRpkTrustStore() != null) {
+                        verifierBuilder.setTrustedRPKs(incompleteConfig.getRpkTrustStore());
+                    } else {
+                        // by default trust all RPK
+                        verifierBuilder.setTrustAllRPKs();
+                    }
+                    if (incompleteConfig.getTrustStore() != null) {
+                        if (trustedCertificates != null
+                                && !Arrays.equals(trustedCertificates, incompleteConfig.getTrustStore())) {
+                            throw new IllegalStateException(String.format(
+                                    "Configuration conflict between LeshanBuilder and DtlsConnectorConfig.Builder for trusted Certificates (trustStore) : \n%s != \n%s",
+                                    Arrays.toString(trustedCertificates),
+                                    Arrays.toString(incompleteConfig.getTrustStore())));
+                        }
+                        verifierBuilder.setTrustedCertificates(incompleteConfig.getTrustStore());
+                    } else {
+                        if (trustedCertificates != null) {
+                            verifierBuilder.setTrustedCertificates(trustedCertificates);
+                        }
+                    }
+                    if (incompleteConfig.getCertificateVerifier() != null) {
+                        if (trustedCertificates != null) {
+                            throw new IllegalStateException(
+                                    "Configuration conflict between LeshanBuilder and DtlsConnectorConfig.Builder: if a CertificateVerifier is set, trustedCertificates must not be set.");
+                        }
+                        verifierBuilder.setCertificateVerifier(incompleteConfig.getCertificateVerifier());
+                    }
+                    dtlsConfigBuilder.setAdvancedCertificateVerifier(verifierBuilder.build());
+                }
             }
 
             // Bootstrap Server acts as Server only : It does not need to initiate handshake
diff --git a/leshan-server-cf/src/main/java/org/eclipse/leshan/server/californium/bootstrap/LwM2mBootstrapPskStore.java b/leshan-server-cf/src/main/java/org/eclipse/leshan/server/californium/bootstrap/LwM2mBootstrapPskStore.java
index aeb05c32..a2e8502e 100644
--- a/leshan-server-cf/src/main/java/org/eclipse/leshan/server/californium/bootstrap/LwM2mBootstrapPskStore.java
+++ b/leshan-server-cf/src/main/java/org/eclipse/leshan/server/californium/bootstrap/LwM2mBootstrapPskStore.java
@@ -19,8 +19,10 @@ import java.net.InetSocketAddress;
 
 import javax.crypto.SecretKey;
 
+import org.eclipse.californium.scandium.dtls.ConnectionId;
 import org.eclipse.californium.scandium.dtls.PskPublicInformation;
-import org.eclipse.californium.scandium.dtls.pskstore.PskStore;
+import org.eclipse.californium.scandium.dtls.PskSecretResult;
+import org.eclipse.californium.scandium.dtls.pskstore.AdvancedPskStore;
 import org.eclipse.californium.scandium.util.SecretUtil;
 import org.eclipse.californium.scandium.util.ServerNames;
 import org.eclipse.leshan.server.security.BootstrapSecurityStore;
@@ -32,7 +34,7 @@ import org.eclipse.leshan.server.security.SecurityInfo;
  * Only supports getting the PSK key for a given identity. (Getting identity from IP only makes sense when we initiate
  * DTLS Connection) side.)
  */
-public class LwM2mBootstrapPskStore implements PskStore {
+public class LwM2mBootstrapPskStore implements AdvancedPskStore {
 
     private BootstrapSecurityStore bsSecurityStore;
 
@@ -41,25 +43,27 @@ public class LwM2mBootstrapPskStore implements PskStore {
     }
 
     @Override
-    public SecretKey getKey(PskPublicInformation identity) {
+    public boolean hasEcdhePskSupported() {
+        return true;
+    }
+
+    @Override
+    public PskSecretResult requestPskSecretResult(ConnectionId cid, ServerNames serverName,
+            PskPublicInformation identity, String hmacAlgorithm, SecretKey otherSecret, byte[] seed) {
         SecurityInfo info = bsSecurityStore.getByIdentity(identity.getPublicInfoAsString());
         if (info == null || info.getPreSharedKey() == null) {
-            return null;
+            return new PskSecretResult(cid, identity, null);
         } else {
             // defensive copy
-            return SecretUtil.create(info.getPreSharedKey(), "PSK");
+            return new PskSecretResult(cid, identity, SecretUtil.create(info.getPreSharedKey(), "PSK"));
         }
-    }
 
-    @Override
-    public SecretKey getKey(ServerNames serverNames, PskPublicInformation identity) {
-        // serverNames is not supported
-        return getKey(identity);
     }
 
     @Override
-    public PskPublicInformation getIdentity(InetSocketAddress inetAddress) {
-        throw new UnsupportedOperationException("Getting PSK Id by IP addresss dos not make sense on BS server side.");
+    public void setResultHandler(
+            @SuppressWarnings("deprecation") org.eclipse.californium.scandium.dtls.PskSecretResultHandler resultHandler) {
+        // we don't use async mode.
     }
 
     @Override
diff --git a/pom.xml b/pom.xml
index aa3e7f1f..808e7925 100644
--- a/pom.xml
+++ b/pom.xml
@@ -108,7 +108,7 @@ Contributors:
         <test.exclusion.pattern>**/Redis*.java</test.exclusion.pattern>
 
         <!-- dependencies version -->
-        <californium.version>2.4.1</californium.version>
+        <californium.version>2.5.0</californium.version>
         <logback.version>1.2.3</logback.version>
         <slf4j.api.version>1.7.30</slf4j.api.version>
         <jetty.version>9.4.34.v20201102</jetty.version>


Test patch:
diff --git a/leshan-integration-tests/src/test/java/org/eclipse/leshan/integration/tests/SecureIntegrationTestHelper.java b/leshan-integration-tests/src/test/java/org/eclipse/leshan/integration/tests/SecureIntegrationTestHelper.java
index a316560e..34537b72 100644
--- a/leshan-integration-tests/src/test/java/org/eclipse/leshan/integration/tests/SecureIntegrationTestHelper.java
+++ b/leshan-integration-tests/src/test/java/org/eclipse/leshan/integration/tests/SecureIntegrationTestHelper.java
@@ -48,9 +48,10 @@ import org.eclipse.californium.core.observe.ObservationStore;
 import org.eclipse.californium.scandium.DTLSConnector;
 import org.eclipse.californium.scandium.config.DtlsConnectorConfig;
 import org.eclipse.californium.scandium.config.DtlsConnectorConfig.Builder;
+import org.eclipse.californium.scandium.dtls.ConnectionId;
 import org.eclipse.californium.scandium.dtls.PskPublicInformation;
 import org.eclipse.californium.scandium.dtls.cipher.CipherSuite;
-import org.eclipse.californium.scandium.dtls.pskstore.PskStore;
+import org.eclipse.californium.scandium.dtls.pskstore.AdvancedPskStore;
 import org.eclipse.leshan.client.californium.LeshanClientBuilder;
 import org.eclipse.leshan.client.engine.DefaultRegistrationEngineFactory;
 import org.eclipse.leshan.client.object.Device;
@@ -237,13 +238,13 @@ public class SecureIntegrationTestHelper extends IntegrationTestHelper {
                 Builder dtlsConfigBuilder = new Builder(dtlsConfig);
 
                 // tricks to be able to change psk information on the fly
-                @SuppressWarnings("deprecation")
-                PskStore pskStore = dtlsConfig.getPskStore();
+                AdvancedPskStore pskStore = dtlsConfig.getAdvancedPskStore();
                 if (pskStore != null) {
-                    PskPublicInformation identity = pskStore.getIdentity(null);
-                    SecretKey key = pskStore.getKey(identity);
+                    PskPublicInformation identity = pskStore.getIdentity(null, null);
+                    SecretKey key = pskStore
+                            .requestPskSecretResult(ConnectionId.EMPTY, null, identity, null, null, null).getSecret();
                     singlePSKStore = new SinglePSKStore(identity, key);
-                    dtlsConfigBuilder.setPskStore(singlePSKStore);
+                    dtlsConfigBuilder.setAdvancedPskStore(singlePSKStore);
                 }
                 builder.setConnector(new DTLSConnector(dtlsConfigBuilder.build()));
                 builder.setNetworkConfig(coapConfig);
diff --git a/leshan-integration-tests/src/test/java/org/eclipse/leshan/integration/tests/SinglePSKStore.java b/leshan-integration-tests/src/test/java/org/eclipse/leshan/integration/tests/SinglePSKStore.java
index a1de6c13..4ea89898 100644
--- a/leshan-integration-tests/src/test/java/org/eclipse/leshan/integration/tests/SinglePSKStore.java
+++ b/leshan-integration-tests/src/test/java/org/eclipse/leshan/integration/tests/SinglePSKStore.java
@@ -19,12 +19,14 @@ import java.net.InetSocketAddress;
 
 import javax.crypto.SecretKey;
 
+import org.eclipse.californium.scandium.dtls.ConnectionId;
 import org.eclipse.californium.scandium.dtls.PskPublicInformation;
-import org.eclipse.californium.scandium.dtls.pskstore.PskStore;
+import org.eclipse.californium.scandium.dtls.PskSecretResult;
+import org.eclipse.californium.scandium.dtls.pskstore.AdvancedPskStore;
 import org.eclipse.californium.scandium.util.SecretUtil;
 import org.eclipse.californium.scandium.util.ServerNames;
 
-public class SinglePSKStore implements PskStore {
+public class SinglePSKStore implements AdvancedPskStore {
 
     private PskPublicInformation identity;
     private SecretKey key;
@@ -40,24 +42,26 @@ public class SinglePSKStore implements PskStore {
     }
 
     @Override
-    public SecretKey getKey(PskPublicInformation identity) {
-        return SecretUtil.create(key);
+    public boolean hasEcdhePskSupported() {
+        return true;
     }
 
     @Override
-    public SecretKey getKey(ServerNames serverName, PskPublicInformation identity) {
-        // we do not support SNI
-        return getKey(identity);
+    public PskSecretResult requestPskSecretResult(ConnectionId cid, ServerNames serverName,
+            PskPublicInformation identity, String hmacAlgorithm, SecretKey otherSecret, byte[] seed) {
+        SecretKey pskSecret = SecretUtil.create(key);
+        return new PskSecretResult(cid, identity, pskSecret);
     }
 
     @Override
-    public PskPublicInformation getIdentity(InetSocketAddress inetAddress) {
-        return identity;
+    public void setResultHandler(
+            @SuppressWarnings("deprecation") org.eclipse.californium.scandium.dtls.PskSecretResultHandler resultHandler) {
+        // we don't use async mode.
     }
 
     @Override
     public PskPublicInformation getIdentity(InetSocketAddress peerAddress, ServerNames virtualHost) {
-        throw new UnsupportedOperationException();
+        return identity;
     }
 
     public void setKey(byte[] key) {