diff --git a/bundles/org.openhab.binding.androidtv/src/main/java/org/openhab/binding/androidtv/internal/protocol/googletv/GoogleTVConnectionManager.java b/bundles/org.openhab.binding.androidtv/src/main/java/org/openhab/binding/androidtv/internal/protocol/googletv/GoogleTVConnectionManager.java index 92ac28454..8396a6053 100644 --- a/bundles/org.openhab.binding.androidtv/src/main/java/org/openhab/binding/androidtv/internal/protocol/googletv/GoogleTVConnectionManager.java +++ b/bundles/org.openhab.binding.androidtv/src/main/java/org/openhab/binding/androidtv/internal/protocol/googletv/GoogleTVConnectionManager.java @@ -18,7 +18,6 @@ import static org.openhab.binding.androidtv.internal.protocol.googletv.GoogleTVC import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.File; -import java.io.FileInputStream; import java.io.IOException; import java.io.InputStreamReader; import java.io.InterruptedIOException; @@ -33,11 +32,9 @@ import java.net.SocketTimeoutException; import java.net.UnknownHostException; import java.nio.charset.StandardCharsets; import java.security.GeneralSecurityException; -import java.security.KeyStore; import java.security.NoSuchAlgorithmException; import java.security.UnrecoverableKeyException; import java.security.cert.Certificate; -import java.security.cert.CertificateEncodingException; import java.security.cert.CertificateException; import java.security.cert.X509Certificate; import java.util.concurrent.BlockingQueue; @@ -369,17 +366,20 @@ public class GoogleTVConnectionManager { try { this.shimX509ClientChain = shimX509ClientChain; logger.trace("Setting shimX509ClientChain {}", config.port); - if (shimX509ClientChain != null && logger.isTraceEnabled()) { - for (int cert = 0; cert < shimX509ClientChain.length; cert++) { - logger.trace("Subject DN: {}", shimX509ClientChain[cert].getSubjectX500Principal()); - logger.trace("Issuer DN: {}", shimX509ClientChain[cert].getIssuerX500Principal()); - logger.trace("Serial number: {}", shimX509ClientChain[cert].getSerialNumber()); + if (shimX509ClientChain != null) { + if (logger.isTraceEnabled()) { + logger.trace("Subject DN: {}", shimX509ClientChain[0].getSubjectX500Principal()); + logger.trace("Issuer DN: {}", shimX509ClientChain[0].getIssuerX500Principal()); + logger.trace("Serial number: {}", shimX509ClientChain[0].getSerialNumber()); logger.trace("Cert: {}", GoogleTVRequest - .decodeMessage(GoogleTVUtils.byteArrayToString(shimX509ClientChain[cert].getEncoded()))); + .decodeMessage(GoogleTVUtils.byteArrayToString(shimX509ClientChain[0].getEncoded()))); } + androidtvPKI.setCaCert(shimX509ClientChain[0]); + androidtvPKI.saveKeyStore(config.keystorePassword, this.encryptionKey); + } - } catch (CertificateEncodingException e) { - logger.trace("setShimX509ClientChain CertificateEncodingException", e); + } catch (Exception e) { + logger.trace("setShimX509ClientChain Exception", e); } } @@ -617,19 +617,13 @@ public class GoogleTVConnectionManager { public void shimInitialize() { synchronized (connectionLock) { - AndroidTVPKI shimPKI = new AndroidTVPKI(); - byte[] shimEncryptionKey = shimPKI.generateEncryptionKey(); SSLContext sslContext; try { - shimPKI.generateNewKeyPair(shimEncryptionKey); - // Move this to PKI. Shim requires a trusted cert chain in the keystore. - KeyStore keystore = KeyStore.getInstance("JKS"); - FileInputStream keystoreInputStream = new FileInputStream(config.keystoreFileName); - keystore.load(keystoreInputStream, config.keystorePassword.toCharArray()); - KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm()); - kmf.init(keystore, config.keystorePassword.toCharArray()); + kmf.init(androidtvPKI.getKeyStore(config.keystorePassword, this.encryptionKey), + config.keystorePassword.toCharArray()); + TrustManager[] trustManagers = defineNoOpTrustManager(); sslContext = SSLContext.getInstance("TLS"); @@ -671,6 +665,10 @@ public class GoogleTVConnectionManager { logger.trace("Connection from: {}", ((X509Certificate) cchain2[i]).getSubjectX500Principal()); shimX509ClientChain[i] = ((X509Certificate) cchain2[i]); + if (this.config.mode.equals(DEFAULT_MODE) && logger.isTraceEnabled()) { + logger.trace("Cert: {}", GoogleTVRequest.decodeMessage( + GoogleTVUtils.byteArrayToString(((X509Certificate) cchain2[i]).getEncoded()))); + } } if (this.config.mode.equals(PIN_MODE)) { diff --git a/bundles/org.openhab.binding.androidtv/src/main/java/org/openhab/binding/androidtv/internal/utils/AndroidTVPKI.java b/bundles/org.openhab.binding.androidtv/src/main/java/org/openhab/binding/androidtv/internal/utils/AndroidTVPKI.java index aad3a8a89..3e3a9e974 100644 --- a/bundles/org.openhab.binding.androidtv/src/main/java/org/openhab/binding/androidtv/internal/utils/AndroidTVPKI.java +++ b/bundles/org.openhab.binding.androidtv/src/main/java/org/openhab/binding/androidtv/internal/utils/AndroidTVPKI.java @@ -74,6 +74,7 @@ public class AndroidTVPKI { private String privKey = ""; private String cert = ""; + private String caCert = ""; private String keystoreFileName = ""; private String keystoreAlgorithm = "RSA"; private int keyLength = 2048; @@ -170,6 +171,20 @@ public class AndroidTVPKI { return cert; } + public void setCaCert(String caCert) { + this.caCert = caCert; + } + + public void setCaCert(Certificate caCert) throws CertificateEncodingException { + this.caCert = new String(Base64.getEncoder().encode(caCert.getEncoded())); + } + + public Certificate getCaCert() throws CertificateException { + Certificate caCert = CertificateFactory.getInstance("X.509") + .generateCertificate(new ByteArrayInputStream(Base64.getDecoder().decode(this.caCert.getBytes()))); + return caCert; + } + public void setAlias(String alias) { this.alias = alias; } @@ -234,6 +249,10 @@ public class AndroidTVPKI { byte[] byteKey = keystore.getKey(this.alias, keystorePassword.toCharArray()).getEncoded(); this.privKey = encrypt(new String(Base64.getEncoder().encode(byteKey)), key); setCert(keystore.getCertificate(this.alias)); + Certificate caCert = keystore.getCertificate("trustedCa"); + if (caCert != null) { + setCaCert(caCert); + } } public KeyStore getKeyStore(String keystorePassword, byte[] keyString) @@ -245,6 +264,9 @@ public class AndroidTVPKI { KeyFactory kf = KeyFactory.getInstance(this.keystoreAlgorithm); keystore.setKeyEntry(this.alias, kf.generatePrivate(keySpec), keystorePassword.toCharArray(), new java.security.cert.Certificate[] { getCert() }); + if (!caCert.isEmpty()) { + keystore.setCertificateEntry("trustedCa", getCaCert()); + } return keystore; }