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);
}
}
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);
}
}
}
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);
}
}
}
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);
});
}
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);
}
}
Aggregations