Skip to content

Commit

Permalink
Certificate: add authentication usage check.
Browse files Browse the repository at this point in the history
  • Loading branch information
sbernard31 committed Apr 23, 2024
1 parent 9feae9e commit 5c8afbd
Show file tree
Hide file tree
Showing 8 changed files with 46 additions and 13 deletions.
Expand Up @@ -36,6 +36,7 @@
import org.eclipse.californium.scandium.dtls.x509.NewAdvancedCertificateVerifier;
import org.eclipse.californium.scandium.util.ServerNames;
import org.eclipse.leshan.core.security.certificate.verifier.X509CertificateVerifier;
import org.eclipse.leshan.core.security.certificate.verifier.X509CertificateVerifier.Role;

public class LwM2mCertificateVerifier implements NewAdvancedCertificateVerifier {

Expand Down Expand Up @@ -69,7 +70,8 @@ public CertificateVerificationResult verifyCertificate(ConnectionId cid, ServerN
try {
// verifyDestination is currently not used.
// The DTLS_VERIFY_SERVER_CERTIFICATES_SUBJECT is therefore set to transient.
certificateVerifier.verifyCertificate(message.getCertificateChain(), remotePeer);
certificateVerifier.verifyCertificate(message.getCertificateChain(), remotePeer,
clientUsage ? Role.CLIENT : Role.SERVER);
return new CertificateVerificationResult(cid, message.getCertificateChain(), null);
} catch (CertificateException exception) {
return new CertificateVerificationResult(cid, new HandshakeException("Unable to verify Certificate",
Expand Down
Expand Up @@ -66,4 +66,18 @@ protected void validateSubject(InetSocketAddress peerSocket, X509Certificate rec
throw new CertificateException(
"Certificate chain could not be validated - server identity does not match certificate");
}

protected void validateCertificateCanBeUsedForAuthentication(X509Certificate certificate,
Role certificateOwnerRole) {
switch (certificateOwnerRole) {
case CLIENT:
X509CertUtil.canBeUsedForAuthentication(certificate, true);
break;
case SERVER:
X509CertUtil.canBeUsedForAuthentication(certificate, false);
break;
default:
throw new IllegalStateException("Unsupported role " + certificateOwnerRole);
}
}
}
Expand Up @@ -70,12 +70,13 @@ public CaConstraintCertificateVerifier(Certificate caCertificate, X509Certificat
}

@Override
public CertPath verifyCertificate(CertPath remotePeerCertChain, InetSocketAddress remotePeerAddress)
throws CertificateException {
public CertPath verifyCertificate(CertPath remotePeerCertChain, InetSocketAddress remotePeerAddress,
Role remotePeerRole) throws CertificateException {

validateCertificateChainNotEmpty(remotePeerCertChain);
X509Certificate receivedServerCertificate = validateReceivedCertificateIsSupported(remotePeerCertChain);
validateNotDirectTrust(remotePeerCertChain);
validateCertificateCanBeUsedForAuthentication(receivedServerCertificate, remotePeerRole);

// - must do PKIX validation with trustStore
CertPath certPath;
Expand Down
Expand Up @@ -44,22 +44,29 @@ public DefaultCertificateVerifier(List<X509Certificate> trustedCertificates) {
}

@Override
public CertPath verifyCertificate(CertPath remotePeerCertChain, InetSocketAddress remotePeerAddress)
throws CertificateException {
public CertPath verifyCertificate(CertPath remotePeerCertChain, InetSocketAddress remotePeerAddress,
Role remotePeerRole) throws CertificateException {

if (trustedCertificates.isEmpty()) {
// In this case we trust anything.
return remotePeerCertChain;
}

validateCertificateChainNotEmpty(remotePeerCertChain);
X509Certificate receivedServerCertificate = validateReceivedCertificateIsSupported(remotePeerCertChain);
validateCertificateCanBeUsedForAuthentication(receivedServerCertificate, remotePeerRole);

// - must do PKIX validation with trustStore
CertPath certPath;
try {
return PKIValidator.applyPKIXValidation(remotePeerCertChain,
certPath = PKIValidator.applyPKIXValidation(remotePeerCertChain,
trustedCertificates.toArray(new X509Certificate[trustedCertificates.size()]));
} catch (GeneralSecurityException e) {
throw new CertificateException("Certificate chain could not be validated");
}

validateSubject(remotePeerAddress, receivedServerCertificate);

return certPath;
}
}
Expand Up @@ -53,8 +53,8 @@ public DomainIssuerCertificateVerifier(Certificate domainIssuerCertificate) {
}

@Override
public CertPath verifyCertificate(CertPath remotePeerCertChain, InetSocketAddress remotePeerAddress)
throws CertificateException {
public CertPath verifyCertificate(CertPath remotePeerCertChain, InetSocketAddress remotePeerAddress,
Role remotePeerRole) throws CertificateException {

validateCertificateChainNotEmpty(remotePeerCertChain);

Expand Down
Expand Up @@ -61,12 +61,13 @@ public ServiceCertificateConstraintCertificateVerifier(Certificate serviceCertif
}

@Override
public CertPath verifyCertificate(CertPath remotePeerCertChain, InetSocketAddress remotePeerAddress)
throws CertificateException {
public CertPath verifyCertificate(CertPath remotePeerCertChain, InetSocketAddress remotePeerAddress,
Role remotePeerRole) throws CertificateException {

validateCertificateChainNotEmpty(remotePeerCertChain);

X509Certificate receivedServerCertificate = validateReceivedCertificateIsSupported(remotePeerCertChain);
validateCertificateCanBeUsedForAuthentication(receivedServerCertificate, remotePeerRole);

// - must do PKIX validation with trustStore
CertPath certPath;
Expand Down
Expand Up @@ -58,11 +58,12 @@ public TrustAnchorAssertionCertificateVerifier(X509Certificate trustAnchor, Stri
}

@Override
public CertPath verifyCertificate(CertPath remotePeerCertChain, InetSocketAddress remotePeerAddress)
throws CertificateException {
public CertPath verifyCertificate(CertPath remotePeerCertChain, InetSocketAddress remotePeerAddress,
Role remotePeerRole) throws CertificateException {

validateCertificateChainNotEmpty(remotePeerCertChain);
X509Certificate receivedServerCertificate = validateReceivedCertificateIsSupported(remotePeerCertChain);
validateCertificateCanBeUsedForAuthentication(receivedServerCertificate, remotePeerRole);

// - must do PKIX validation with trustStore
CertPath certPath;
Expand Down
Expand Up @@ -21,6 +21,13 @@

public interface X509CertificateVerifier {

CertPath verifyCertificate(CertPath remotePeerCertChain, InetSocketAddress remotePeerAddress)
public enum Role {
// used for client certificate
CLIENT,
// used for server certificate
SERVER;
}

CertPath verifyCertificate(CertPath remotePeerCertChain, InetSocketAddress remotePeerAddress, Role remotePeerRole)
throws CertificateException;
}

0 comments on commit 5c8afbd

Please sign in to comment.