From ee55c0bf85a594161ce3aa7bfbd3d2adc8d06929 Mon Sep 17 00:00:00 2001 From: Andrii Shvaika Date: Thu, 1 Jul 2021 17:08:41 +0300 Subject: [PATCH] Improvements to key store read for lwm2m. --- .../LwM2MServerSecurityInfoRepository.java | 52 ++----- .../src/main/resources/thingsboard.yml | 14 +- .../resources/application-test.properties | 5 +- .../LwM2MTransportBootstrapService.java | 146 ++---------------- .../lwm2m/config/LwM2MSecureServerConfig.java | 8 +- .../config/LwM2MTransportBootstrapConfig.java | 16 +- .../config/LwM2MTransportServerConfig.java | 16 +- .../server/DefaultLwM2mTransportService.java | 117 +------------- .../src/main/resources/tb-lwm2m-transport.yml | 14 +- 9 files changed, 51 insertions(+), 337 deletions(-) diff --git a/application/src/main/java/org/thingsboard/server/service/lwm2m/LwM2MServerSecurityInfoRepository.java b/application/src/main/java/org/thingsboard/server/service/lwm2m/LwM2MServerSecurityInfoRepository.java index 78f849667f..b4ac3d30fd 100644 --- a/application/src/main/java/org/thingsboard/server/service/lwm2m/LwM2MServerSecurityInfoRepository.java +++ b/application/src/main/java/org/thingsboard/server/service/lwm2m/LwM2MServerSecurityInfoRepository.java @@ -30,8 +30,12 @@ import java.math.BigInteger; import java.security.AlgorithmParameters; import java.security.GeneralSecurityException; import java.security.KeyFactory; +import java.security.KeyStore; import java.security.KeyStoreException; +import java.security.NoSuchAlgorithmException; +import java.security.PrivateKey; import java.security.PublicKey; +import java.security.UnrecoverableKeyException; import java.security.cert.CertificateEncodingException; import java.security.cert.X509Certificate; import java.security.spec.ECGenParameterSpec; @@ -62,49 +66,23 @@ public class LwM2MServerSecurityInfoRepository { bsServ.setPort(serverConfig.getPort()); bsServ.setSecurityHost(serverConfig.getSecureHost()); bsServ.setSecurityPort(serverConfig.getSecurePort()); - bsServ.setServerPublicKey(getPublicKey(serverConfig.getCertificateAlias(), this.serverConfig.getPublicX(), this.serverConfig.getPublicY())); + bsServ.setServerPublicKey(getPublicKey(serverConfig)); return bsServ; } - private String getPublicKey(String alias, String publicServerX, String publicServerY) { - String publicKey = getServerPublicKeyX509(alias); - return publicKey != null ? publicKey : getRPKPublicKey(publicServerX, publicServerY); - } - - private String getServerPublicKeyX509(String alias) { + private String getPublicKey(LwM2MSecureServerConfig config) { try { - X509Certificate serverCertificate = (X509Certificate) serverConfig.getKeyStoreValue().getCertificate(alias); - return Hex.encodeHexString(serverCertificate.getEncoded()); - } catch (CertificateEncodingException | KeyStoreException e) { - e.printStackTrace(); - } - return null; - } - - private String getRPKPublicKey(String publicServerX, String publicServerY) { - try { - /** Get Elliptic Curve Parameter spec for secp256r1 */ - AlgorithmParameters algoParameters = AlgorithmParameters.getInstance("EC"); - algoParameters.init(new ECGenParameterSpec("secp256r1")); - ECParameterSpec parameterSpec = algoParameters.getParameterSpec(ECParameterSpec.class); - if (publicServerX != null && !publicServerX.isEmpty() && publicServerY != null && !publicServerY.isEmpty()) { - /** Get point values */ - byte[] publicX = Hex.decodeHex(publicServerX.toCharArray()); - byte[] publicY = Hex.decodeHex(publicServerY.toCharArray()); - /** Create key specs */ - KeySpec publicKeySpec = new ECPublicKeySpec(new ECPoint(new BigInteger(publicX), new BigInteger(publicY)), - parameterSpec); - /** Get keys */ - PublicKey publicKey = KeyFactory.getInstance("EC").generatePublic(publicKeySpec); - if (publicKey != null && publicKey.getEncoded().length > 0) { - return Hex.encodeHexString(publicKey.getEncoded()); - } + KeyStore keyStore = serverConfig.getKeyStoreValue(); + if (keyStore != null) { + X509Certificate serverCertificate = (X509Certificate) serverConfig.getKeyStoreValue().getCertificate(config.getCertificateAlias()); + return Hex.encodeHexString(serverCertificate.getPublicKey().getEncoded()); } - } catch (GeneralSecurityException | IllegalArgumentException e) { - log.error("[{}] Failed generate Server RPK for profile", e.getMessage()); - throw new RuntimeException(e); + } catch (Exception e) { + log.trace("Failed to fetch public key from key store!", e); + } - return null; + return ""; } + } diff --git a/application/src/main/resources/thingsboard.yml b/application/src/main/resources/thingsboard.yml index 30f7756aca..3b83c3d3b6 100644 --- a/application/src/main/resources/thingsboard.yml +++ b/application/src/main/resources/thingsboard.yml @@ -649,12 +649,9 @@ transport: security: bind_address: "${LWM2M_BIND_ADDRESS_SECURITY:0.0.0.0}" bind_port: "${LWM2M_BIND_PORT_SECURITY:5686}" - # Only for RPK: Public & Private Key. If the keystore file is missing or not working - public_x: "${LWM2M_SERVER_PUBLIC_X:05064b9e6762dd8d8b8a52355d7b4d8b9a3d64e6d2ee277d76c248861353f358}" - public_y: "${LWM2M_SERVER_PUBLIC_Y:5eeb1838e4f9e37b31fa347aef5ce3431eb54e0a2506910c5e0298817445721b}" - private_encoded: "${LWM2M_SERVER_PRIVATE_ENCODED:308193020100301306072a8648ce3d020106082a8648ce3d030107047930770201010420dc774b309e547ceb48fee547e104ce201a9c48c449dc5414cd04e7f5cf05f67ba00a06082a8648ce3d030107a1440342000405064b9e6762dd8d8b8a52355d7b4d8b9a3d64e6d2ee277d76c248861353f3585eeb1838e4f9e37b31fa347aef5ce3431eb54e0a2506910c5e0298817445721b}" # Only Certificate_x509: - alias: "${LWM2M_KEYSTORE_ALIAS_SERVER:server}" + alias: "${LWM2M_KEYSTORE_SERVER_ALIAS:server}" + password: "${LWM2M_KEYSTORE_SERVER_PASSWORD:server_ks_password}" skip_validity_check_for_client_cert: "${TB_LWM2M_SERVER_SECURITY_SKIP_VALIDITY_CHECK_FOR_CLIENT_CERT:false}" bootstrap: enable: "${LWM2M_ENABLED_BS:true}" @@ -664,12 +661,9 @@ transport: security: bind_address: "${LWM2M_BIND_ADDRESS_SECURITY_BS:0.0.0.0}" bind_port: "${LWM2M_BIND_PORT_SECURITY_BS:5688}" - # Only for RPK: Public & Private Key. If the keystore file is missing or not working - public_x: "${LWM2M_SERVER_PUBLIC_X_BS:5017c87a1c1768264656b3b355434b0def6edb8b9bf166a4762d9930cd730f91}" - public_y: "${LWM2M_SERVER_PUBLIC_Y_BS:3fc4e61bcd8901ec27c424114c3e887ed372497f0c2cf85839b8443e76988b34}" - private_encoded: "${LWM2M_SERVER_PRIVATE_ENCODED_BS:308193020100301306072a8648ce3d020106082a8648ce3d0301070479307702010104205ecafd90caa7be45c42e1f3f32571632b8409e6e6249d7124f4ba56fab3c8083a00a06082a8648ce3d030107a144034200045017c87a1c1768264656b3b355434b0def6edb8b9bf166a4762d9930cd730f913fc4e61bcd8901ec27c424114c3e887ed372497f0c2cf85839b8443e76988b34}" # Only Certificate_x509: - alias: "${LWM2M_KEYSTORE_ALIAS_BS:bootstrap}" + alias: "${LWM2M_KEYSTORE_BS_ALIAS:bootstrap}" + password: "${LWM2M_KEYSTORE_BS_PASSWORD:server_ks_password}" security: # Certificate_x509: # To get helps about files format and how to generate it, see: https://github.com/eclipse/leshan/wiki/Credential-files-format diff --git a/application/src/test/resources/application-test.properties b/application/src/test/resources/application-test.properties index 02d43723ed..d82de51785 100644 --- a/application/src/test/resources/application-test.properties +++ b/application/src/test/resources/application-test.properties @@ -1,4 +1,7 @@ transport.lwm2m.security.key_store=lwm2m/credentials/serverKeyStore.jks transport.lwm2m.security.key_store_password=server edges.enabled=true -transport.lwm2m.bootstrap.security.alias=server \ No newline at end of file +transport.lwm2m.server.security.alias=server +transport.lwm2m.server.security.password=server +transport.lwm2m.bootstrap.security.alias=server +transport.lwm2m.bootstrap.security.password=server \ No newline at end of file diff --git a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/bootstrap/LwM2MTransportBootstrapService.java b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/bootstrap/LwM2MTransportBootstrapService.java index 8823881ae7..015cf1cbcf 100644 --- a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/bootstrap/LwM2MTransportBootstrapService.java +++ b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/bootstrap/LwM2MTransportBootstrapService.java @@ -31,6 +31,7 @@ import org.thingsboard.server.transport.lwm2m.bootstrap.secure.LwM2mDefaultBoots import org.thingsboard.server.transport.lwm2m.config.LwM2MTransportBootstrapConfig; import org.thingsboard.server.transport.lwm2m.config.LwM2MTransportServerConfig; import org.thingsboard.server.transport.lwm2m.secure.LWM2MGenerationPSkRPkECC; +import org.thingsboard.server.transport.lwm2m.server.DefaultLwM2mTransportService; import javax.annotation.PostConstruct; import javax.annotation.PreDestroy; @@ -65,10 +66,7 @@ import static org.thingsboard.server.transport.lwm2m.server.LwM2mNetworkConfig.g @Component @ConditionalOnExpression("('${service.type:null}'=='tb-transport' && '${transport.lwm2m.enabled:false}'=='true' && '${transport.lwm2m.bootstrap.enable:false}'=='true') || ('${service.type:null}'=='monolith' && '${transport.lwm2m.enabled:false}'=='true'&& '${transport.lwm2m.bootstrap.enable:false}'=='true')") @RequiredArgsConstructor -//TODO: @ybondarenko please refactor this to be similar to DefaultLwM2mTransportService public class LwM2MTransportBootstrapService { - private PublicKey publicKey; - private PrivateKey privateKey; private boolean pskMode = false; private final LwM2MTransportServerConfig serverConfig; @@ -101,44 +99,34 @@ public class LwM2MTransportBootstrapService { builder.setLocalAddress(bootstrapConfig.getHost(), bootstrapConfig.getPort()); builder.setLocalSecureAddress(bootstrapConfig.getSecureHost(), bootstrapConfig.getSecurePort()); - /** Create CoAP Config */ + /* Create CoAP Config */ builder.setCoapConfig(getCoapConfig(bootstrapConfig.getPort(), bootstrapConfig.getSecurePort(), serverConfig)); - /** Define model provider (Create Models )*/ + /* Define model provider (Create Models )*/ - /** Create credentials */ + /* Create credentials */ this.setServerWithCredentials(builder); // /** Set securityStore with new ConfigStore */ // builder.setConfigStore(lwM2MInMemoryBootstrapConfigStore); - /** SecurityStore */ + /* SecurityStore */ builder.setSecurityStore(lwM2MBootstrapSecurityStore); - /** Create and Set DTLS Config */ + /* Create and Set DTLS Config */ DtlsConnectorConfig.Builder dtlsConfig = new DtlsConnectorConfig.Builder(); dtlsConfig.setRecommendedSupportedGroupsOnly(serverConfig.isRecommendedSupportedGroups()); dtlsConfig.setRecommendedCipherSuitesOnly(serverConfig.isRecommendedCiphers()); - if (this.pskMode) { - dtlsConfig.setSupportedCipherSuites( - TLS_PSK_WITH_AES_128_CCM_8, - TLS_PSK_WITH_AES_128_CBC_SHA256); - } else { - dtlsConfig.setSupportedCipherSuites( - TLS_PSK_WITH_AES_128_CCM_8, - TLS_PSK_WITH_AES_128_CBC_SHA256, - TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8, - TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256); - } + dtlsConfig.setSupportedCipherSuites(this.pskMode ? DefaultLwM2mTransportService.PSK_CIPHER_SUITES : DefaultLwM2mTransportService.RPK_OR_X509_CIPHER_SUITES); - /** Set DTLS Config */ + /* Set DTLS Config */ builder.setDtlsConfig(dtlsConfig); BootstrapSessionManager sessionManager = new LwM2mDefaultBootstrapSessionManager(lwM2MBootstrapSecurityStore); builder.setSessionManager(sessionManager); - /** Create BootstrapServer */ + /* Create BootstrapServer */ return builder.build(); } @@ -153,19 +141,15 @@ public class LwM2MTransportBootstrapService { trustedCertificates[0] = rootCAX509Cert; builder.setTrustedCertificates(trustedCertificates); } else { - /** by default trust all */ + /* by default trust all */ builder.setTrustedCertificates(new X509Certificate[0]); } } - } else if (this.setServerRPK(builder)) { - this.infoPramsUri("RPK"); - this.infoParamsBootstrapServerKey(this.publicKey, this.privateKey); } else { - /** by default trust all */ + /* by default trust all */ builder.setTrustedCertificates(new X509Certificate[0]); log.info("Unable to load X509 files for BootStrapServer"); this.pskMode = true; - this.infoPramsUri("PSK"); } } catch (KeyStoreException ex) { log.error("[{}] Unable to load X509 files server", ex.getMessage()); @@ -173,19 +157,14 @@ public class LwM2MTransportBootstrapService { } private boolean setBuilderX509(LeshanBootstrapServerBuilder builder) { - /** - * For deb => KeyStorePathFile == yml or commandline: KEY_STORE_PATH_FILE - * For idea => KeyStorePathResource == common/transport/lwm2m/src/main/resources/credentials: in LwM2MTransportContextServer: credentials/serverKeyStore.jks - */ try { X509Certificate serverCertificate = (X509Certificate) serverConfig.getKeyStoreValue().getCertificate(this.bootstrapConfig.getCertificateAlias()); - PrivateKey privateKey = (PrivateKey) serverConfig.getKeyStoreValue().getKey(this.bootstrapConfig.getCertificateAlias(), serverConfig.getKeyStorePassword() == null ? null : serverConfig.getKeyStorePassword().toCharArray()); + PrivateKey privateKey = (PrivateKey) serverConfig.getKeyStoreValue().getKey(this.bootstrapConfig.getCertificateAlias(), serverConfig.getCertificatePassword() == null ? null : serverConfig.getCertificatePassword().toCharArray()); PublicKey publicKey = serverCertificate.getPublicKey(); if (privateKey != null && privateKey.getEncoded().length > 0 && publicKey != null && publicKey.getEncoded().length > 0) { builder.setPublicKey(serverCertificate.getPublicKey()); builder.setPrivateKey(privateKey); builder.setCertificateChain(new X509Certificate[]{serverCertificate}); - this.infoParamsServerX509(serverCertificate, publicKey, privateKey); return true; } else { return false; @@ -196,105 +175,4 @@ public class LwM2MTransportBootstrapService { } } - private void infoParamsServerX509(X509Certificate certificate, PublicKey publicKey, PrivateKey privateKey) { - try { - this.infoPramsUri("X509"); - log.info("\n- X509 Certificate (Hex): [{}]", - Hex.encodeHexString(certificate.getEncoded())); - this.infoParamsBootstrapServerKey(publicKey, privateKey); - } catch (CertificateEncodingException e) { - log.error("", e); - } - } - - private void infoPramsUri(String mode) { - log.info("Bootstrap Server uses [{}]: serverNoSecureURI : [{}:{}], serverSecureURI : [{}:{}]", - mode, - this.bootstrapConfig.getHost(), - this.bootstrapConfig.getPort(), - this.bootstrapConfig.getSecureHost(), - this.bootstrapConfig.getSecurePort()); - } - - - private boolean setServerRPK(LeshanBootstrapServerBuilder builder) { - try { - this.generateKeyForBootstrapRPK(); - if (this.publicKey != null && this.publicKey.getEncoded().length > 0 && - this.privateKey != null && this.privateKey.getEncoded().length > 0) { - builder.setPublicKey(this.publicKey); -// builder.setCertificateChain(new X509Certificate[] { serverCertificate }); - /// Trust all certificates. - builder.setTrustedCertificates(new X509Certificate[0]); - builder.setPrivateKey(this.privateKey); - return true; - } - } catch (NoSuchAlgorithmException | InvalidParameterSpecException | InvalidKeySpecException e) { - log.error("Fail create Bootstrap Server with RPK", e); - } - return false; - } - - - /** - * From yml: bootstrap - * public_x: "${LWM2M_SERVER_PUBLIC_X_BS:993ef2b698c6a9c0c1d8be78b13a9383c0854c7c7c7a504d289b403794648183}" - * public_y: "${LWM2M_SERVER_PUBLIC_Y_BS:267412d5fc4e5ceb2257cb7fd7f76ebdac2fa9aa100afb162e990074cc0bfaa2}" - * private_encoded: "${LWM2M_SERVER_PRIVATE_ENCODED_BS:9dbdbb073fc63570693a9aaf1013414e261c571f27e27fc6a8c1c2ad9347875a}" - */ - private void generateKeyForBootstrapRPK() throws NoSuchAlgorithmException, InvalidParameterSpecException, InvalidKeySpecException { - /** Get Elliptic Curve Parameter spec for secp256r1 */ - AlgorithmParameters algoParameters = AlgorithmParameters.getInstance("EC"); - algoParameters.init(new ECGenParameterSpec("secp256r1")); - ECParameterSpec parameterSpec = algoParameters.getParameterSpec(ECParameterSpec.class); - LwM2MTransportBootstrapConfig serverConfig = this.bootstrapConfig; - if (StringUtils.isNotEmpty(serverConfig.getPublicX()) && StringUtils.isNotEmpty(serverConfig.getPublicY())) { - /** Get point values */ - byte[] publicX = Hex.decodeHex(serverConfig.getPublicX().toCharArray()); - byte[] publicY = Hex.decodeHex(serverConfig.getPublicY().toCharArray()); - /** Create key specs */ - KeySpec publicKeySpec = new ECPublicKeySpec(new ECPoint(new BigInteger(publicX), new BigInteger(publicY)), - parameterSpec); - /** Get public key */ - this.publicKey = KeyFactory.getInstance("EC").generatePublic(publicKeySpec); - } - String privateEncodedKey = serverConfig.getPrivateEncoded(); - if (StringUtils.isNotEmpty(privateEncodedKey)) { - /** Get private key */ - byte[] privateS = Hex.decodeHex(privateEncodedKey.toCharArray()); - try { - this.privateKey = KeyFactory.getInstance("EC").generatePrivate(new PKCS8EncodedKeySpec(privateS)); - } catch (InvalidKeySpecException ignore2) { - log.error("Invalid Bootstrap Server rpk.PrivateKey.getEncoded () [{}}]. PrivateKey has no EC algorithm", privateEncodedKey); - } - } - } - - private void infoParamsBootstrapServerKey(PublicKey publicKey, PrivateKey privateKey) { - /** Get x coordinate */ - byte[] x = ((ECPublicKey) publicKey).getW().getAffineX().toByteArray(); - if (x[0] == 0) - x = Arrays.copyOfRange(x, 1, x.length); - - /** Get Y coordinate */ - byte[] y = ((ECPublicKey) publicKey).getW().getAffineY().toByteArray(); - if (y[0] == 0) - y = Arrays.copyOfRange(y, 1, y.length); - - /** Get Curves params */ - String params = ((ECPublicKey) publicKey).getParams().toString(); - String privHex = Hex.encodeHexString(privateKey.getEncoded()); - log.info("\n- Public Key (Hex): [{}] \n" + - "- Private Key (Hex): [{}], \n" + - "public_x: \"${LWM2M_SERVER_PUBLIC_X_BS:{}}\" \n" + - "public_y: \"${LWM2M_SERVER_PUBLIC_Y_BS:{}}\" \n" + - "private_encoded: \"${LWM2M_SERVER_PRIVATE_ENCODED_BS:{}}\" \n" + - "- Elliptic Curve parameters : [{}]", - Hex.encodeHexString(publicKey.getEncoded()), - privHex, - Hex.encodeHexString(x), - Hex.encodeHexString(y), - privHex, - params); - } } diff --git a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/config/LwM2MSecureServerConfig.java b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/config/LwM2MSecureServerConfig.java index fcca9fb975..a525c5f157 100644 --- a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/config/LwM2MSecureServerConfig.java +++ b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/config/LwM2MSecureServerConfig.java @@ -27,12 +27,8 @@ public interface LwM2MSecureServerConfig { Integer getSecurePort(); - String getPublicX(); - - String getPublicY(); - - String getPrivateEncoded(); - String getCertificateAlias(); + String getCertificatePassword(); + } diff --git a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/config/LwM2MTransportBootstrapConfig.java b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/config/LwM2MTransportBootstrapConfig.java index c0379f9cee..6778056dd0 100644 --- a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/config/LwM2MTransportBootstrapConfig.java +++ b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/config/LwM2MTransportBootstrapConfig.java @@ -46,20 +46,12 @@ public class LwM2MTransportBootstrapConfig implements LwM2MSecureServerConfig { @Value("${transport.lwm2m.bootstrap.security.bind_port:}") private Integer securePort; - @Getter - @Value("${transport.lwm2m.bootstrap.security.public_x:}") - private String publicX; - - @Getter - @Value("${transport.lwm2m.bootstrap.security.public_y:}") - private String publicY; - - @Getter - @Value("${transport.lwm2m.bootstrap.security.private_encoded:}") - private String privateEncoded; - @Getter @Value("${transport.lwm2m.bootstrap.security.alias:}") private String certificateAlias; + @Getter + @Value("${transport.lwm2m.bootstrap.security.password:}") + private String certificatePassword; + } diff --git a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/config/LwM2MTransportServerConfig.java b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/config/LwM2MTransportServerConfig.java index 295b1eb9ba..4f9f0798c2 100644 --- a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/config/LwM2MTransportServerConfig.java +++ b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/config/LwM2MTransportServerConfig.java @@ -120,22 +120,14 @@ public class LwM2MTransportServerConfig implements LwM2MSecureServerConfig { @Value("${transport.lwm2m.server.security.bind_port:}") private Integer securePort; - @Getter - @Value("${transport.lwm2m.server.security.public_x:}") - private String publicX; - - @Getter - @Value("${transport.lwm2m.server.security.public_y:}") - private String publicY; - - @Getter - @Value("${transport.lwm2m.server.security.private_encoded:}") - private String privateEncoded; - @Getter @Value("${transport.lwm2m.server.security.alias:}") private String certificateAlias; + @Getter + @Value("${transport.lwm2m.server.security.password:}") + private String certificatePassword; + @Getter @Value("${transport.lwm2m.log_max_length:}") private int logMaxLength; diff --git a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/DefaultLwM2mTransportService.java b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/DefaultLwM2mTransportService.java index 8059d210dc..bf32b2f817 100644 --- a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/DefaultLwM2mTransportService.java +++ b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/DefaultLwM2mTransportService.java @@ -21,14 +21,12 @@ import org.eclipse.californium.scandium.config.DtlsConnectorConfig; import org.eclipse.californium.scandium.dtls.cipher.CipherSuite; import org.eclipse.leshan.core.node.codec.DefaultLwM2mNodeDecoder; import org.eclipse.leshan.core.node.codec.DefaultLwM2mNodeEncoder; -import org.eclipse.leshan.core.util.Hex; import org.eclipse.leshan.server.californium.LeshanServer; import org.eclipse.leshan.server.californium.LeshanServerBuilder; import org.eclipse.leshan.server.californium.registration.CaliforniumRegistrationStore; import org.eclipse.leshan.server.model.LwM2mModelProvider; import org.springframework.stereotype.Component; import org.thingsboard.server.cache.ota.OtaPackageDataCache; -import org.thingsboard.server.common.data.StringUtils; import org.thingsboard.server.queue.util.TbLwM2mTransportComponent; import org.thingsboard.server.transport.lwm2m.config.LwM2MTransportServerConfig; import org.thingsboard.server.transport.lwm2m.secure.LWM2MGenerationPSkRPkECC; @@ -41,24 +39,9 @@ import org.thingsboard.server.transport.lwm2m.utils.LwM2mValueConverterImpl; import javax.annotation.PostConstruct; import javax.annotation.PreDestroy; -import java.math.BigInteger; -import java.security.AlgorithmParameters; -import java.security.KeyFactory; -import java.security.NoSuchAlgorithmException; import java.security.PrivateKey; import java.security.PublicKey; -import java.security.cert.CertificateEncodingException; import java.security.cert.X509Certificate; -import java.security.interfaces.ECPublicKey; -import java.security.spec.ECGenParameterSpec; -import java.security.spec.ECParameterSpec; -import java.security.spec.ECPoint; -import java.security.spec.ECPublicKeySpec; -import java.security.spec.InvalidKeySpecException; -import java.security.spec.InvalidParameterSpecException; -import java.security.spec.KeySpec; -import java.security.spec.PKCS8EncodedKeySpec; -import java.util.Arrays; import static org.eclipse.californium.scandium.dtls.cipher.CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256; import static org.eclipse.californium.scandium.dtls.cipher.CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8; @@ -75,8 +58,6 @@ public class DefaultLwM2mTransportService implements LwM2MTransportService { public static final CipherSuite[] RPK_OR_X509_CIPHER_SUITES = {TLS_PSK_WITH_AES_128_CCM_8, TLS_PSK_WITH_AES_128_CBC_SHA256, TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8, TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256}; public static final CipherSuite[] PSK_CIPHER_SUITES = {TLS_PSK_WITH_AES_128_CCM_8, TLS_PSK_WITH_AES_128_CBC_SHA256}; - private PublicKey publicKey; - private PrivateKey privateKey; private final LwM2mTransportContext context; private final LwM2MTransportServerConfig config; @@ -97,14 +78,13 @@ public class DefaultLwM2mTransportService implements LwM2MTransportService { new LWM2MGenerationPSkRPkECC(); } this.server = getLhServer(); - /** + /* * Add a resource to the server. * CoapResource -> * path = FW_PACKAGE or SW_PACKAGE * nameFile = "BC68JAR01A09_TO_BC68JAR01A10.bin" * "coap://host:port/{path}/{token}/{nameFile}" */ - LwM2mTransportCoapResource otaCoapResource = new LwM2mTransportCoapResource(otaPackageDataCache, FIRMWARE_UPDATE_COAP_RESOURCE); this.server.coap().getServer().add(otaCoapResource); this.startLhServer(); @@ -170,29 +150,23 @@ public class DefaultLwM2mTransportService implements LwM2MTransportService { dtlsConfig.setAdvancedCertificateVerifier(certificateVerifier); builder.setAuthorizer(authorizer); dtlsConfig.setSupportedCipherSuites(RPK_OR_X509_CIPHER_SUITES); - } else if (this.setServerRPK(builder)) { - this.infoPramsUri("RPK"); - this.infoParamsServerKey(this.publicKey, this.privateKey); - dtlsConfig.setSupportedCipherSuites(RPK_OR_X509_CIPHER_SUITES); } else { /* by default trust all */ builder.setTrustedCertificates(new X509Certificate[0]); log.info("Unable to load X509 files for LWM2MServer"); dtlsConfig.setSupportedCipherSuites(PSK_CIPHER_SUITES); - this.infoPramsUri("PSK"); } } private boolean setBuilderX509(LeshanServerBuilder builder) { try { X509Certificate serverCertificate = (X509Certificate) config.getKeyStoreValue().getCertificate(config.getCertificateAlias()); - PrivateKey privateKey = (PrivateKey) config.getKeyStoreValue().getKey(config.getCertificateAlias(), config.getKeyStorePassword() == null ? null : config.getKeyStorePassword().toCharArray()); + PrivateKey privateKey = (PrivateKey) config.getKeyStoreValue().getKey(config.getCertificateAlias(), config.getCertificatePassword() == null ? null : config.getCertificatePassword().toCharArray()); PublicKey publicKey = serverCertificate.getPublicKey(); if (privateKey != null && privateKey.getEncoded().length > 0 && publicKey != null && publicKey.getEncoded().length > 0) { builder.setPublicKey(serverCertificate.getPublicKey()); builder.setPrivateKey(privateKey); builder.setCertificateChain(new X509Certificate[]{serverCertificate}); - this.infoParamsServerX509(serverCertificate, publicKey, privateKey); return true; } else { return false; @@ -203,93 +177,6 @@ public class DefaultLwM2mTransportService implements LwM2MTransportService { } } - private void infoParamsServerX509(X509Certificate certificate, PublicKey publicKey, PrivateKey privateKey) { - try { - infoPramsUri("X509"); - log.info("\n- X509 Certificate (Hex): [{}]", - Hex.encodeHexString(certificate.getEncoded())); - this.infoParamsServerKey(publicKey, privateKey); - } catch (CertificateEncodingException e) { - log.error("", e); - } - } - - private void infoPramsUri(String mode) { - LwM2MTransportServerConfig lwM2MTransportServerConfig = config; - log.info("Server uses [{}]: serverNoSecureURI : [{}:{}], serverSecureURI : [{}:{}]", mode, - lwM2MTransportServerConfig.getHost(), - lwM2MTransportServerConfig.getPort(), - lwM2MTransportServerConfig.getSecureHost(), - lwM2MTransportServerConfig.getSecurePort()); - } - - private boolean setServerRPK(LeshanServerBuilder builder) { - try { - this.loadOrGenerateRPKKeys(); - if (this.publicKey != null && this.publicKey.getEncoded().length > 0 && - this.privateKey != null && this.privateKey.getEncoded().length > 0) { - builder.setPublicKey(this.publicKey); - builder.setPrivateKey(this.privateKey); - return true; - } - } catch (NoSuchAlgorithmException | InvalidParameterSpecException | InvalidKeySpecException e) { - log.error("Fail create Server with RPK", e); - } - return false; - } - - private void loadOrGenerateRPKKeys() throws NoSuchAlgorithmException, InvalidParameterSpecException, InvalidKeySpecException { - /* Get Elliptic Curve Parameter spec for secp256r1 */ - AlgorithmParameters algoParameters = AlgorithmParameters.getInstance("EC"); - algoParameters.init(new ECGenParameterSpec("secp256r1")); - ECParameterSpec parameterSpec = algoParameters.getParameterSpec(ECParameterSpec.class); - LwM2MTransportServerConfig serverConfig = config; - if (StringUtils.isNotEmpty(serverConfig.getPublicX()) && StringUtils.isNotEmpty(serverConfig.getPublicY())) { - byte[] publicX = Hex.decodeHex(serverConfig.getPublicX().toCharArray()); - byte[] publicY = Hex.decodeHex(serverConfig.getPublicY().toCharArray()); - KeySpec publicKeySpec = new ECPublicKeySpec(new ECPoint(new BigInteger(publicX), new BigInteger(publicY)), - parameterSpec); - this.publicKey = KeyFactory.getInstance("EC").generatePublic(publicKeySpec); - } - String privateEncodedKey = serverConfig.getPrivateEncoded(); - if (StringUtils.isNotEmpty(privateEncodedKey)) { - byte[] privateS = Hex.decodeHex(privateEncodedKey.toCharArray()); - try { - this.privateKey = KeyFactory.getInstance("EC").generatePrivate(new PKCS8EncodedKeySpec(privateS)); - } catch (InvalidKeySpecException ignore2) { - log.error("Invalid Server rpk.PrivateKey.getEncoded () [{}}]. PrivateKey has no EC algorithm", privateEncodedKey); - } - } - } - - private void infoParamsServerKey(PublicKey publicKey, PrivateKey privateKey) { - /* Get x coordinate */ - byte[] x = ((ECPublicKey) publicKey).getW().getAffineX().toByteArray(); - if (x[0] == 0) - x = Arrays.copyOfRange(x, 1, x.length); - - /* Get Y coordinate */ - byte[] y = ((ECPublicKey) publicKey).getW().getAffineY().toByteArray(); - if (y[0] == 0) - y = Arrays.copyOfRange(y, 1, y.length); - - /* Get Curves params */ - String params = ((ECPublicKey) publicKey).getParams().toString(); - String privHex = Hex.encodeHexString(privateKey.getEncoded()); - log.info(" \n- Public Key (Hex): [{}] \n" + - "- Private Key (Hex): [{}], \n" + - "public_x: \"${LWM2M_SERVER_PUBLIC_X:{}}\" \n" + - "public_y: \"${LWM2M_SERVER_PUBLIC_Y:{}}\" \n" + - "private_encoded: \"${LWM2M_SERVER_PRIVATE_ENCODED:{}}\" \n" + - "- Elliptic Curve parameters : [{}]", - Hex.encodeHexString(publicKey.getEncoded()), - privHex, - Hex.encodeHexString(x), - Hex.encodeHexString(y), - privHex, - params); - } - @Override public String getName() { return "LWM2M"; diff --git a/transport/lwm2m/src/main/resources/tb-lwm2m-transport.yml b/transport/lwm2m/src/main/resources/tb-lwm2m-transport.yml index d7e97231e0..695053d417 100644 --- a/transport/lwm2m/src/main/resources/tb-lwm2m-transport.yml +++ b/transport/lwm2m/src/main/resources/tb-lwm2m-transport.yml @@ -108,12 +108,9 @@ transport: security: bind_address: "${LWM2M_BIND_ADDRESS_SECURITY:0.0.0.0}" bind_port: "${LWM2M_BIND_PORT_SECURITY:5686}" - # Only for RPK: Public & Private Key. If the keystore file is missing or not working - public_x: "${LWM2M_SERVER_PUBLIC_X:05064b9e6762dd8d8b8a52355d7b4d8b9a3d64e6d2ee277d76c248861353f358}" - public_y: "${LWM2M_SERVER_PUBLIC_Y:5eeb1838e4f9e37b31fa347aef5ce3431eb54e0a2506910c5e0298817445721b}" - private_encoded: "${LWM2M_SERVER_PRIVATE_ENCODED:308193020100301306072a8648ce3d020106082a8648ce3d030107047930770201010420dc774b309e547ceb48fee547e104ce201a9c48c449dc5414cd04e7f5cf05f67ba00a06082a8648ce3d030107a1440342000405064b9e6762dd8d8b8a52355d7b4d8b9a3d64e6d2ee277d76c248861353f3585eeb1838e4f9e37b31fa347aef5ce3431eb54e0a2506910c5e0298817445721b}" # Only Certificate_x509: - alias: "${LWM2M_KEYSTORE_ALIAS_SERVER:server}" + alias: "${LWM2M_KEYSTORE_SERVER_ALIAS:server}" + password: "${LWM2M_KEYSTORE_SERVER_PASSWORD:server_ks_password}" skip_validity_check_for_client_cert: "${TB_LWM2M_SERVER_SECURITY_SKIP_VALIDITY_CHECK_FOR_CLIENT_CERT:false}" bootstrap: enable: "${LWM2M_ENABLED_BS:true}" @@ -123,12 +120,9 @@ transport: security: bind_address: "${LWM2M_BIND_ADDRESS_SECURITY_BS:0.0.0.0}" bind_port: "${LWM2M_BIND_PORT_SECURITY_BS:5688}" - # Only for RPK: Public & Private Key. If the keystore file is missing or not working - public_x: "${LWM2M_SERVER_PUBLIC_X_BS:5017c87a1c1768264656b3b355434b0def6edb8b9bf166a4762d9930cd730f91}" - public_y: "${LWM2M_SERVER_PUBLIC_Y_BS:3fc4e61bcd8901ec27c424114c3e887ed372497f0c2cf85839b8443e76988b34}" - private_encoded: "${LWM2M_SERVER_PRIVATE_ENCODED_BS:308193020100301306072a8648ce3d020106082a8648ce3d0301070479307702010104205ecafd90caa7be45c42e1f3f32571632b8409e6e6249d7124f4ba56fab3c8083a00a06082a8648ce3d030107a144034200045017c87a1c1768264656b3b355434b0def6edb8b9bf166a4762d9930cd730f913fc4e61bcd8901ec27c424114c3e887ed372497f0c2cf85839b8443e76988b34}" # Only Certificate_x509: - alias: "${LWM2M_KEYSTORE_ALIAS_BS:bootstrap}" + alias: "${LWM2M_KEYSTORE_BS_ALIAS:bootstrap}" + password: "${LWM2M_KEYSTORE_BS_PASSWORD:server_ks_password}" security: # Certificate_x509: # To get helps about files format and how to generate it, see: https://github.com/eclipse/leshan/wiki/Credential-files-format