1ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvistpackage com.android.hotspot2.osu; 2ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist 3ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvistimport android.util.Log; 4ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist 5ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvistimport com.android.hotspot2.pps.HomeSP; 6ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist 7ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvistimport java.io.IOException; 8ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvistimport java.net.Socket; 9ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvistimport java.security.GeneralSecurityException; 10ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvistimport java.security.KeyStore; 11ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvistimport java.security.KeyStoreException; 12ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvistimport java.security.Principal; 13ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvistimport java.security.PrivateKey; 14ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvistimport java.security.cert.Certificate; 15ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvistimport java.security.cert.X509Certificate; 16ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvistimport java.util.ArrayList; 17ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvistimport java.util.HashMap; 18ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvistimport java.util.List; 19ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvistimport java.util.Map; 20ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist 21ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvistimport javax.net.ssl.X509KeyManager; 22ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist 23ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvistpublic class ClientKeyManager implements X509KeyManager { 24ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist private final KeyStore mKeyStore; 25ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist private final Map<OSUCertType, String> mAliasMap; 26ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist private final Map<OSUCertType, Object> mTempKeys; 27ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist 28ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist private static final String sTempAlias = "client-alias"; 29ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist 30ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist public ClientKeyManager(HomeSP homeSP, KeyStore keyStore) throws IOException { 31ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist mKeyStore = keyStore; 32ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist mAliasMap = new HashMap<>(); 33ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist mAliasMap.put(OSUCertType.AAA, OSUManager.CERT_CLT_CA_ALIAS + homeSP.getFQDN()); 34ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist mAliasMap.put(OSUCertType.Client, OSUManager.CERT_CLT_CERT_ALIAS + homeSP.getFQDN()); 35ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist mAliasMap.put(OSUCertType.PrivateKey, OSUManager.CERT_CLT_KEY_ALIAS + homeSP.getFQDN()); 36ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist mTempKeys = new HashMap<>(); 37ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist } 38ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist 39ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist public void reloadKeys(Map<OSUCertType, List<X509Certificate>> certs, PrivateKey key) 40ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist throws IOException { 41ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist List<X509Certificate> clientCerts = certs.get(OSUCertType.Client); 42ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist X509Certificate[] certArray = new X509Certificate[clientCerts.size()]; 43ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist int n = 0; 44ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist for (X509Certificate cert : clientCerts) { 45ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist certArray[n++] = cert; 46ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist } 47ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist mTempKeys.put(OSUCertType.Client, certArray); 48ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist mTempKeys.put(OSUCertType.PrivateKey, key); 49ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist } 50ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist 51ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist @Override 52ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist public String chooseClientAlias(String[] keyType, Principal[] issuers, Socket socket) { 53ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist if (mTempKeys.isEmpty()) { 54ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist return mAliasMap.get(OSUCertType.Client); 55ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist } else { 56ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist return sTempAlias; 57ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist } 58ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist } 59ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist 60ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist @Override 61ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist public String[] getClientAliases(String keyType, Principal[] issuers) { 62ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist if (mTempKeys.isEmpty()) { 63ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist String alias = mAliasMap.get(OSUCertType.Client); 64ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist return alias != null ? new String[]{alias} : null; 65ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist } else { 66ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist return new String[]{sTempAlias}; 67ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist } 68ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist } 69ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist 70ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist @Override 71ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist public String chooseServerAlias(String keyType, Principal[] issuers, Socket socket) { 72ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist throw new UnsupportedOperationException(); 73ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist } 74ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist 75ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist @Override 76ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist public String[] getServerAliases(String keyType, Principal[] issuers) { 77ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist throw new UnsupportedOperationException(); 78ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist } 79ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist 80ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist @Override 81ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist public X509Certificate[] getCertificateChain(String alias) { 82ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist if (mTempKeys.isEmpty()) { 83ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist if (!mAliasMap.get(OSUCertType.Client).equals(alias)) { 84ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist Log.w(OSUManager.TAG, "Bad cert alias requested: '" + alias + "'"); 85ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist return null; 86ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist } 87ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist try { 88ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist List<X509Certificate> certs = new ArrayList<>(); 89ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist for (Certificate certificate : 90ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist mKeyStore.getCertificateChain(mAliasMap.get(OSUCertType.Client))) { 91ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist if (certificate instanceof X509Certificate) { 92ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist certs.add((X509Certificate) certificate); 93ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist } 94ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist } 95ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist return certs.toArray(new X509Certificate[certs.size()]); 96ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist } catch (KeyStoreException kse) { 97ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist Log.w(OSUManager.TAG, "Failed to retrieve certificates: " + kse); 98ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist return null; 99ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist } 100ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist } else if (sTempAlias.equals(alias)) { 101ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist return (X509Certificate[]) mTempKeys.get(OSUCertType.Client); 102ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist } else { 103ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist Log.w(OSUManager.TAG, "Bad cert alias requested: '" + alias + "'"); 104ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist return null; 105ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist } 106ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist } 107ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist 108ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist @Override 109ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist public PrivateKey getPrivateKey(String alias) { 110ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist if (mTempKeys.isEmpty()) { 111ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist if (!mAliasMap.get(OSUCertType.Client).equals(alias)) { 112ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist Log.w(OSUManager.TAG, "Bad key alias requested: '" + alias + "'"); 113ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist } 114ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist try { 115ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist return (PrivateKey) mKeyStore.getKey(mAliasMap.get(OSUCertType.PrivateKey), null); 116ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist } catch (GeneralSecurityException gse) { 117ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist Log.w(OSUManager.TAG, "Failed to retrieve private key: " + gse); 118ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist return null; 119ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist } 120ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist } else if (sTempAlias.equals(alias)) { 121ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist return (PrivateKey) mTempKeys.get(OSUCertType.PrivateKey); 122ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist } else { 123ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist Log.w(OSUManager.TAG, "Bad cert alias requested: '" + alias + "'"); 124ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist return null; 125ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist } 126ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist } 127ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist} 128