Credential.java revision 4e940bb499f65b4305dbeb2e01237c43c2b0b42d
1package com.android.server.wifi.hotspot2.pps; 2 3import android.net.wifi.WifiEnterpriseConfig; 4import android.security.Credentials; 5import android.security.KeyStore; 6import android.text.TextUtils; 7import android.util.Base64; 8import android.util.Log; 9 10import com.android.server.wifi.anqp.eap.EAP; 11import com.android.server.wifi.anqp.eap.EAPMethod; 12import com.android.server.wifi.anqp.eap.NonEAPInnerAuth; 13import com.android.server.wifi.hotspot2.Utils; 14import com.android.server.wifi.hotspot2.omadm.OMAException; 15 16import java.io.IOException; 17import java.nio.charset.StandardCharsets; 18import java.security.GeneralSecurityException; 19import java.security.MessageDigest; 20 21public class Credential { 22 public enum CertType {IEEE, x509v3} 23 24 public static final String CertTypeX509 = "x509v3"; 25 public static final String CertTypeIEEE = "802.1ar"; 26 27 private final long mCtime; 28 private final long mExpTime; 29 private final String mRealm; 30 private final boolean mCheckAAACert; 31 32 private final String mUserName; 33 private final String mPassword; 34 private final boolean mMachineManaged; 35 private final String mSTokenApp; 36 private final boolean mShare; 37 private final EAPMethod mEAPMethod; 38 39 private final CertType mCertType; 40 private final byte[] mFingerPrint; 41 42 private final String mImsi; 43 44 public Credential(long ctime, long expTime, String realm, boolean checkAAACert, 45 EAPMethod eapMethod, String userName, String password, 46 boolean machineManaged, String stApp, boolean share) { 47 mCtime = ctime; 48 mExpTime = expTime; 49 mRealm = realm; 50 mCheckAAACert = checkAAACert; 51 mEAPMethod = eapMethod; 52 mUserName = userName; 53 54 if (!TextUtils.isEmpty(password)) { 55 byte[] pwOctets = Base64.decode(password, Base64.DEFAULT); 56 mPassword = new String(pwOctets, StandardCharsets.UTF_8); 57 } else { 58 mPassword = null; 59 } 60 61 mMachineManaged = machineManaged; 62 mSTokenApp = stApp; 63 mShare = share; 64 65 mCertType = null; 66 mFingerPrint = null; 67 68 mImsi = null; 69 } 70 71 public Credential(long ctime, long expTime, String realm, boolean checkAAACert, 72 EAPMethod eapMethod, Credential.CertType certType, byte[] fingerPrint) { 73 mCtime = ctime; 74 mExpTime = expTime; 75 mRealm = realm; 76 mCheckAAACert = checkAAACert; 77 mEAPMethod = eapMethod; 78 mCertType = certType; 79 mFingerPrint = fingerPrint; 80 81 mUserName = null; 82 mPassword = null; 83 mMachineManaged = false; 84 mSTokenApp = null; 85 mShare = false; 86 87 mImsi = null; 88 } 89 90 public Credential(long ctime, long expTime, String realm, boolean checkAAACert, 91 EAPMethod eapMethod, String imsi) { 92 mCtime = ctime; 93 mExpTime = expTime; 94 mRealm = realm; 95 mCheckAAACert = checkAAACert; 96 mEAPMethod = eapMethod; 97 mImsi = imsi; 98 99 mCertType = null; 100 mFingerPrint = null; 101 102 mUserName = null; 103 mPassword = null; 104 mMachineManaged = false; 105 mSTokenApp = null; 106 mShare = false; 107 } 108 109 public Credential(WifiEnterpriseConfig enterpriseConfig, KeyStore keyStore) throws IOException { 110 mCtime = 0; 111 mExpTime = 0; 112 mRealm = enterpriseConfig.getRealm(); 113 mCheckAAACert = true; 114 mEAPMethod = mapEapMethod(enterpriseConfig.getEapMethod(), 115 enterpriseConfig.getPhase2Method()); 116 mCertType = mEAPMethod.getEAPMethodID() == EAP.EAPMethodID.EAP_TLS ? CertType.x509v3 : null; 117 byte[] fingerPrint; 118 119 if (enterpriseConfig.getClientCertificate() != null) { 120 // !!! Not sure this will be true in any practical instances: 121 try { 122 MessageDigest digester = MessageDigest.getInstance("SHA-256"); 123 fingerPrint = digester.digest(enterpriseConfig.getClientCertificate().getEncoded()); 124 } 125 catch (GeneralSecurityException gse) { 126 Log.e("CRED", "Failed to generate certificate fingerprint: " + gse); 127 fingerPrint = null; 128 } 129 } 130 else if (enterpriseConfig.getClientCertificateAlias() != null) { 131 String alias = enterpriseConfig.getClientCertificateAlias(); 132 Log.d("HS2J", "Client alias '" + alias + "'"); 133 byte[] octets = keyStore.get(Credentials.USER_CERTIFICATE + alias); 134 Log.d("HS2J", "DER: " + (octets == null ? "-" : Integer.toString(octets.length))); 135 if (octets != null) { 136 try { 137 MessageDigest digester = MessageDigest.getInstance("SHA-256"); 138 fingerPrint = digester.digest(octets); 139 } 140 catch (GeneralSecurityException gse) { 141 Log.e("HS2J", "Failed to construct digest: " + gse); 142 fingerPrint = null; 143 } 144 } 145 else // !!! The current alias is *not* derived from the fingerprint... 146 { 147 try { 148 fingerPrint = Base64.decode(enterpriseConfig.getClientCertificateAlias(), 149 Base64.DEFAULT); 150 } catch (IllegalArgumentException ie) { 151 Log.e("CRED", "Bad base 64 alias"); 152 fingerPrint = null; 153 } 154 } 155 } 156 else { 157 fingerPrint = null; 158 } 159 mFingerPrint = fingerPrint; 160 mImsi = enterpriseConfig.getPlmn(); 161 mUserName = enterpriseConfig.getIdentity(); 162 mPassword = enterpriseConfig.getPassword(); 163 mMachineManaged = false; 164 mSTokenApp = null; 165 mShare = false; 166 } 167 168 public static CertType mapCertType(String certType) throws OMAException { 169 if (certType.equalsIgnoreCase(CertTypeX509)) { 170 return CertType.x509v3; 171 } else if (certType.equalsIgnoreCase(CertTypeIEEE)) { 172 return CertType.IEEE; 173 } else { 174 throw new OMAException("Invalid cert type: '" + certType + "'"); 175 } 176 } 177 178 private static EAPMethod mapEapMethod(int eapMethod, int phase2Method) throws IOException { 179 if (eapMethod == WifiEnterpriseConfig.Eap.TLS) { 180 return new EAPMethod(EAP.EAPMethodID.EAP_TLS, null); 181 } else if (eapMethod == WifiEnterpriseConfig.Eap.TTLS) { 182 /* keep this table in sync with WifiEnterpriseConfig.Phase2 enum */ 183 NonEAPInnerAuth inner; 184 switch (phase2Method) { 185 case WifiEnterpriseConfig.Phase2.PAP: 186 inner = new NonEAPInnerAuth(NonEAPInnerAuth.NonEAPType.PAP); 187 break; 188 case WifiEnterpriseConfig.Phase2.MSCHAP: 189 inner = new NonEAPInnerAuth(NonEAPInnerAuth.NonEAPType.MSCHAP); 190 break; 191 case WifiEnterpriseConfig.Phase2.MSCHAPV2: 192 inner = new NonEAPInnerAuth(NonEAPInnerAuth.NonEAPType.MSCHAPv2); 193 break; 194 default: 195 throw new IOException("TTLS phase2 method " + 196 phase2Method + " not valid for Passpoint"); 197 } 198 return new EAPMethod(EAP.EAPMethodID.EAP_TTLS, inner); 199 } else if (eapMethod == WifiEnterpriseConfig.Eap.PEAP) { 200 /* restricting passpoint implementation from using PEAP */ 201 return null; 202 } else if (eapMethod == WifiEnterpriseConfig.Eap.PWD) { 203 /* restricting passpoint implementation from using EAP_PWD */ 204 return null; 205 } else if (eapMethod == WifiEnterpriseConfig.Eap.SIM) { 206 return new EAPMethod(EAP.EAPMethodID.EAP_SIM, null); 207 } else if (eapMethod == WifiEnterpriseConfig.Eap.AKA) { 208 return new EAPMethod(EAP.EAPMethodID.EAP_AKA, null); 209 } 210 /* 211 TODO: Uncomment this when AKA_PRIME is defined in WifiEnterpriseConfig 212 else if (eapMethod == WifiEnterpriseConfig.Eap.AKA_PRIME) { 213 return new EAPMethod(EAP.EAPMethodID.EAP_AKAPrim, null); 214 } 215 */ 216 217 Log.d("PARSE-LOG", "Invalid eap method"); 218 return null; 219 } 220 221 public EAPMethod getEAPMethod() { 222 return mEAPMethod; 223 } 224 225 public String getRealm() { 226 return mRealm; 227 } 228 229 public String getImsi() { 230 return mImsi; 231 } 232 233 public String getUserName() { 234 return mUserName; 235 } 236 237 public String getPassword() { 238 return mPassword; 239 } 240 241 public CertType getCertType() { 242 return mCertType; 243 } 244 245 public byte[] getFingerPrint() { 246 return mFingerPrint; 247 } 248 249 @Override 250 public String toString() { 251 return "Credential{" + 252 "mCtime=" + Utils.toUTCString(mCtime) + 253 ", mExpTime=" + Utils.toUTCString(mExpTime) + 254 ", mRealm='" + mRealm + '\'' + 255 ", mCheckAAACert=" + mCheckAAACert + 256 ", mUserName='" + mUserName + '\'' + 257 ", mPassword='" + mPassword + '\'' + 258 ", mMachineManaged=" + mMachineManaged + 259 ", mSTokenApp='" + mSTokenApp + '\'' + 260 ", mShare=" + mShare + 261 ", mEAPMethod=" + mEAPMethod + 262 ", mCertType=" + mCertType + 263 ", mFingerPrint=" + Utils.toHexString(mFingerPrint) + 264 ", mImsi='" + mImsi + '\'' + 265 '}'; 266 } 267} 268