[androidtv] Moves Shim PKI to AndroidTVPKI and adds Trusted CA Certificate functions (#15174)

Signed-off-by: Ben Rosenblum <rosenblumb@gmail.com>
This commit is contained in:
morph166955 2023-07-15 02:40:41 -05:00 committed by GitHub
parent cad86bc83b
commit ee687aa1cd
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 40 additions and 20 deletions

View File

@ -18,7 +18,6 @@ import static org.openhab.binding.androidtv.internal.protocol.googletv.GoogleTVC
import java.io.BufferedReader; import java.io.BufferedReader;
import java.io.BufferedWriter; import java.io.BufferedWriter;
import java.io.File; import java.io.File;
import java.io.FileInputStream;
import java.io.IOException; import java.io.IOException;
import java.io.InputStreamReader; import java.io.InputStreamReader;
import java.io.InterruptedIOException; import java.io.InterruptedIOException;
@ -33,11 +32,9 @@ import java.net.SocketTimeoutException;
import java.net.UnknownHostException; import java.net.UnknownHostException;
import java.nio.charset.StandardCharsets; import java.nio.charset.StandardCharsets;
import java.security.GeneralSecurityException; import java.security.GeneralSecurityException;
import java.security.KeyStore;
import java.security.NoSuchAlgorithmException; import java.security.NoSuchAlgorithmException;
import java.security.UnrecoverableKeyException; import java.security.UnrecoverableKeyException;
import java.security.cert.Certificate; import java.security.cert.Certificate;
import java.security.cert.CertificateEncodingException;
import java.security.cert.CertificateException; import java.security.cert.CertificateException;
import java.security.cert.X509Certificate; import java.security.cert.X509Certificate;
import java.util.concurrent.BlockingQueue; import java.util.concurrent.BlockingQueue;
@ -369,17 +366,20 @@ public class GoogleTVConnectionManager {
try { try {
this.shimX509ClientChain = shimX509ClientChain; this.shimX509ClientChain = shimX509ClientChain;
logger.trace("Setting shimX509ClientChain {}", config.port); logger.trace("Setting shimX509ClientChain {}", config.port);
if (shimX509ClientChain != null && logger.isTraceEnabled()) { if (shimX509ClientChain != null) {
for (int cert = 0; cert < shimX509ClientChain.length; cert++) { if (logger.isTraceEnabled()) {
logger.trace("Subject DN: {}", shimX509ClientChain[cert].getSubjectX500Principal()); logger.trace("Subject DN: {}", shimX509ClientChain[0].getSubjectX500Principal());
logger.trace("Issuer DN: {}", shimX509ClientChain[cert].getIssuerX500Principal()); logger.trace("Issuer DN: {}", shimX509ClientChain[0].getIssuerX500Principal());
logger.trace("Serial number: {}", shimX509ClientChain[cert].getSerialNumber()); logger.trace("Serial number: {}", shimX509ClientChain[0].getSerialNumber());
logger.trace("Cert: {}", GoogleTVRequest 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) { } catch (Exception e) {
logger.trace("setShimX509ClientChain CertificateEncodingException", e); logger.trace("setShimX509ClientChain Exception", e);
} }
} }
@ -617,19 +617,13 @@ public class GoogleTVConnectionManager {
public void shimInitialize() { public void shimInitialize() {
synchronized (connectionLock) { synchronized (connectionLock) {
AndroidTVPKI shimPKI = new AndroidTVPKI();
byte[] shimEncryptionKey = shimPKI.generateEncryptionKey();
SSLContext sslContext; SSLContext sslContext;
try { 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()); 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(); TrustManager[] trustManagers = defineNoOpTrustManager();
sslContext = SSLContext.getInstance("TLS"); sslContext = SSLContext.getInstance("TLS");
@ -671,6 +665,10 @@ public class GoogleTVConnectionManager {
logger.trace("Connection from: {}", logger.trace("Connection from: {}",
((X509Certificate) cchain2[i]).getSubjectX500Principal()); ((X509Certificate) cchain2[i]).getSubjectX500Principal());
shimX509ClientChain[i] = ((X509Certificate) cchain2[i]); 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)) { if (this.config.mode.equals(PIN_MODE)) {

View File

@ -74,6 +74,7 @@ public class AndroidTVPKI {
private String privKey = ""; private String privKey = "";
private String cert = ""; private String cert = "";
private String caCert = "";
private String keystoreFileName = ""; private String keystoreFileName = "";
private String keystoreAlgorithm = "RSA"; private String keystoreAlgorithm = "RSA";
private int keyLength = 2048; private int keyLength = 2048;
@ -170,6 +171,20 @@ public class AndroidTVPKI {
return cert; 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) { public void setAlias(String alias) {
this.alias = alias; this.alias = alias;
} }
@ -234,6 +249,10 @@ public class AndroidTVPKI {
byte[] byteKey = keystore.getKey(this.alias, keystorePassword.toCharArray()).getEncoded(); byte[] byteKey = keystore.getKey(this.alias, keystorePassword.toCharArray()).getEncoded();
this.privKey = encrypt(new String(Base64.getEncoder().encode(byteKey)), key); this.privKey = encrypt(new String(Base64.getEncoder().encode(byteKey)), key);
setCert(keystore.getCertificate(this.alias)); setCert(keystore.getCertificate(this.alias));
Certificate caCert = keystore.getCertificate("trustedCa");
if (caCert != null) {
setCaCert(caCert);
}
} }
public KeyStore getKeyStore(String keystorePassword, byte[] keyString) public KeyStore getKeyStore(String keystorePassword, byte[] keyString)
@ -245,6 +264,9 @@ public class AndroidTVPKI {
KeyFactory kf = KeyFactory.getInstance(this.keystoreAlgorithm); KeyFactory kf = KeyFactory.getInstance(this.keystoreAlgorithm);
keystore.setKeyEntry(this.alias, kf.generatePrivate(keySpec), keystorePassword.toCharArray(), keystore.setKeyEntry(this.alias, kf.generatePrivate(keySpec), keystorePassword.toCharArray(),
new java.security.cert.Certificate[] { getCert() }); new java.security.cert.Certificate[] { getCert() });
if (!caCert.isEmpty()) {
keystore.setCertificateEntry("trustedCa", getCaCert());
}
return keystore; return keystore;
} }