WifiEnterpriseConfig.java revision 8b643c13f97c0f304a45039b9d1fe6900940499e
19b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff/* 29b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff * Copyright (C) 2013 The Android Open Source Project 39b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff * 49b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff * Licensed under the Apache License, Version 2.0 (the "License"); 59b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff * you may not use this file except in compliance with the License. 69b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff * You may obtain a copy of the License at 79b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff * 89b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff * http://www.apache.org/licenses/LICENSE-2.0 99b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff * 109b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff * Unless required by applicable law or agreed to in writing, software 119b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff * distributed under the License is distributed on an "AS IS" BASIS, 129b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 139b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff * See the License for the specific language governing permissions and 149b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff * limitations under the License. 159b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff */ 169b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriffpackage android.net.wifi; 179b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff 189b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriffimport android.os.Parcel; 199b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriffimport android.os.Parcelable; 208b643c13f97c0f304a45039b9d1fe6900940499eIrfan Sheriffimport android.os.Process; 219b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriffimport android.security.Credentials; 229b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriffimport android.text.TextUtils; 2326d0076f0dbb021c4e5cc1b37b632b2223fd9278Irfan Sheriff 2426d0076f0dbb021c4e5cc1b37b632b2223fd9278Irfan Sheriffimport com.android.org.bouncycastle.asn1.ASN1InputStream; 2526d0076f0dbb021c4e5cc1b37b632b2223fd9278Irfan Sheriffimport com.android.org.bouncycastle.asn1.ASN1Sequence; 2626d0076f0dbb021c4e5cc1b37b632b2223fd9278Irfan Sheriffimport com.android.org.bouncycastle.asn1.DEROctetString; 2726d0076f0dbb021c4e5cc1b37b632b2223fd9278Irfan Sheriffimport com.android.org.bouncycastle.asn1.x509.BasicConstraints; 2826d0076f0dbb021c4e5cc1b37b632b2223fd9278Irfan Sheriff 2926d0076f0dbb021c4e5cc1b37b632b2223fd9278Irfan Sheriffimport java.io.ByteArrayInputStream; 3026d0076f0dbb021c4e5cc1b37b632b2223fd9278Irfan Sheriffimport java.io.IOException; 3126d0076f0dbb021c4e5cc1b37b632b2223fd9278Irfan Sheriffimport java.security.KeyFactory; 3226d0076f0dbb021c4e5cc1b37b632b2223fd9278Irfan Sheriffimport java.security.KeyStore; 3326d0076f0dbb021c4e5cc1b37b632b2223fd9278Irfan Sheriffimport java.security.NoSuchAlgorithmException; 3426d0076f0dbb021c4e5cc1b37b632b2223fd9278Irfan Sheriffimport java.security.PrivateKey; 3526d0076f0dbb021c4e5cc1b37b632b2223fd9278Irfan Sheriffimport java.security.cert.Certificate; 3626d0076f0dbb021c4e5cc1b37b632b2223fd9278Irfan Sheriffimport java.security.cert.CertificateEncodingException; 3726d0076f0dbb021c4e5cc1b37b632b2223fd9278Irfan Sheriffimport java.security.cert.CertificateException; 3826d0076f0dbb021c4e5cc1b37b632b2223fd9278Irfan Sheriffimport java.security.cert.CertificateFactory; 3926d0076f0dbb021c4e5cc1b37b632b2223fd9278Irfan Sheriffimport java.security.cert.X509Certificate; 4026d0076f0dbb021c4e5cc1b37b632b2223fd9278Irfan Sheriffimport java.security.spec.InvalidKeySpecException; 4126d0076f0dbb021c4e5cc1b37b632b2223fd9278Irfan Sheriffimport java.security.spec.PKCS8EncodedKeySpec; 429b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriffimport java.util.HashMap; 439b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriffimport java.util.Map; 449b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff 45fdc028383a01eaaa9bf93cb5d3ce50bd744eab52Irfan Sheriff/** 46fdc028383a01eaaa9bf93cb5d3ce50bd744eab52Irfan Sheriff * Enterprise configuration details for Wi-Fi. Stores details about the EAP method 47fdc028383a01eaaa9bf93cb5d3ce50bd744eab52Irfan Sheriff * and any associated credentials. 48fdc028383a01eaaa9bf93cb5d3ce50bd744eab52Irfan Sheriff */ 499b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriffpublic class WifiEnterpriseConfig implements Parcelable { 509b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff private static final String TAG = "WifiEnterpriseConfig"; 519b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff /** 529b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff * In old configurations, the "private_key" field was used. However, newer 539b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff * configurations use the key_id field with the engine_id set to "keystore". 549b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff * If this field is found in the configuration, the migration code is 559b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff * triggered. 569b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff */ 579b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff private static final String OLD_PRIVATE_KEY_NAME = "private_key"; 589b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff 599b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff /** 609b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff * String representing the keystore OpenSSL ENGINE's ID. 619b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff */ 629b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff private static final String ENGINE_ID_KEYSTORE = "keystore"; 639b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff 649b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff /** 659b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff * String representing the keystore URI used for wpa_supplicant. 669b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff */ 679b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff private static final String KEYSTORE_URI = "keystore://"; 689b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff 699b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff /** 709b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff * String to set the engine value to when it should be enabled. 719b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff */ 729b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff private static final String ENGINE_ENABLE = "1"; 739b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff 749b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff /** 759b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff * String to set the engine value to when it should be disabled. 769b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff */ 779b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff private static final String ENGINE_DISABLE = "0"; 789b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff 799b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff private static final String CA_CERT_PREFIX = KEYSTORE_URI + Credentials.CA_CERTIFICATE; 809b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff private static final String CLIENT_CERT_PREFIX = KEYSTORE_URI + Credentials.USER_CERTIFICATE; 819b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff 829b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff private static final String EAP_KEY = "eap"; 839b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff private static final String PHASE2_KEY = "phase2"; 849b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff private static final String IDENTITY_KEY = "identity"; 859b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff private static final String ANON_IDENTITY_KEY = "anonymous_identity"; 869b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff private static final String PASSWORD_KEY = "password"; 879b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff private static final String CLIENT_CERT_KEY = "client_cert"; 889b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff private static final String CA_CERT_KEY = "ca_cert"; 899b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff private static final String SUBJECT_MATCH_KEY = "subject_match"; 909b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff private static final String ENGINE_KEY = "engine"; 919b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff private static final String ENGINE_ID_KEY = "engine_id"; 929b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff private static final String PRIVATE_KEY_ID_KEY = "key_id"; 939b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff 949b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff private HashMap<String, String> mFields = new HashMap<String, String>(); 9526d0076f0dbb021c4e5cc1b37b632b2223fd9278Irfan Sheriff private X509Certificate mCaCert; 9626d0076f0dbb021c4e5cc1b37b632b2223fd9278Irfan Sheriff private PrivateKey mClientPrivateKey; 9726d0076f0dbb021c4e5cc1b37b632b2223fd9278Irfan Sheriff private X509Certificate mClientCertificate; 989b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff 999b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff /** This represents an empty value of an enterprise field. 1009b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff * NULL is used at wpa_supplicant to indicate an empty value 1019b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff */ 102e095675c872f40f630aa3f9189eb5c02f3cfee6dIrfan Sheriff static final String EMPTY_VALUE = "NULL"; 1039b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff 1049b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff public WifiEnterpriseConfig() { 105e095675c872f40f630aa3f9189eb5c02f3cfee6dIrfan Sheriff // Do not set defaults so that the enterprise fields that are not changed 106e095675c872f40f630aa3f9189eb5c02f3cfee6dIrfan Sheriff // by API are not changed underneath 107e095675c872f40f630aa3f9189eb5c02f3cfee6dIrfan Sheriff // This is essential because an app may not have all fields like password 108e095675c872f40f630aa3f9189eb5c02f3cfee6dIrfan Sheriff // available. It allows modification of subset of fields. 109e095675c872f40f630aa3f9189eb5c02f3cfee6dIrfan Sheriff 1109b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff } 1119b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff 1129b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff /** Copy constructor */ 1139b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff public WifiEnterpriseConfig(WifiEnterpriseConfig source) { 1149b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff for (String key : source.mFields.keySet()) { 1159b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff mFields.put(key, source.mFields.get(key)); 1169b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff } 1179b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff } 1189b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff 1199b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff @Override 1209b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff public int describeContents() { 1219b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff return 0; 1229b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff } 1239b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff 12486ee9640ee6d6bd9bb655af830eea5515400f25bIrfan Sheriff @Override 1259b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff public void writeToParcel(Parcel dest, int flags) { 1269b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff dest.writeInt(mFields.size()); 1279b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff for (Map.Entry<String, String> entry : mFields.entrySet()) { 1289b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff dest.writeString(entry.getKey()); 1299b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff dest.writeString(entry.getValue()); 1309b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff } 13126d0076f0dbb021c4e5cc1b37b632b2223fd9278Irfan Sheriff 13226d0076f0dbb021c4e5cc1b37b632b2223fd9278Irfan Sheriff writeCertificate(dest, mCaCert); 13326d0076f0dbb021c4e5cc1b37b632b2223fd9278Irfan Sheriff 13426d0076f0dbb021c4e5cc1b37b632b2223fd9278Irfan Sheriff if (mClientPrivateKey != null) { 13526d0076f0dbb021c4e5cc1b37b632b2223fd9278Irfan Sheriff String algorithm = mClientPrivateKey.getAlgorithm(); 13626d0076f0dbb021c4e5cc1b37b632b2223fd9278Irfan Sheriff byte[] userKeyBytes = mClientPrivateKey.getEncoded(); 13726d0076f0dbb021c4e5cc1b37b632b2223fd9278Irfan Sheriff dest.writeInt(userKeyBytes.length); 13826d0076f0dbb021c4e5cc1b37b632b2223fd9278Irfan Sheriff dest.writeByteArray(userKeyBytes); 13926d0076f0dbb021c4e5cc1b37b632b2223fd9278Irfan Sheriff dest.writeString(algorithm); 14026d0076f0dbb021c4e5cc1b37b632b2223fd9278Irfan Sheriff } else { 14126d0076f0dbb021c4e5cc1b37b632b2223fd9278Irfan Sheriff dest.writeInt(0); 14226d0076f0dbb021c4e5cc1b37b632b2223fd9278Irfan Sheriff } 14326d0076f0dbb021c4e5cc1b37b632b2223fd9278Irfan Sheriff 14426d0076f0dbb021c4e5cc1b37b632b2223fd9278Irfan Sheriff writeCertificate(dest, mClientCertificate); 14526d0076f0dbb021c4e5cc1b37b632b2223fd9278Irfan Sheriff } 14626d0076f0dbb021c4e5cc1b37b632b2223fd9278Irfan Sheriff 14726d0076f0dbb021c4e5cc1b37b632b2223fd9278Irfan Sheriff private void writeCertificate(Parcel dest, X509Certificate cert) { 14826d0076f0dbb021c4e5cc1b37b632b2223fd9278Irfan Sheriff if (cert != null) { 14926d0076f0dbb021c4e5cc1b37b632b2223fd9278Irfan Sheriff try { 15026d0076f0dbb021c4e5cc1b37b632b2223fd9278Irfan Sheriff byte[] certBytes = cert.getEncoded(); 15126d0076f0dbb021c4e5cc1b37b632b2223fd9278Irfan Sheriff dest.writeInt(certBytes.length); 15226d0076f0dbb021c4e5cc1b37b632b2223fd9278Irfan Sheriff dest.writeByteArray(certBytes); 15326d0076f0dbb021c4e5cc1b37b632b2223fd9278Irfan Sheriff } catch (CertificateEncodingException e) { 15426d0076f0dbb021c4e5cc1b37b632b2223fd9278Irfan Sheriff dest.writeInt(0); 15526d0076f0dbb021c4e5cc1b37b632b2223fd9278Irfan Sheriff } 15626d0076f0dbb021c4e5cc1b37b632b2223fd9278Irfan Sheriff } else { 15726d0076f0dbb021c4e5cc1b37b632b2223fd9278Irfan Sheriff dest.writeInt(0); 15826d0076f0dbb021c4e5cc1b37b632b2223fd9278Irfan Sheriff } 1599b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff } 1609b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff 1619b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff public static final Creator<WifiEnterpriseConfig> CREATOR = 1629b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff new Creator<WifiEnterpriseConfig>() { 1639b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff public WifiEnterpriseConfig createFromParcel(Parcel in) { 1649b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff WifiEnterpriseConfig enterpriseConfig = new WifiEnterpriseConfig(); 1659b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff int count = in.readInt(); 1669b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff for (int i = 0; i < count; i++) { 1679b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff String key = in.readString(); 1689b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff String value = in.readString(); 1699b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff enterpriseConfig.mFields.put(key, value); 1709b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff } 17126d0076f0dbb021c4e5cc1b37b632b2223fd9278Irfan Sheriff 17226d0076f0dbb021c4e5cc1b37b632b2223fd9278Irfan Sheriff enterpriseConfig.mCaCert = readCertificate(in); 17326d0076f0dbb021c4e5cc1b37b632b2223fd9278Irfan Sheriff 17426d0076f0dbb021c4e5cc1b37b632b2223fd9278Irfan Sheriff PrivateKey userKey = null; 17526d0076f0dbb021c4e5cc1b37b632b2223fd9278Irfan Sheriff int len = in.readInt(); 17626d0076f0dbb021c4e5cc1b37b632b2223fd9278Irfan Sheriff if (len > 0) { 17726d0076f0dbb021c4e5cc1b37b632b2223fd9278Irfan Sheriff try { 17826d0076f0dbb021c4e5cc1b37b632b2223fd9278Irfan Sheriff byte[] bytes = new byte[len]; 17926d0076f0dbb021c4e5cc1b37b632b2223fd9278Irfan Sheriff in.readByteArray(bytes); 18026d0076f0dbb021c4e5cc1b37b632b2223fd9278Irfan Sheriff String algorithm = in.readString(); 18126d0076f0dbb021c4e5cc1b37b632b2223fd9278Irfan Sheriff KeyFactory keyFactory = KeyFactory.getInstance(algorithm); 18226d0076f0dbb021c4e5cc1b37b632b2223fd9278Irfan Sheriff userKey = keyFactory.generatePrivate(new PKCS8EncodedKeySpec(bytes)); 18326d0076f0dbb021c4e5cc1b37b632b2223fd9278Irfan Sheriff } catch (NoSuchAlgorithmException e) { 18426d0076f0dbb021c4e5cc1b37b632b2223fd9278Irfan Sheriff userKey = null; 18526d0076f0dbb021c4e5cc1b37b632b2223fd9278Irfan Sheriff } catch (InvalidKeySpecException e) { 18626d0076f0dbb021c4e5cc1b37b632b2223fd9278Irfan Sheriff userKey = null; 18726d0076f0dbb021c4e5cc1b37b632b2223fd9278Irfan Sheriff } 18826d0076f0dbb021c4e5cc1b37b632b2223fd9278Irfan Sheriff } 18926d0076f0dbb021c4e5cc1b37b632b2223fd9278Irfan Sheriff 19026d0076f0dbb021c4e5cc1b37b632b2223fd9278Irfan Sheriff enterpriseConfig.mClientPrivateKey = userKey; 19126d0076f0dbb021c4e5cc1b37b632b2223fd9278Irfan Sheriff enterpriseConfig.mClientCertificate = readCertificate(in); 1929b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff return enterpriseConfig; 1939b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff } 1949b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff 19526d0076f0dbb021c4e5cc1b37b632b2223fd9278Irfan Sheriff private X509Certificate readCertificate(Parcel in) { 19626d0076f0dbb021c4e5cc1b37b632b2223fd9278Irfan Sheriff X509Certificate cert = null; 19726d0076f0dbb021c4e5cc1b37b632b2223fd9278Irfan Sheriff int len = in.readInt(); 19826d0076f0dbb021c4e5cc1b37b632b2223fd9278Irfan Sheriff if (len > 0) { 19926d0076f0dbb021c4e5cc1b37b632b2223fd9278Irfan Sheriff try { 20026d0076f0dbb021c4e5cc1b37b632b2223fd9278Irfan Sheriff byte[] bytes = new byte[len]; 20126d0076f0dbb021c4e5cc1b37b632b2223fd9278Irfan Sheriff in.readByteArray(bytes); 20226d0076f0dbb021c4e5cc1b37b632b2223fd9278Irfan Sheriff CertificateFactory cFactory = CertificateFactory.getInstance("X.509"); 20326d0076f0dbb021c4e5cc1b37b632b2223fd9278Irfan Sheriff cert = (X509Certificate) cFactory 20426d0076f0dbb021c4e5cc1b37b632b2223fd9278Irfan Sheriff .generateCertificate(new ByteArrayInputStream(bytes)); 20526d0076f0dbb021c4e5cc1b37b632b2223fd9278Irfan Sheriff } catch (CertificateException e) { 20626d0076f0dbb021c4e5cc1b37b632b2223fd9278Irfan Sheriff cert = null; 20726d0076f0dbb021c4e5cc1b37b632b2223fd9278Irfan Sheriff } 20826d0076f0dbb021c4e5cc1b37b632b2223fd9278Irfan Sheriff } 20926d0076f0dbb021c4e5cc1b37b632b2223fd9278Irfan Sheriff return cert; 21026d0076f0dbb021c4e5cc1b37b632b2223fd9278Irfan Sheriff } 21126d0076f0dbb021c4e5cc1b37b632b2223fd9278Irfan Sheriff 2129b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff public WifiEnterpriseConfig[] newArray(int size) { 2139b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff return new WifiEnterpriseConfig[size]; 2149b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff } 2159b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff }; 2169b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff 217fdc028383a01eaaa9bf93cb5d3ce50bd744eab52Irfan Sheriff /** The Extensible Authentication Protocol method used */ 2189b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff public static final class Eap { 219fdc028383a01eaaa9bf93cb5d3ce50bd744eab52Irfan Sheriff /** No EAP method used. Represents an empty config */ 220e095675c872f40f630aa3f9189eb5c02f3cfee6dIrfan Sheriff public static final int NONE = -1; 221fdc028383a01eaaa9bf93cb5d3ce50bd744eab52Irfan Sheriff /** Protected EAP */ 2229b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff public static final int PEAP = 0; 223fdc028383a01eaaa9bf93cb5d3ce50bd744eab52Irfan Sheriff /** EAP-Transport Layer Security */ 2249b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff public static final int TLS = 1; 225fdc028383a01eaaa9bf93cb5d3ce50bd744eab52Irfan Sheriff /** EAP-Tunneled Transport Layer Security */ 2269b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff public static final int TTLS = 2; 227fdc028383a01eaaa9bf93cb5d3ce50bd744eab52Irfan Sheriff /** EAP-Password */ 2289b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff public static final int PWD = 3; 2299b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff /** @hide */ 2309b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff public static final String[] strings = { "PEAP", "TLS", "TTLS", "PWD" }; 2319b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff } 2329b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff 233fdc028383a01eaaa9bf93cb5d3ce50bd744eab52Irfan Sheriff /** The inner authentication method used */ 2349b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff public static final class Phase2 { 2359b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff public static final int NONE = 0; 236fdc028383a01eaaa9bf93cb5d3ce50bd744eab52Irfan Sheriff /** Password Authentication Protocol */ 2379b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff public static final int PAP = 1; 238fdc028383a01eaaa9bf93cb5d3ce50bd744eab52Irfan Sheriff /** Microsoft Challenge Handshake Authentication Protocol */ 2399b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff public static final int MSCHAP = 2; 240fdc028383a01eaaa9bf93cb5d3ce50bd744eab52Irfan Sheriff /** Microsoft Challenge Handshake Authentication Protocol v2 */ 2419b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff public static final int MSCHAPV2 = 3; 242fdc028383a01eaaa9bf93cb5d3ce50bd744eab52Irfan Sheriff /** Generic Token Card */ 2439b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff public static final int GTC = 4; 2449b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff private static final String PREFIX = "auth="; 2459b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff /** @hide */ 2469b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff public static final String[] strings = {EMPTY_VALUE, "PAP", "MSCHAP", "MSCHAPV2", "GTC" }; 2479b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff } 2489b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff 24926d0076f0dbb021c4e5cc1b37b632b2223fd9278Irfan Sheriff /** Internal use only */ 25026d0076f0dbb021c4e5cc1b37b632b2223fd9278Irfan Sheriff HashMap<String, String> getFields() { 2519b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff return mFields; 2529b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff } 2539b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff 25426d0076f0dbb021c4e5cc1b37b632b2223fd9278Irfan Sheriff /** Internal use only */ 25526d0076f0dbb021c4e5cc1b37b632b2223fd9278Irfan Sheriff static String[] getSupplicantKeys() { 256e095675c872f40f630aa3f9189eb5c02f3cfee6dIrfan Sheriff return new String[] { EAP_KEY, PHASE2_KEY, IDENTITY_KEY, ANON_IDENTITY_KEY, PASSWORD_KEY, 257e095675c872f40f630aa3f9189eb5c02f3cfee6dIrfan Sheriff CLIENT_CERT_KEY, CA_CERT_KEY, SUBJECT_MATCH_KEY, ENGINE_KEY, ENGINE_ID_KEY, 258e095675c872f40f630aa3f9189eb5c02f3cfee6dIrfan Sheriff PRIVATE_KEY_ID_KEY }; 259e095675c872f40f630aa3f9189eb5c02f3cfee6dIrfan Sheriff } 260e095675c872f40f630aa3f9189eb5c02f3cfee6dIrfan Sheriff 2619b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff /** 2629b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff * Set the EAP authentication method. 2639b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff * @param eapMethod is one {@link Eap#PEAP}, {@link Eap#TLS}, {@link Eap#TTLS} or 2649b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff * {@link Eap#PWD} 265fdc028383a01eaaa9bf93cb5d3ce50bd744eab52Irfan Sheriff * @throws IllegalArgumentException on an invalid eap method 2669b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff */ 2679b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff public void setEapMethod(int eapMethod) { 2689b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff switch (eapMethod) { 2699b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff /** Valid methods */ 2709b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff case Eap.PEAP: 2719b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff case Eap.PWD: 2729b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff case Eap.TLS: 2739b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff case Eap.TTLS: 2749b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff mFields.put(EAP_KEY, Eap.strings[eapMethod]); 2759b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff break; 2769b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff default: 2779b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff throw new IllegalArgumentException("Unknown EAP method"); 2789b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff } 2799b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff } 2809b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff 2819b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff /** 2829b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff * Get the eap method. 2839b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff * @return eap method configured 2849b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff */ 2859b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff public int getEapMethod() { 2869b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff String eapMethod = mFields.get(EAP_KEY); 287e095675c872f40f630aa3f9189eb5c02f3cfee6dIrfan Sheriff return getStringIndex(Eap.strings, eapMethod, Eap.NONE); 2889b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff } 2899b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff 2909b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff /** 2919b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff * Set Phase 2 authentication method. Sets the inner authentication method to be used in 2929b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff * phase 2 after setting up a secure channel 2939b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff * @param phase2Method is the inner authentication method and can be one of {@link Phase2#NONE}, 2949b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff * {@link Phase2#PAP}, {@link Phase2#MSCHAP}, {@link Phase2#MSCHAPV2}, 2959b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff * {@link Phase2#GTC} 296fdc028383a01eaaa9bf93cb5d3ce50bd744eab52Irfan Sheriff * @throws IllegalArgumentException on an invalid phase2 method 2979b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff * 2989b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff */ 2999b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff public void setPhase2Method(int phase2Method) { 3009b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff switch (phase2Method) { 3019b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff case Phase2.NONE: 3029b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff mFields.put(PHASE2_KEY, EMPTY_VALUE); 3039b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff break; 3049b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff /** Valid methods */ 3059b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff case Phase2.PAP: 3069b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff case Phase2.MSCHAP: 3079b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff case Phase2.MSCHAPV2: 3089b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff case Phase2.GTC: 3099b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff mFields.put(PHASE2_KEY, convertToQuotedString( 3109b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff Phase2.PREFIX + Phase2.strings[phase2Method])); 3119b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff break; 3129b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff default: 3139b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff throw new IllegalArgumentException("Unknown Phase 2 method"); 3149b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff } 3159b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff } 3169b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff 3179b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff /** 3189b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff * Get the phase 2 authentication method. 3199b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff * @return a phase 2 method defined at {@link Phase2} 3209b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff * */ 3219b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff public int getPhase2Method() { 322e095675c872f40f630aa3f9189eb5c02f3cfee6dIrfan Sheriff String phase2Method = removeDoubleQuotes(mFields.get(PHASE2_KEY)); 323e095675c872f40f630aa3f9189eb5c02f3cfee6dIrfan Sheriff // Remove auth= prefix 324e095675c872f40f630aa3f9189eb5c02f3cfee6dIrfan Sheriff if (phase2Method.startsWith(Phase2.PREFIX)) { 325e095675c872f40f630aa3f9189eb5c02f3cfee6dIrfan Sheriff phase2Method = phase2Method.substring(Phase2.PREFIX.length()); 326e095675c872f40f630aa3f9189eb5c02f3cfee6dIrfan Sheriff } 3279b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff return getStringIndex(Phase2.strings, phase2Method, Phase2.NONE); 3289b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff } 3299b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff 3309b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff /** 3319b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff * Set the identity 3329b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff * @param identity 3339b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff */ 3349b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff public void setIdentity(String identity) { 3359b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff setFieldValue(IDENTITY_KEY, identity, ""); 3369b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff } 3379b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff 3389b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff /** 3399b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff * Get the identity 3409b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff * @return the identity 3419b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff */ 3429b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff public String getIdentity() { 3439b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff return getFieldValue(IDENTITY_KEY, ""); 3449b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff } 3459b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff 3469b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff /** 3479b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff * Set anonymous identity. This is used as the unencrypted identity with 3489b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff * certain EAP types 3499b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff * @param anonymousIdentity the anonymous identity 3509b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff */ 3519b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff public void setAnonymousIdentity(String anonymousIdentity) { 3529b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff setFieldValue(ANON_IDENTITY_KEY, anonymousIdentity, ""); 3539b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff } 3549b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff 3559b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff /** Get the anonymous identity 3569b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff * @return anonymous identity 3579b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff */ 3589b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff public String getAnonymousIdentity() { 3599b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff return getFieldValue(ANON_IDENTITY_KEY, ""); 3609b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff } 3619b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff 3629b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff /** 3639b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff * Set the password. 3649b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff * @param password the password 3659b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff */ 3669b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff public void setPassword(String password) { 3679b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff setFieldValue(PASSWORD_KEY, password, ""); 3689b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff } 3699b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff 3709b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff /** 3719b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff * Set CA certificate alias. 3729b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff * 3739b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff * <p> See the {@link android.security.KeyChain} for details on installing or choosing 3749b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff * a certificate 3759b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff * </p> 3769b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff * @param alias identifies the certificate 37726d0076f0dbb021c4e5cc1b37b632b2223fd9278Irfan Sheriff * @hide 3789b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff */ 37926d0076f0dbb021c4e5cc1b37b632b2223fd9278Irfan Sheriff public void setCaCertificateAlias(String alias) { 3809b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff setFieldValue(CA_CERT_KEY, alias, CA_CERT_PREFIX); 3819b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff } 3829b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff 3839b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff /** 3849b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff * Get CA certificate alias 3859b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff * @return alias to the CA certificate 38626d0076f0dbb021c4e5cc1b37b632b2223fd9278Irfan Sheriff * @hide 3879b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff */ 38826d0076f0dbb021c4e5cc1b37b632b2223fd9278Irfan Sheriff public String getCaCertificateAlias() { 3899b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff return getFieldValue(CA_CERT_KEY, CA_CERT_PREFIX); 3909b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff } 3919b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff 3929b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff /** 39326d0076f0dbb021c4e5cc1b37b632b2223fd9278Irfan Sheriff * Specify a X.509 certificate that identifies the server. 39426d0076f0dbb021c4e5cc1b37b632b2223fd9278Irfan Sheriff * 39526d0076f0dbb021c4e5cc1b37b632b2223fd9278Irfan Sheriff * <p>A default name is automatically assigned to the certificate and used 396fdc028383a01eaaa9bf93cb5d3ce50bd744eab52Irfan Sheriff * with this configuration. The framework takes care of installing the 397fdc028383a01eaaa9bf93cb5d3ce50bd744eab52Irfan Sheriff * certificate when the config is saved and removing the certificate when 398fdc028383a01eaaa9bf93cb5d3ce50bd744eab52Irfan Sheriff * the config is removed. 399fdc028383a01eaaa9bf93cb5d3ce50bd744eab52Irfan Sheriff * 40026d0076f0dbb021c4e5cc1b37b632b2223fd9278Irfan Sheriff * @param cert X.509 CA certificate 40126d0076f0dbb021c4e5cc1b37b632b2223fd9278Irfan Sheriff * @throws IllegalArgumentException if not a CA certificate 40226d0076f0dbb021c4e5cc1b37b632b2223fd9278Irfan Sheriff */ 40326d0076f0dbb021c4e5cc1b37b632b2223fd9278Irfan Sheriff public void setCaCertificate(X509Certificate cert) { 40426d0076f0dbb021c4e5cc1b37b632b2223fd9278Irfan Sheriff if (cert.getBasicConstraints() >= 0) { 40526d0076f0dbb021c4e5cc1b37b632b2223fd9278Irfan Sheriff mCaCert = cert; 40626d0076f0dbb021c4e5cc1b37b632b2223fd9278Irfan Sheriff } else { 40726d0076f0dbb021c4e5cc1b37b632b2223fd9278Irfan Sheriff throw new IllegalArgumentException("Not a CA certificate"); 40826d0076f0dbb021c4e5cc1b37b632b2223fd9278Irfan Sheriff } 40926d0076f0dbb021c4e5cc1b37b632b2223fd9278Irfan Sheriff } 41026d0076f0dbb021c4e5cc1b37b632b2223fd9278Irfan Sheriff 41126d0076f0dbb021c4e5cc1b37b632b2223fd9278Irfan Sheriff /** 4129b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff * Set Client certificate alias. 4139b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff * 4149b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff * <p> See the {@link android.security.KeyChain} for details on installing or choosing 4159b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff * a certificate 4169b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff * </p> 4179b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff * @param alias identifies the certificate 41826d0076f0dbb021c4e5cc1b37b632b2223fd9278Irfan Sheriff * @hide 4199b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff */ 42026d0076f0dbb021c4e5cc1b37b632b2223fd9278Irfan Sheriff public void setClientCertificateAlias(String alias) { 4219b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff setFieldValue(CLIENT_CERT_KEY, alias, CLIENT_CERT_PREFIX); 4229b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff setFieldValue(PRIVATE_KEY_ID_KEY, alias, Credentials.USER_PRIVATE_KEY); 4239b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff // Also, set engine parameters 4249b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff if (TextUtils.isEmpty(alias)) { 4259b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff mFields.put(ENGINE_KEY, ENGINE_DISABLE); 4269b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff mFields.put(ENGINE_ID_KEY, EMPTY_VALUE); 4279b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff } else { 4289b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff mFields.put(ENGINE_KEY, ENGINE_ENABLE); 4299b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff mFields.put(ENGINE_ID_KEY, convertToQuotedString(ENGINE_ID_KEYSTORE)); 4309b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff } 4319b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff } 4329b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff 4339b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff /** 4349b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff * Get client certificate alias 4359b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff * @return alias to the client certificate 43626d0076f0dbb021c4e5cc1b37b632b2223fd9278Irfan Sheriff * @hide 4379b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff */ 43826d0076f0dbb021c4e5cc1b37b632b2223fd9278Irfan Sheriff public String getClientCertificateAlias() { 4399b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff return getFieldValue(CLIENT_CERT_KEY, CLIENT_CERT_PREFIX); 4409b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff } 4419b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff 4429b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff /** 44326d0076f0dbb021c4e5cc1b37b632b2223fd9278Irfan Sheriff * Specify a private key and client certificate for client authorization. 44426d0076f0dbb021c4e5cc1b37b632b2223fd9278Irfan Sheriff * 44526d0076f0dbb021c4e5cc1b37b632b2223fd9278Irfan Sheriff * <p>A default name is automatically assigned to the key entry and used 446fdc028383a01eaaa9bf93cb5d3ce50bd744eab52Irfan Sheriff * with this configuration. The framework takes care of installing the 447fdc028383a01eaaa9bf93cb5d3ce50bd744eab52Irfan Sheriff * key entry when the config is saved and removing the key entry when 448fdc028383a01eaaa9bf93cb5d3ce50bd744eab52Irfan Sheriff * the config is removed. 449fdc028383a01eaaa9bf93cb5d3ce50bd744eab52Irfan Sheriff 45026d0076f0dbb021c4e5cc1b37b632b2223fd9278Irfan Sheriff * @param privateKey 45126d0076f0dbb021c4e5cc1b37b632b2223fd9278Irfan Sheriff * @param clientCertificate 452fdc028383a01eaaa9bf93cb5d3ce50bd744eab52Irfan Sheriff * @throws IllegalArgumentException for an invalid key or certificate. 45326d0076f0dbb021c4e5cc1b37b632b2223fd9278Irfan Sheriff */ 45426d0076f0dbb021c4e5cc1b37b632b2223fd9278Irfan Sheriff public void setClientKeyEntry(PrivateKey privateKey, X509Certificate clientCertificate) { 45526d0076f0dbb021c4e5cc1b37b632b2223fd9278Irfan Sheriff if (clientCertificate != null) { 45626d0076f0dbb021c4e5cc1b37b632b2223fd9278Irfan Sheriff if (clientCertificate.getBasicConstraints() != -1) { 45726d0076f0dbb021c4e5cc1b37b632b2223fd9278Irfan Sheriff throw new IllegalArgumentException("Cannot be a CA certificate"); 45826d0076f0dbb021c4e5cc1b37b632b2223fd9278Irfan Sheriff } 45926d0076f0dbb021c4e5cc1b37b632b2223fd9278Irfan Sheriff if (privateKey == null) { 46026d0076f0dbb021c4e5cc1b37b632b2223fd9278Irfan Sheriff throw new IllegalArgumentException("Client cert without a private key"); 46126d0076f0dbb021c4e5cc1b37b632b2223fd9278Irfan Sheriff } 46226d0076f0dbb021c4e5cc1b37b632b2223fd9278Irfan Sheriff if (privateKey.getEncoded() == null) { 46326d0076f0dbb021c4e5cc1b37b632b2223fd9278Irfan Sheriff throw new IllegalArgumentException("Private key cannot be encoded"); 46426d0076f0dbb021c4e5cc1b37b632b2223fd9278Irfan Sheriff } 46526d0076f0dbb021c4e5cc1b37b632b2223fd9278Irfan Sheriff } 46626d0076f0dbb021c4e5cc1b37b632b2223fd9278Irfan Sheriff 46726d0076f0dbb021c4e5cc1b37b632b2223fd9278Irfan Sheriff mClientPrivateKey = privateKey; 46826d0076f0dbb021c4e5cc1b37b632b2223fd9278Irfan Sheriff mClientCertificate = clientCertificate; 46926d0076f0dbb021c4e5cc1b37b632b2223fd9278Irfan Sheriff } 47026d0076f0dbb021c4e5cc1b37b632b2223fd9278Irfan Sheriff 47126d0076f0dbb021c4e5cc1b37b632b2223fd9278Irfan Sheriff boolean needsKeyStore() { 47226d0076f0dbb021c4e5cc1b37b632b2223fd9278Irfan Sheriff // Has no keys to be installed 47326d0076f0dbb021c4e5cc1b37b632b2223fd9278Irfan Sheriff if (mClientCertificate == null && mCaCert == null) return false; 47426d0076f0dbb021c4e5cc1b37b632b2223fd9278Irfan Sheriff return true; 47526d0076f0dbb021c4e5cc1b37b632b2223fd9278Irfan Sheriff } 47626d0076f0dbb021c4e5cc1b37b632b2223fd9278Irfan Sheriff 47726d0076f0dbb021c4e5cc1b37b632b2223fd9278Irfan Sheriff boolean installKeys(android.security.KeyStore keyStore, String name) { 47826d0076f0dbb021c4e5cc1b37b632b2223fd9278Irfan Sheriff boolean ret = true; 47926d0076f0dbb021c4e5cc1b37b632b2223fd9278Irfan Sheriff String privKeyName = Credentials.USER_PRIVATE_KEY + name; 48026d0076f0dbb021c4e5cc1b37b632b2223fd9278Irfan Sheriff String userCertName = Credentials.USER_CERTIFICATE + name; 48126d0076f0dbb021c4e5cc1b37b632b2223fd9278Irfan Sheriff String caCertName = Credentials.CA_CERTIFICATE + name; 48226d0076f0dbb021c4e5cc1b37b632b2223fd9278Irfan Sheriff if (mClientCertificate != null) { 48326d0076f0dbb021c4e5cc1b37b632b2223fd9278Irfan Sheriff byte[] privKeyData = mClientPrivateKey.getEncoded(); 4848b643c13f97c0f304a45039b9d1fe6900940499eIrfan Sheriff ret = keyStore.importKey(privKeyName, privKeyData, Process.WIFI_UID); 48526d0076f0dbb021c4e5cc1b37b632b2223fd9278Irfan Sheriff if (ret == false) { 48626d0076f0dbb021c4e5cc1b37b632b2223fd9278Irfan Sheriff return ret; 48726d0076f0dbb021c4e5cc1b37b632b2223fd9278Irfan Sheriff } 48826d0076f0dbb021c4e5cc1b37b632b2223fd9278Irfan Sheriff 48926d0076f0dbb021c4e5cc1b37b632b2223fd9278Irfan Sheriff ret = putCertInKeyStore(keyStore, userCertName, mClientCertificate); 49026d0076f0dbb021c4e5cc1b37b632b2223fd9278Irfan Sheriff if (ret == false) { 49126d0076f0dbb021c4e5cc1b37b632b2223fd9278Irfan Sheriff // Remove private key installed 4928b643c13f97c0f304a45039b9d1fe6900940499eIrfan Sheriff keyStore.delKey(privKeyName, Process.WIFI_UID); 49326d0076f0dbb021c4e5cc1b37b632b2223fd9278Irfan Sheriff return ret; 49426d0076f0dbb021c4e5cc1b37b632b2223fd9278Irfan Sheriff } 49526d0076f0dbb021c4e5cc1b37b632b2223fd9278Irfan Sheriff } 49626d0076f0dbb021c4e5cc1b37b632b2223fd9278Irfan Sheriff 49726d0076f0dbb021c4e5cc1b37b632b2223fd9278Irfan Sheriff if (mCaCert != null) { 49826d0076f0dbb021c4e5cc1b37b632b2223fd9278Irfan Sheriff ret = putCertInKeyStore(keyStore, caCertName, mCaCert); 49926d0076f0dbb021c4e5cc1b37b632b2223fd9278Irfan Sheriff if (ret == false) { 50026d0076f0dbb021c4e5cc1b37b632b2223fd9278Irfan Sheriff if (mClientCertificate != null) { 50126d0076f0dbb021c4e5cc1b37b632b2223fd9278Irfan Sheriff // Remove client key+cert 5028b643c13f97c0f304a45039b9d1fe6900940499eIrfan Sheriff keyStore.delKey(privKeyName, Process.WIFI_UID); 5038b643c13f97c0f304a45039b9d1fe6900940499eIrfan Sheriff keyStore.delete(userCertName, Process.WIFI_UID); 50426d0076f0dbb021c4e5cc1b37b632b2223fd9278Irfan Sheriff } 50526d0076f0dbb021c4e5cc1b37b632b2223fd9278Irfan Sheriff return ret; 50626d0076f0dbb021c4e5cc1b37b632b2223fd9278Irfan Sheriff } 50726d0076f0dbb021c4e5cc1b37b632b2223fd9278Irfan Sheriff } 50826d0076f0dbb021c4e5cc1b37b632b2223fd9278Irfan Sheriff 50926d0076f0dbb021c4e5cc1b37b632b2223fd9278Irfan Sheriff // Set alias names 51026d0076f0dbb021c4e5cc1b37b632b2223fd9278Irfan Sheriff if (mClientCertificate != null) { 51126d0076f0dbb021c4e5cc1b37b632b2223fd9278Irfan Sheriff setClientCertificateAlias(name); 51226d0076f0dbb021c4e5cc1b37b632b2223fd9278Irfan Sheriff mClientPrivateKey = null; 51326d0076f0dbb021c4e5cc1b37b632b2223fd9278Irfan Sheriff mClientCertificate = null; 51426d0076f0dbb021c4e5cc1b37b632b2223fd9278Irfan Sheriff } 51526d0076f0dbb021c4e5cc1b37b632b2223fd9278Irfan Sheriff 51626d0076f0dbb021c4e5cc1b37b632b2223fd9278Irfan Sheriff if (mCaCert != null) { 51726d0076f0dbb021c4e5cc1b37b632b2223fd9278Irfan Sheriff setCaCertificateAlias(name); 51826d0076f0dbb021c4e5cc1b37b632b2223fd9278Irfan Sheriff mCaCert = null; 51926d0076f0dbb021c4e5cc1b37b632b2223fd9278Irfan Sheriff } 52026d0076f0dbb021c4e5cc1b37b632b2223fd9278Irfan Sheriff 52126d0076f0dbb021c4e5cc1b37b632b2223fd9278Irfan Sheriff return ret; 52226d0076f0dbb021c4e5cc1b37b632b2223fd9278Irfan Sheriff } 52326d0076f0dbb021c4e5cc1b37b632b2223fd9278Irfan Sheriff 52426d0076f0dbb021c4e5cc1b37b632b2223fd9278Irfan Sheriff private boolean putCertInKeyStore(android.security.KeyStore keyStore, String name, 52526d0076f0dbb021c4e5cc1b37b632b2223fd9278Irfan Sheriff Certificate cert) { 52626d0076f0dbb021c4e5cc1b37b632b2223fd9278Irfan Sheriff try { 52726d0076f0dbb021c4e5cc1b37b632b2223fd9278Irfan Sheriff byte[] certData = Credentials.convertToPem(cert); 5288b643c13f97c0f304a45039b9d1fe6900940499eIrfan Sheriff return keyStore.put(name, certData, Process.WIFI_UID); 52926d0076f0dbb021c4e5cc1b37b632b2223fd9278Irfan Sheriff } catch (IOException e1) { 53026d0076f0dbb021c4e5cc1b37b632b2223fd9278Irfan Sheriff return false; 53126d0076f0dbb021c4e5cc1b37b632b2223fd9278Irfan Sheriff } catch (CertificateException e2) { 53226d0076f0dbb021c4e5cc1b37b632b2223fd9278Irfan Sheriff return false; 53326d0076f0dbb021c4e5cc1b37b632b2223fd9278Irfan Sheriff } 53426d0076f0dbb021c4e5cc1b37b632b2223fd9278Irfan Sheriff } 53526d0076f0dbb021c4e5cc1b37b632b2223fd9278Irfan Sheriff 53626d0076f0dbb021c4e5cc1b37b632b2223fd9278Irfan Sheriff void removeKeys(android.security.KeyStore keyStore) { 53726d0076f0dbb021c4e5cc1b37b632b2223fd9278Irfan Sheriff String client = getFieldValue(CLIENT_CERT_KEY, CLIENT_CERT_PREFIX); 53826d0076f0dbb021c4e5cc1b37b632b2223fd9278Irfan Sheriff // a valid client certificate is configured 53926d0076f0dbb021c4e5cc1b37b632b2223fd9278Irfan Sheriff if (!TextUtils.isEmpty(client)) { 5408b643c13f97c0f304a45039b9d1fe6900940499eIrfan Sheriff keyStore.delKey(Credentials.USER_PRIVATE_KEY + client, Process.WIFI_UID); 5418b643c13f97c0f304a45039b9d1fe6900940499eIrfan Sheriff keyStore.delete(Credentials.USER_CERTIFICATE + client, Process.WIFI_UID); 54226d0076f0dbb021c4e5cc1b37b632b2223fd9278Irfan Sheriff } 54326d0076f0dbb021c4e5cc1b37b632b2223fd9278Irfan Sheriff 54426d0076f0dbb021c4e5cc1b37b632b2223fd9278Irfan Sheriff String ca = getFieldValue(CA_CERT_KEY, CA_CERT_PREFIX); 54526d0076f0dbb021c4e5cc1b37b632b2223fd9278Irfan Sheriff // a valid ca certificate is configured 54626d0076f0dbb021c4e5cc1b37b632b2223fd9278Irfan Sheriff if (!TextUtils.isEmpty(ca)) { 5478b643c13f97c0f304a45039b9d1fe6900940499eIrfan Sheriff keyStore.delete(Credentials.CA_CERTIFICATE + ca, Process.WIFI_UID); 54826d0076f0dbb021c4e5cc1b37b632b2223fd9278Irfan Sheriff } 54926d0076f0dbb021c4e5cc1b37b632b2223fd9278Irfan Sheriff } 55026d0076f0dbb021c4e5cc1b37b632b2223fd9278Irfan Sheriff 55126d0076f0dbb021c4e5cc1b37b632b2223fd9278Irfan Sheriff /** 5529b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff * Set subject match. This is the substring to be matched against the subject of the 5539b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff * authentication server certificate. 5549b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff * @param subjectMatch substring to be matched 5559b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff */ 5569b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff public void setSubjectMatch(String subjectMatch) { 5579b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff setFieldValue(SUBJECT_MATCH_KEY, subjectMatch, ""); 5589b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff } 5599b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff 5609b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff /** 5619b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff * Get subject match 5629b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff * @return the subject match string 5639b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff */ 5649b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff public String getSubjectMatch() { 5659b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff return getFieldValue(SUBJECT_MATCH_KEY, ""); 5669b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff } 5679b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff 56826d0076f0dbb021c4e5cc1b37b632b2223fd9278Irfan Sheriff /** See {@link WifiConfiguration#getKeyIdForCredentials} @hide */ 56926d0076f0dbb021c4e5cc1b37b632b2223fd9278Irfan Sheriff String getKeyId(WifiEnterpriseConfig current) { 57026d0076f0dbb021c4e5cc1b37b632b2223fd9278Irfan Sheriff String eap = mFields.get(EAP_KEY); 57126d0076f0dbb021c4e5cc1b37b632b2223fd9278Irfan Sheriff String phase2 = mFields.get(PHASE2_KEY); 57226d0076f0dbb021c4e5cc1b37b632b2223fd9278Irfan Sheriff 57326d0076f0dbb021c4e5cc1b37b632b2223fd9278Irfan Sheriff // If either eap or phase2 are not initialized, use current config details 57426d0076f0dbb021c4e5cc1b37b632b2223fd9278Irfan Sheriff if (TextUtils.isEmpty((eap))) { 57526d0076f0dbb021c4e5cc1b37b632b2223fd9278Irfan Sheriff eap = current.mFields.get(EAP_KEY); 57626d0076f0dbb021c4e5cc1b37b632b2223fd9278Irfan Sheriff } 57726d0076f0dbb021c4e5cc1b37b632b2223fd9278Irfan Sheriff if (TextUtils.isEmpty(phase2)) { 57826d0076f0dbb021c4e5cc1b37b632b2223fd9278Irfan Sheriff phase2 = current.mFields.get(PHASE2_KEY); 57926d0076f0dbb021c4e5cc1b37b632b2223fd9278Irfan Sheriff } 58026d0076f0dbb021c4e5cc1b37b632b2223fd9278Irfan Sheriff return eap + "_" + phase2; 58126d0076f0dbb021c4e5cc1b37b632b2223fd9278Irfan Sheriff } 58226d0076f0dbb021c4e5cc1b37b632b2223fd9278Irfan Sheriff 5839b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff /** Migrates the old style TLS config to the new config style. This should only be used 5849b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff * when restoring an old wpa_supplicant.conf or upgrading from a previous 5859b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff * platform version. 5869b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff * @return true if the config was updated 5879b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff * @hide 5889b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff */ 58926d0076f0dbb021c4e5cc1b37b632b2223fd9278Irfan Sheriff boolean migrateOldEapTlsNative(WifiNative wifiNative, int netId) { 5909b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff String oldPrivateKey = wifiNative.getNetworkVariable(netId, OLD_PRIVATE_KEY_NAME); 5919b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff /* 5929b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff * If the old configuration value is not present, then there is nothing 5939b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff * to do. 5949b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff */ 5959b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff if (TextUtils.isEmpty(oldPrivateKey)) { 5969b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff return false; 5979b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff } else { 5989b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff // Also ignore it if it's empty quotes. 5999b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff oldPrivateKey = removeDoubleQuotes(oldPrivateKey); 6009b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff if (TextUtils.isEmpty(oldPrivateKey)) { 6019b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff return false; 6029b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff } 6039b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff } 6049b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff 6059b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff mFields.put(ENGINE_KEY, ENGINE_ENABLE); 6069b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff mFields.put(ENGINE_ID_KEY, convertToQuotedString(ENGINE_ID_KEYSTORE)); 6079b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff 6089b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff /* 6099b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff * The old key started with the keystore:// URI prefix, but we don't 6109b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff * need that anymore. Trim it off if it exists. 6119b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff */ 6129b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff final String keyName; 6139b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff if (oldPrivateKey.startsWith(KEYSTORE_URI)) { 6149b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff keyName = new String(oldPrivateKey.substring(KEYSTORE_URI.length())); 6159b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff } else { 6169b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff keyName = oldPrivateKey; 6179b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff } 6189b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff mFields.put(PRIVATE_KEY_ID_KEY, convertToQuotedString(keyName)); 6199b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff 6209b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff wifiNative.setNetworkVariable(netId, ENGINE_KEY, mFields.get(ENGINE_KEY)); 6219b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff wifiNative.setNetworkVariable(netId, ENGINE_ID_KEY, mFields.get(ENGINE_ID_KEY)); 6229b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff wifiNative.setNetworkVariable(netId, PRIVATE_KEY_ID_KEY, mFields.get(PRIVATE_KEY_ID_KEY)); 6239b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff // Remove old private_key string so we don't run this again. 6249b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff wifiNative.setNetworkVariable(netId, OLD_PRIVATE_KEY_NAME, EMPTY_VALUE); 6259b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff return true; 6269b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff } 6279b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff 6288b643c13f97c0f304a45039b9d1fe6900940499eIrfan Sheriff /** Migrate certs from global pool to wifi UID if not already done */ 6298b643c13f97c0f304a45039b9d1fe6900940499eIrfan Sheriff void migrateCerts(android.security.KeyStore keyStore) { 6308b643c13f97c0f304a45039b9d1fe6900940499eIrfan Sheriff String client = getFieldValue(CLIENT_CERT_KEY, CLIENT_CERT_PREFIX); 6318b643c13f97c0f304a45039b9d1fe6900940499eIrfan Sheriff // a valid client certificate is configured 6328b643c13f97c0f304a45039b9d1fe6900940499eIrfan Sheriff if (!TextUtils.isEmpty(client)) { 6338b643c13f97c0f304a45039b9d1fe6900940499eIrfan Sheriff if (!keyStore.contains(Credentials.USER_PRIVATE_KEY + client, Process.WIFI_UID)) { 6348b643c13f97c0f304a45039b9d1fe6900940499eIrfan Sheriff keyStore.duplicate(Credentials.USER_PRIVATE_KEY + client, -1, 6358b643c13f97c0f304a45039b9d1fe6900940499eIrfan Sheriff Credentials.USER_PRIVATE_KEY + client, Process.WIFI_UID); 6368b643c13f97c0f304a45039b9d1fe6900940499eIrfan Sheriff keyStore.duplicate(Credentials.USER_CERTIFICATE + client, -1, 6378b643c13f97c0f304a45039b9d1fe6900940499eIrfan Sheriff Credentials.USER_CERTIFICATE + client, Process.WIFI_UID); 6388b643c13f97c0f304a45039b9d1fe6900940499eIrfan Sheriff } 6398b643c13f97c0f304a45039b9d1fe6900940499eIrfan Sheriff } 6408b643c13f97c0f304a45039b9d1fe6900940499eIrfan Sheriff 6418b643c13f97c0f304a45039b9d1fe6900940499eIrfan Sheriff String ca = getFieldValue(CA_CERT_KEY, CA_CERT_PREFIX); 6428b643c13f97c0f304a45039b9d1fe6900940499eIrfan Sheriff // a valid ca certificate is configured 6438b643c13f97c0f304a45039b9d1fe6900940499eIrfan Sheriff if (!TextUtils.isEmpty(ca)) { 6448b643c13f97c0f304a45039b9d1fe6900940499eIrfan Sheriff if (!keyStore.contains(Credentials.CA_CERTIFICATE + ca, Process.WIFI_UID)) { 6458b643c13f97c0f304a45039b9d1fe6900940499eIrfan Sheriff keyStore.duplicate(Credentials.CA_CERTIFICATE + ca, -1, 6468b643c13f97c0f304a45039b9d1fe6900940499eIrfan Sheriff Credentials.CA_CERTIFICATE + ca, Process.WIFI_UID); 6478b643c13f97c0f304a45039b9d1fe6900940499eIrfan Sheriff } 6488b643c13f97c0f304a45039b9d1fe6900940499eIrfan Sheriff } 6498b643c13f97c0f304a45039b9d1fe6900940499eIrfan Sheriff } 6508b643c13f97c0f304a45039b9d1fe6900940499eIrfan Sheriff 6519b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff private String removeDoubleQuotes(String string) { 6529b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff int length = string.length(); 6539b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff if ((length > 1) && (string.charAt(0) == '"') 6549b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff && (string.charAt(length - 1) == '"')) { 6559b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff return string.substring(1, length - 1); 6569b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff } 6579b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff return string; 6589b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff } 6599b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff 6609b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff private String convertToQuotedString(String string) { 6619b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff return "\"" + string + "\""; 6629b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff } 6639b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff 6649b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff /** Returns the index at which the toBeFound string is found in the array. 6659b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff * @param arr array of strings 6669b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff * @param toBeFound string to be found 6679b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff * @param defaultIndex default index to be returned when string is not found 6689b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff * @return the index into array 6699b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff */ 6709b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff private int getStringIndex(String arr[], String toBeFound, int defaultIndex) { 67126d0076f0dbb021c4e5cc1b37b632b2223fd9278Irfan Sheriff if (TextUtils.isEmpty(toBeFound)) return defaultIndex; 6729b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff for (int i = 0; i < arr.length; i++) { 673e095675c872f40f630aa3f9189eb5c02f3cfee6dIrfan Sheriff if (toBeFound.equals(arr[i])) return i; 6749b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff } 6759b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff return defaultIndex; 6769b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff } 6779b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff 6789b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff /** Returns the field value for the key. 6799b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff * @param key into the hash 6809b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff * @param prefix is the prefix that the value may have 6819b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff * @return value 6829b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff */ 6839b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff private String getFieldValue(String key, String prefix) { 6849b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff String value = mFields.get(key); 68526d0076f0dbb021c4e5cc1b37b632b2223fd9278Irfan Sheriff // Uninitialized or known to be empty after reading from supplicant 68626d0076f0dbb021c4e5cc1b37b632b2223fd9278Irfan Sheriff if (TextUtils.isEmpty(value) || EMPTY_VALUE.equals(value)) return ""; 6879b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff return removeDoubleQuotes(value).substring(prefix.length()); 6889b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff } 6899b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff 6909b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff /** Set a value with an optional prefix at key 6919b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff * @param key into the hash 6929b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff * @param value to be set 6939b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff * @param prefix an optional value to be prefixed to actual value 6949b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff */ 6959b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff private void setFieldValue(String key, String value, String prefix) { 6969b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff if (TextUtils.isEmpty(value)) { 6979b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff mFields.put(key, EMPTY_VALUE); 6989b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff } else { 6999b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff mFields.put(key, convertToQuotedString(prefix + value)); 7009b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff } 7019b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff } 7029b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff 7039b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff @Override 7049b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff public String toString() { 7059b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff StringBuffer sb = new StringBuffer(); 7069b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff for (String key : mFields.keySet()) { 7079b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff sb.append(key).append(" ").append(mFields.get(key)).append("\n"); 7089b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff } 7099b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff return sb.toString(); 7109b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff } 7119b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff} 712