Search in sources :

Example 1 with CertificateVerificationResult

use of org.eclipse.californium.scandium.dtls.CertificateVerificationResult in project hono by eclipse.

the class DeviceRegistryBasedCertificateVerifier method verifyCertificate.

@Override
public CertificateVerificationResult verifyCertificate(final ConnectionId cid, final ServerNames serverName, final Boolean clientUsage, final boolean truncateCertificatePath, final CertificateMessage message, final DTLSSession session) {
    try {
        final CertPath certChain = message.getCertificateChain();
        if (certChain == null) {
            final AlertMessage alert = new AlertMessage(AlertLevel.FATAL, AlertDescription.BAD_CERTIFICATE, session.getPeer());
            throw new HandshakeException("RPK not supported", alert);
        }
        final var certificates = certChain.getCertificates();
        if (certificates.isEmpty()) {
            final AlertMessage alert = new AlertMessage(AlertLevel.FATAL, AlertDescription.BAD_CERTIFICATE, session.getPeer());
            throw new HandshakeException("client certificate chain must not be empty", alert);
        }
        if (clientUsage != null) {
            final Certificate clientCertificate = certificates.get(0);
            if (clientCertificate instanceof X509Certificate && !CertPathUtil.canBeUsedForAuthentication((X509Certificate) clientCertificate, clientUsage)) {
                final AlertMessage alert = new AlertMessage(AlertLevel.FATAL, AlertDescription.BAD_CERTIFICATE, session.getPeer());
                throw new HandshakeException("certificate cannot be used for client authentication", alert);
            }
        }
        adapter.runOnContext((v) -> validateCertificateAndLoadDevice(cid, certChain, session));
        return null;
    } catch (HandshakeException e) {
        LOG.debug("certificate validation failed", e);
        return new CertificateVerificationResult(cid, e, null);
    }
}
Also used : CertPath(java.security.cert.CertPath) HandshakeException(org.eclipse.californium.scandium.dtls.HandshakeException) AlertMessage(org.eclipse.californium.scandium.dtls.AlertMessage) X509Certificate(java.security.cert.X509Certificate) X509Certificate(java.security.cert.X509Certificate) Certificate(java.security.cert.Certificate) CertificateVerificationResult(org.eclipse.californium.scandium.dtls.CertificateVerificationResult)

Example 2 with CertificateVerificationResult

use of org.eclipse.californium.scandium.dtls.CertificateVerificationResult in project thingsboard by thingsboard.

the class TbLwM2MDtlsBootstrapCertificateVerifier method verifyCertificate.

@Override
public CertificateVerificationResult verifyCertificate(ConnectionId cid, ServerNames serverName, InetSocketAddress remotePeer, boolean clientUsage, boolean verifySubject, boolean truncateCertificatePath, CertificateMessage message) {
    CertPath certChain = message.getCertificateChain();
    if (certChain == null) {
        // We trust all RPK on this layer, and use TbLwM2MAuthorizer
        PublicKey publicKey = message.getPublicKey();
        return new CertificateVerificationResult(cid, publicKey, null);
    } else {
        try {
            boolean x509CredentialsFound = false;
            X509Certificate[] chain = certChain.getCertificates().toArray(new X509Certificate[0]);
            for (X509Certificate cert : chain) {
                try {
                    if (!skipValidityCheckForClientCert) {
                        cert.checkValidity();
                    }
                    TbLwM2MSecurityInfo securityInfo = null;
                    // verify if trust
                    if (staticCertificateVerifier != null) {
                        HandshakeException exception = staticCertificateVerifier.verifyCertificate(cid, serverName, remotePeer, clientUsage, verifySubject, truncateCertificatePath, message).getException();
                        if (exception == null) {
                            String endpoint = config.getTrustSslCredentials().getValueFromSubjectNameByKey(cert.getSubjectX500Principal().getName(), "CN");
                            if (StringUtils.isNotEmpty(endpoint)) {
                                securityInfo = bsSecurityStore.getX509ByEndpoint(endpoint);
                            }
                        } else {
                            log.trace("Certificate validation failed.", exception);
                        }
                    }
                    // if not trust or cert trust securityInfo == null
                    if (securityInfo == null || securityInfo.getMsg() == null) {
                        String strCert = SslUtil.getCertificateString(cert);
                        String sha3Hash = EncryptionUtil.getSha3Hash(strCert);
                        try {
                            securityInfo = bsSecurityStore.getX509ByEndpoint(sha3Hash);
                        } catch (LwM2MAuthException e) {
                            log.trace("Failed to find security info: [{}]", sha3Hash, e);
                        }
                    }
                    ValidateDeviceCredentialsResponse msg = securityInfo != null ? securityInfo.getMsg() : null;
                    if (msg != null && StringUtils.isNotEmpty(msg.getCredentials())) {
                        x509CredentialsFound = true;
                        break;
                    }
                } catch (CertificateEncodingException | CertificateExpiredException | CertificateNotYetValidException e) {
                    log.trace("Failed to find security info: [{}]", cert.getSubjectX500Principal().getName(), e);
                }
            }
            if (!x509CredentialsFound) {
                AlertMessage alert = new AlertMessage(AlertMessage.AlertLevel.FATAL, AlertMessage.AlertDescription.INTERNAL_ERROR);
                throw new HandshakeException("x509 verification not enabled!", alert);
            }
            return new CertificateVerificationResult(cid, certChain, null);
        } catch (HandshakeException e) {
            log.trace("Certificate validation failed!", e);
            return new CertificateVerificationResult(cid, e, null);
        }
    }
}
Also used : CertificateNotYetValidException(java.security.cert.CertificateNotYetValidException) CertificateExpiredException(java.security.cert.CertificateExpiredException) PublicKey(java.security.PublicKey) LwM2MAuthException(org.thingsboard.server.transport.lwm2m.server.client.LwM2MAuthException) CertificateEncodingException(java.security.cert.CertificateEncodingException) X509Certificate(java.security.cert.X509Certificate) CertificateVerificationResult(org.eclipse.californium.scandium.dtls.CertificateVerificationResult) TbLwM2MSecurityInfo(org.thingsboard.server.transport.lwm2m.secure.TbLwM2MSecurityInfo) CertPath(java.security.cert.CertPath) HandshakeException(org.eclipse.californium.scandium.dtls.HandshakeException) ValidateDeviceCredentialsResponse(org.thingsboard.server.common.transport.auth.ValidateDeviceCredentialsResponse) AlertMessage(org.eclipse.californium.scandium.dtls.AlertMessage)

Example 3 with CertificateVerificationResult

use of org.eclipse.californium.scandium.dtls.CertificateVerificationResult in project thingsboard by thingsboard.

the class TbLwM2MDtlsCertificateVerifier method verifyCertificate.

@Override
public CertificateVerificationResult verifyCertificate(ConnectionId cid, ServerNames serverName, InetSocketAddress remotePeer, boolean clientUsage, boolean verifySubject, boolean truncateCertificatePath, CertificateMessage message) {
    CertPath certChain = message.getCertificateChain();
    if (certChain == null) {
        // We trust all RPK on this layer, and use TbLwM2MAuthorizer
        PublicKey publicKey = message.getPublicKey();
        return new CertificateVerificationResult(cid, publicKey, null);
    } else {
        try {
            boolean x509CredentialsFound = false;
            X509Certificate[] chain = certChain.getCertificates().toArray(new X509Certificate[0]);
            for (X509Certificate cert : chain) {
                try {
                    if (!skipValidityCheckForClientCert) {
                        cert.checkValidity();
                    }
                    TbLwM2MSecurityInfo securityInfo = null;
                    if (staticCertificateVerifier != null) {
                        HandshakeException exception = staticCertificateVerifier.verifyCertificate(cid, serverName, remotePeer, clientUsage, verifySubject, truncateCertificatePath, message).getException();
                        if (exception == null) {
                            try {
                                String endpoint = config.getTrustSslCredentials().getValueFromSubjectNameByKey(cert.getSubjectX500Principal().getName(), "CN");
                                if (StringUtils.isNotEmpty(endpoint)) {
                                    securityInfo = securityInfoValidator.getEndpointSecurityInfoByCredentialsId(endpoint, CLIENT);
                                }
                            } catch (LwM2MAuthException e) {
                                log.trace("Certificate trust validation failed.", e);
                            }
                        } else {
                            log.trace("Certificate trust validation failed.", exception);
                        }
                    }
                    // if not trust or cert trust securityInfo == null
                    String strCert = SslUtil.getCertificateString(cert);
                    String sha3Hash = EncryptionUtil.getSha3Hash(strCert);
                    if (securityInfo == null || securityInfo.getMsg() == null) {
                        try {
                            securityInfo = securityInfoValidator.getEndpointSecurityInfoByCredentialsId(sha3Hash, CLIENT);
                        } catch (LwM2MAuthException e) {
                            log.trace("Failed find security info: {}", sha3Hash, e);
                        }
                    }
                    ValidateDeviceCredentialsResponse msg = securityInfo != null ? securityInfo.getMsg() : null;
                    if (msg != null && StringUtils.isNotEmpty(msg.getCredentials())) {
                        LwM2MClientCredentials credentials = JacksonUtil.fromString(msg.getCredentials(), LwM2MClientCredentials.class);
                        if (!credentials.getClient().getSecurityConfigClientMode().equals(LwM2MSecurityMode.X509)) {
                            continue;
                        }
                        X509ClientCredential config = (X509ClientCredential) credentials.getClient();
                        String certBody = config.getCert();
                        String endpoint = config.getEndpoint();
                        if (StringUtils.isBlank(certBody) || strCert.equals(certBody)) {
                            x509CredentialsFound = true;
                            DeviceProfile deviceProfile = msg.getDeviceProfile();
                            if (msg.hasDeviceInfo() && deviceProfile != null) {
                                sessionStorage.put(endpoint, new TbX509DtlsSessionInfo(cert.getSubjectX500Principal().getName(), msg));
                                try {
                                    securityStore.putX509(securityInfo);
                                } catch (NonUniqueSecurityInfoException e) {
                                    log.trace("Failed to add security info: {}", securityInfo, e);
                                }
                                break;
                            }
                        } else {
                            log.trace("[{}][{}] Certificate mismatch. Expected: {}, Actual: {}", endpoint, sha3Hash, strCert, certBody);
                        }
                    }
                } catch (CertificateEncodingException | CertificateExpiredException | CertificateNotYetValidException e) {
                    log.error(e.getMessage(), e);
                }
            }
            if (!x509CredentialsFound) {
                AlertMessage alert = new AlertMessage(AlertMessage.AlertLevel.FATAL, AlertMessage.AlertDescription.INTERNAL_ERROR);
                throw new HandshakeException("x509 verification not enabled!", alert);
            }
            return new CertificateVerificationResult(cid, certChain, null);
        } catch (HandshakeException e) {
            log.trace("Certificate validation failed!", e);
            return new CertificateVerificationResult(cid, e, null);
        }
    }
}
Also used : CertificateNotYetValidException(java.security.cert.CertificateNotYetValidException) CertificateExpiredException(java.security.cert.CertificateExpiredException) PublicKey(java.security.PublicKey) LwM2MAuthException(org.thingsboard.server.transport.lwm2m.server.client.LwM2MAuthException) CertificateEncodingException(java.security.cert.CertificateEncodingException) X509Certificate(java.security.cert.X509Certificate) CertificateVerificationResult(org.eclipse.californium.scandium.dtls.CertificateVerificationResult) X509ClientCredential(org.thingsboard.server.common.data.device.credentials.lwm2m.X509ClientCredential) DeviceProfile(org.thingsboard.server.common.data.DeviceProfile) NonUniqueSecurityInfoException(org.eclipse.leshan.server.security.NonUniqueSecurityInfoException) LwM2MClientCredentials(org.thingsboard.server.transport.lwm2m.secure.credentials.LwM2MClientCredentials) CertPath(java.security.cert.CertPath) HandshakeException(org.eclipse.californium.scandium.dtls.HandshakeException) ValidateDeviceCredentialsResponse(org.thingsboard.server.common.transport.auth.ValidateDeviceCredentialsResponse) AlertMessage(org.eclipse.californium.scandium.dtls.AlertMessage)

Example 4 with CertificateVerificationResult

use of org.eclipse.californium.scandium.dtls.CertificateVerificationResult in project hono by eclipse.

the class DeviceRegistryBasedCertificateVerifier method validateCertificateAndLoadDevice.

/**
 * Validates a device's client certificate and completes the DTLS handshake result handler.
 *
 * @param cid the connection id to report the result.
 * @param certPath certificate path.
 * @param session session.
 * @see #setResultHandler(HandshakeResultHandler)
 */
private void validateCertificateAndLoadDevice(final ConnectionId cid, final CertPath certPath, final DTLSSession session) {
    LOG.debug("validating client's X.509 certificate");
    final Span span = tracer.buildSpan("validate client certificate").withTag(Tags.SPAN_KIND.getKey(), Tags.SPAN_KIND_CLIENT).withTag(Tags.COMPONENT.getKey(), adapter.getTypeName()).start();
    validateCertificateAndLoadDevice(session, certPath, span).map(info -> {
        // set AdditionalInfo as customArgument here
        return new CertificateVerificationResult(cid, certPath, info);
    }).otherwise(t -> {
        TracingHelper.logError(span, "could not validate X509 for device", t);
        LOG.debug("error validating X509", t);
        final AlertMessage alert = new AlertMessage(AlertLevel.FATAL, AlertDescription.BAD_CERTIFICATE, session.getPeer());
        return new CertificateVerificationResult(cid, new HandshakeException("error validating X509", alert), null);
    }).onSuccess(result -> {
        span.finish();
        californiumResultHandler.apply(result);
    });
}
Also used : HttpURLConnection(java.net.HttpURLConnection) X509Certificate(java.security.cert.X509Certificate) X500Principal(javax.security.auth.x500.X500Principal) LoggerFactory(org.slf4j.LoggerFactory) CertificateType(org.eclipse.californium.scandium.dtls.CertificateType) ClientErrorException(org.eclipse.hono.client.ClientErrorException) AlertDescription(org.eclipse.californium.scandium.dtls.AlertMessage.AlertDescription) Tags(io.opentracing.tag.Tags) CertificateMessage(org.eclipse.californium.scandium.dtls.CertificateMessage) ServerName(org.eclipse.californium.scandium.util.ServerName) DeviceCredentials(org.eclipse.hono.adapter.auth.device.DeviceCredentials) HandshakeException(org.eclipse.californium.scandium.dtls.HandshakeException) CertPathUtil(org.eclipse.californium.elements.util.CertPathUtil) ServerNames(org.eclipse.californium.scandium.util.ServerNames) StreamSupport(java.util.stream.StreamSupport) NewAdvancedCertificateVerifier(org.eclipse.californium.scandium.dtls.x509.NewAdvancedCertificateVerifier) TracingHelper(org.eclipse.hono.tracing.TracingHelper) X509Authentication(org.eclipse.hono.adapter.auth.device.X509Authentication) Logger(org.slf4j.Logger) NameType(org.eclipse.californium.scandium.util.ServerName.NameType) Tracer(io.opentracing.Tracer) TenantServiceBasedX509Authentication(org.eclipse.hono.adapter.auth.device.TenantServiceBasedX509Authentication) AlertLevel(org.eclipse.californium.scandium.dtls.AlertMessage.AlertLevel) AdditionalInfo(org.eclipse.californium.elements.auth.AdditionalInfo) Promise(io.vertx.core.Promise) HandshakeResultHandler(org.eclipse.californium.scandium.dtls.HandshakeResultHandler) CertPath(java.security.cert.CertPath) Collectors(java.util.stream.Collectors) Future(io.vertx.core.Future) Device(org.eclipse.hono.auth.Device) Objects(java.util.Objects) DTLSSession(org.eclipse.californium.scandium.dtls.DTLSSession) List(java.util.List) Certificate(java.security.cert.Certificate) TenantTraceSamplingHelper(org.eclipse.hono.tracing.TenantTraceSamplingHelper) DeviceCredentialsAuthProvider(org.eclipse.hono.adapter.auth.device.DeviceCredentialsAuthProvider) X509AuthProvider(org.eclipse.hono.adapter.auth.device.X509AuthProvider) ConnectionId(org.eclipse.californium.scandium.dtls.ConnectionId) CertificateVerificationResult(org.eclipse.californium.scandium.dtls.CertificateVerificationResult) Optional(java.util.Optional) AlertMessage(org.eclipse.californium.scandium.dtls.AlertMessage) Span(io.opentracing.Span) SubjectDnCredentials(org.eclipse.hono.adapter.auth.device.SubjectDnCredentials) Span(io.opentracing.Span) HandshakeException(org.eclipse.californium.scandium.dtls.HandshakeException) AlertMessage(org.eclipse.californium.scandium.dtls.AlertMessage) CertificateVerificationResult(org.eclipse.californium.scandium.dtls.CertificateVerificationResult)

Example 5 with CertificateVerificationResult

use of org.eclipse.californium.scandium.dtls.CertificateVerificationResult in project thingsboard by thingsboard.

the class TbCoapDtlsCertificateVerifier method verifyCertificate.

@Override
public CertificateVerificationResult verifyCertificate(ConnectionId cid, ServerNames serverName, InetSocketAddress remotePeer, boolean clientUsage, boolean verifySubject, boolean truncateCertificatePath, CertificateMessage message) {
    try {
        CertPath certpath = message.getCertificateChain();
        X509Certificate[] chain = certpath.getCertificates().toArray(new X509Certificate[0]);
        for (X509Certificate cert : chain) {
            try {
                if (!skipValidityCheckForClientCert) {
                    cert.checkValidity();
                }
                String strCert = SslUtil.getCertificateString(cert);
                String sha3Hash = EncryptionUtil.getSha3Hash(strCert);
                final ValidateDeviceCredentialsResponse[] deviceCredentialsResponse = new ValidateDeviceCredentialsResponse[1];
                CountDownLatch latch = new CountDownLatch(1);
                transportService.process(DeviceTransportType.COAP, TransportProtos.ValidateDeviceX509CertRequestMsg.newBuilder().setHash(sha3Hash).build(), new TransportServiceCallback<>() {

                    @Override
                    public void onSuccess(ValidateDeviceCredentialsResponse msg) {
                        if (!StringUtils.isEmpty(msg.getCredentials())) {
                            deviceCredentialsResponse[0] = msg;
                        }
                        latch.countDown();
                    }

                    @Override
                    public void onError(Throwable e) {
                        log.error(e.getMessage(), e);
                        latch.countDown();
                    }
                });
                latch.await(10, TimeUnit.SECONDS);
                ValidateDeviceCredentialsResponse msg = deviceCredentialsResponse[0];
                if (msg != null && strCert.equals(msg.getCredentials())) {
                    DeviceProfile deviceProfile = msg.getDeviceProfile();
                    if (msg.hasDeviceInfo() && deviceProfile != null) {
                        tbCoapDtlsSessionInMemoryStorage.put(remotePeer, new TbCoapDtlsSessionInfo(msg, deviceProfile));
                    }
                    break;
                }
            } catch (InterruptedException | CertificateEncodingException | CertificateExpiredException | CertificateNotYetValidException e) {
                log.error(e.getMessage(), e);
                AlertMessage alert = new AlertMessage(AlertMessage.AlertLevel.FATAL, AlertMessage.AlertDescription.BAD_CERTIFICATE);
                throw new HandshakeException("Certificate chain could not be validated", alert);
            }
        }
        return new CertificateVerificationResult(cid, certpath, null);
    } catch (HandshakeException e) {
        log.trace("Certificate validation failed!", e);
        return new CertificateVerificationResult(cid, e, null);
    }
}
Also used : CertificateNotYetValidException(java.security.cert.CertificateNotYetValidException) CertificateExpiredException(java.security.cert.CertificateExpiredException) CertificateEncodingException(java.security.cert.CertificateEncodingException) CountDownLatch(java.util.concurrent.CountDownLatch) X509Certificate(java.security.cert.X509Certificate) CertificateVerificationResult(org.eclipse.californium.scandium.dtls.CertificateVerificationResult) DeviceProfile(org.thingsboard.server.common.data.DeviceProfile) CertPath(java.security.cert.CertPath) ValidateDeviceCredentialsResponse(org.thingsboard.server.common.transport.auth.ValidateDeviceCredentialsResponse) HandshakeException(org.eclipse.californium.scandium.dtls.HandshakeException) AlertMessage(org.eclipse.californium.scandium.dtls.AlertMessage)

Aggregations

CertPath (java.security.cert.CertPath)5 X509Certificate (java.security.cert.X509Certificate)5 AlertMessage (org.eclipse.californium.scandium.dtls.AlertMessage)5 CertificateVerificationResult (org.eclipse.californium.scandium.dtls.CertificateVerificationResult)5 HandshakeException (org.eclipse.californium.scandium.dtls.HandshakeException)5 CertificateEncodingException (java.security.cert.CertificateEncodingException)3 CertificateExpiredException (java.security.cert.CertificateExpiredException)3 CertificateNotYetValidException (java.security.cert.CertificateNotYetValidException)3 PublicKey (java.security.PublicKey)2 Certificate (java.security.cert.Certificate)2 ValidateDeviceCredentialsResponse (org.thingsboard.server.common.transport.auth.ValidateDeviceCredentialsResponse)2 LwM2MAuthException (org.thingsboard.server.transport.lwm2m.server.client.LwM2MAuthException)2 Span (io.opentracing.Span)1 Tracer (io.opentracing.Tracer)1 Tags (io.opentracing.tag.Tags)1 Future (io.vertx.core.Future)1 Promise (io.vertx.core.Promise)1 HttpURLConnection (java.net.HttpURLConnection)1 List (java.util.List)1 Objects (java.util.Objects)1