diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/device/credentials/lwm2m/AbstractLwM2MClientCredentialsWithKey.java b/common/data/src/main/java/org/thingsboard/server/common/data/device/credentials/lwm2m/AbstractLwM2MClientCredentialsWithKey.java deleted file mode 100644 index 26cc55faa6..0000000000 --- a/common/data/src/main/java/org/thingsboard/server/common/data/device/credentials/lwm2m/AbstractLwM2MClientCredentialsWithKey.java +++ /dev/null @@ -1,45 +0,0 @@ -/** - * Copyright © 2016-2021 The Thingsboard Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.thingsboard.server.common.data.device.credentials.lwm2m; - -import com.fasterxml.jackson.annotation.JsonIgnore; -import lombok.Getter; -import lombok.Setter; -import lombok.SneakyThrows; -import org.apache.commons.codec.binary.Base64; -import org.apache.commons.codec.binary.Hex; - -public abstract class AbstractLwM2MClientCredentialsWithKey extends AbstractLwM2MClientCredentials { - @Getter - @Setter - private String key; - - private byte[] keyInBytes; - - @SneakyThrows - @JsonIgnore - public byte[] getDecodedKey() throws IllegalArgumentException { - if (keyInBytes == null) { - if (this.getSecurityConfigClientMode() == LwM2MSecurityMode.PSK) { - keyInBytes = Hex.decodeHex(key.toLowerCase().toCharArray()); - } - else { - keyInBytes = Base64.decodeBase64(key.getBytes()); - } - } - return keyInBytes; - } -} diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/device/credentials/lwm2m/AbstractLwM2MClientSecurityCredentials.java b/common/data/src/main/java/org/thingsboard/server/common/data/device/credentials/lwm2m/AbstractLwM2MClientSecurityCredentials.java new file mode 100644 index 0000000000..e5e3271c7a --- /dev/null +++ b/common/data/src/main/java/org/thingsboard/server/common/data/device/credentials/lwm2m/AbstractLwM2MClientSecurityCredentials.java @@ -0,0 +1,30 @@ +/** + * Copyright © 2016-2021 The Thingsboard Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.thingsboard.server.common.data.device.credentials.lwm2m; + +import lombok.Getter; +import lombok.Setter; +import org.apache.commons.codec.DecoderException; + +public abstract class AbstractLwM2MClientSecurityCredentials extends AbstractLwM2MClientCredentials { + @Getter + @Setter + protected String key; + + protected byte[] securityInBytes; + + public abstract byte[] getDecoded() throws IllegalArgumentException, DecoderException; +} diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/device/credentials/lwm2m/PSKClientCredentials.java b/common/data/src/main/java/org/thingsboard/server/common/data/device/credentials/lwm2m/PSKClientCredentials.java index f90e85ff4a..03d2ab328c 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/device/credentials/lwm2m/PSKClientCredentials.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/device/credentials/lwm2m/PSKClientCredentials.java @@ -17,14 +17,24 @@ package org.thingsboard.server.common.data.device.credentials.lwm2m; import lombok.Getter; import lombok.Setter; +import org.apache.commons.codec.DecoderException; +import org.apache.commons.codec.binary.Hex; @Getter @Setter -public class PSKClientCredentials extends AbstractLwM2MClientCredentialsWithKey { +public class PSKClientCredentials extends AbstractLwM2MClientSecurityCredentials { private String identity; @Override public LwM2MSecurityMode getSecurityConfigClientMode() { return LwM2MSecurityMode.PSK; } -} + + @Override + public byte[] getDecoded() throws IllegalArgumentException, DecoderException { + if (securityInBytes == null) { + securityInBytes = Hex.decodeHex(key.toLowerCase().toCharArray()); + } + return securityInBytes; + } +} \ No newline at end of file diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/device/credentials/lwm2m/RPKClientCredentials.java b/common/data/src/main/java/org/thingsboard/server/common/data/device/credentials/lwm2m/RPKClientCredentials.java index 4ebe2de71a..a05bb438c6 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/device/credentials/lwm2m/RPKClientCredentials.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/device/credentials/lwm2m/RPKClientCredentials.java @@ -15,10 +15,21 @@ */ package org.thingsboard.server.common.data.device.credentials.lwm2m; -public class RPKClientCredentials extends AbstractLwM2MClientCredentialsWithKey { +import org.apache.commons.codec.DecoderException; +import org.apache.commons.codec.binary.Base64; + +public class RPKClientCredentials extends AbstractLwM2MClientSecurityCredentials { @Override public LwM2MSecurityMode getSecurityConfigClientMode() { return LwM2MSecurityMode.RPK; } + + @Override + public byte[] getDecoded() throws IllegalArgumentException, DecoderException { + if (securityInBytes == null) { + securityInBytes = Base64.decodeBase64(key.getBytes()); + } + return securityInBytes; + } } diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/device/credentials/lwm2m/X509ClientCredentials.java b/common/data/src/main/java/org/thingsboard/server/common/data/device/credentials/lwm2m/X509ClientCredentials.java index d91fbf62ea..dfef57e18e 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/device/credentials/lwm2m/X509ClientCredentials.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/device/credentials/lwm2m/X509ClientCredentials.java @@ -15,30 +15,27 @@ */ package org.thingsboard.server.common.data.device.credentials.lwm2m; -import com.fasterxml.jackson.annotation.JsonIgnore; import lombok.Getter; import lombok.Setter; -import lombok.SneakyThrows; +import org.apache.commons.codec.DecoderException; import org.apache.commons.codec.binary.Base64; @Getter @Setter -public class X509ClientCredentials extends AbstractLwM2MClientCredentials { - private String cert; +public class X509ClientCredentials extends AbstractLwM2MClientSecurityCredentials { - private byte[] certInBytes; + private String cert; @Override public LwM2MSecurityMode getSecurityConfigClientMode() { return LwM2MSecurityMode.X509; } - @SneakyThrows - @JsonIgnore - public byte[] getDecodedCert() throws IllegalArgumentException { - if (certInBytes == null) { - certInBytes = Base64.decodeBase64(cert.getBytes()); + @Override + public byte[] getDecoded() throws IllegalArgumentException, DecoderException { + if (securityInBytes == null && cert != null) { + securityInBytes = Base64.decodeBase64(cert.getBytes()); } - return certInBytes; + return securityInBytes; } } diff --git a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/secure/LwM2mCredentialsSecurityInfoValidator.java b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/secure/LwM2mCredentialsSecurityInfoValidator.java index bf30723ce0..6b7b3a9877 100644 --- a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/secure/LwM2mCredentialsSecurityInfoValidator.java +++ b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/secure/LwM2mCredentialsSecurityInfoValidator.java @@ -17,6 +17,7 @@ package org.thingsboard.server.transport.lwm2m.secure; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; +import org.apache.commons.codec.DecoderException; import org.eclipse.leshan.core.util.SecurityUtil; import org.eclipse.leshan.server.security.SecurityInfo; import org.springframework.stereotype.Component; @@ -146,14 +147,14 @@ public class LwM2mCredentialsSecurityInfoValidator { PSKClientCredentials pskConfig = (PSKClientCredentials) clientCredentialsConfig; if (StringUtils.isNotEmpty(pskConfig.getIdentity())) { try { - if (pskConfig.getDecodedKey() != null && pskConfig.getDecodedKey().length > 0) { + if (pskConfig.getDecoded() != null && pskConfig.getDecoded().length > 0) { endpoint = StringUtils.isNotEmpty(pskConfig.getEndpoint()) ? pskConfig.getEndpoint() : endpoint; if (endpoint != null && !endpoint.isEmpty()) { - result.setSecurityInfo(SecurityInfo.newPreSharedKeyInfo(endpoint, pskConfig.getIdentity(), pskConfig.getDecodedKey())); + result.setSecurityInfo(SecurityInfo.newPreSharedKeyInfo(endpoint, pskConfig.getIdentity(), pskConfig.getDecoded())); result.setSecurityMode(PSK); } } - } catch (IllegalArgumentException e) { + } catch (IllegalArgumentException | DecoderException e) { log.error("Missing PSK key: " + e.getMessage()); } } else { @@ -164,14 +165,14 @@ public class LwM2mCredentialsSecurityInfoValidator { private void createClientSecurityInfoRPK(TbLwM2MSecurityInfo result, String endpoint, LwM2MClientCredentials clientCredentialsConfig) { RPKClientCredentials rpkConfig = (RPKClientCredentials) clientCredentialsConfig; try { - if (rpkConfig.getDecodedKey() != null) { - PublicKey key = SecurityUtil.publicKey.decode(rpkConfig.getDecodedKey()); + if (rpkConfig.getDecoded() != null) { + PublicKey key = SecurityUtil.publicKey.decode(rpkConfig.getDecoded()); result.setSecurityInfo(SecurityInfo.newRawPublicKeyInfo(endpoint, key)); result.setSecurityMode(RPK); } else { log.error("Missing RPK key"); } - } catch (IllegalArgumentException | IOException | GeneralSecurityException e) { + } catch (IllegalArgumentException | IOException | GeneralSecurityException | DecoderException e) { log.error("RPK: Invalid security info content: " + e.getMessage()); } } diff --git a/dao/src/main/java/org/thingsboard/server/dao/device/DeviceCredentialsServiceImpl.java b/dao/src/main/java/org/thingsboard/server/dao/device/DeviceCredentialsServiceImpl.java index 4c6031d8bf..a5ed9e1e29 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/device/DeviceCredentialsServiceImpl.java +++ b/dao/src/main/java/org/thingsboard/server/dao/device/DeviceCredentialsServiceImpl.java @@ -117,7 +117,7 @@ public class DeviceCredentialsServiceImpl extends AbstractEntityService implemen formatSimpleMqttCredentials(deviceCredentials); break; case LWM2M_CREDENTIALS: - formatSimpleLwm2mCredentials(deviceCredentials); + formatAndValidateSimpleLwm2mCredentials(deviceCredentials); break; } } @@ -160,7 +160,7 @@ public class DeviceCredentialsServiceImpl extends AbstractEntityService implemen deviceCredentials.setCredentialsValue(cert); } - private void formatSimpleLwm2mCredentials(DeviceCredentials deviceCredentials) { + private void formatAndValidateSimpleLwm2mCredentials(DeviceCredentials deviceCredentials) { LwM2MDeviceCredentials lwM2MCredentials; try { lwM2MCredentials = JacksonUtil.fromString(deviceCredentials.getCredentialsValue(), LwM2MDeviceCredentials.class); @@ -171,8 +171,6 @@ public class DeviceCredentialsServiceImpl extends AbstractEntityService implemen String credentialsId = null; LwM2MClientCredentials clientCredentials = lwM2MCredentials.getClient(); - LwM2MServerCredentials bootstrapServer = lwM2MCredentials.getBootstrap().getBootstrapServer(); - LwM2MServerCredentials lwm2mServer = lwM2MCredentials.getBootstrap().getLwm2mServer(); switch (clientCredentials.getSecurityConfigClientMode()) { case NO_SEC: case RPK: @@ -264,7 +262,7 @@ public class DeviceCredentialsServiceImpl extends AbstractEntityService implemen try { String pubkClient = EncryptionUtil.pubkTrimNewLines(rpkCredentials.getKey()); rpkCredentials.setKey(pubkClient); - SecurityUtil.publicKey.decode(rpkCredentials.getDecodedKey()); + SecurityUtil.publicKey.decode(rpkCredentials.getDecoded()); } catch (Exception e) { throw new DeviceCredentialsValidationException("LwM2M client RPK key should be in RFC7250 standard and support only EC algorithm and encoded to Base64 format!"); } @@ -275,7 +273,7 @@ public class DeviceCredentialsServiceImpl extends AbstractEntityService implemen try { String certClient = EncryptionUtil.certTrimNewLines(x509CCredentials.getCert()); x509CCredentials.setCert(certClient); - SecurityUtil.certificate.decode(x509CCredentials.getDecodedCert()); + SecurityUtil.certificate.decode(x509CCredentials.getDecoded()); } catch (Exception e) { throw new DeviceCredentialsValidationException("LwM2M client X509 certificate should be in DER-encoded X509v3 format and support only EC algorithm and encoded to Base64 format!"); }