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