Merge "API to set multiple CA certificates for WifiEnterpriseConfig" into mm-wireless-dev
This commit is contained in:
@@ -19218,6 +19218,7 @@ package android.net.wifi {
|
||||
method public java.lang.String getAltSubjectMatch();
|
||||
method public java.lang.String getAnonymousIdentity();
|
||||
method public java.security.cert.X509Certificate getCaCertificate();
|
||||
method public java.security.cert.X509Certificate[] getCaCertificates();
|
||||
method public java.security.cert.X509Certificate getClientCertificate();
|
||||
method public java.lang.String getDomainSuffixMatch();
|
||||
method public int getEapMethod();
|
||||
@@ -19230,6 +19231,7 @@ package android.net.wifi {
|
||||
method public void setAltSubjectMatch(java.lang.String);
|
||||
method public void setAnonymousIdentity(java.lang.String);
|
||||
method public void setCaCertificate(java.security.cert.X509Certificate);
|
||||
method public void setCaCertificates(java.security.cert.X509Certificate[]);
|
||||
method public void setClientKeyEntry(java.security.PrivateKey, java.security.cert.X509Certificate);
|
||||
method public void setDomainSuffixMatch(java.lang.String);
|
||||
method public void setEapMethod(int);
|
||||
|
||||
@@ -20994,6 +20994,7 @@ package android.net.wifi {
|
||||
method public java.lang.String getAltSubjectMatch();
|
||||
method public java.lang.String getAnonymousIdentity();
|
||||
method public java.security.cert.X509Certificate getCaCertificate();
|
||||
method public java.security.cert.X509Certificate[] getCaCertificates();
|
||||
method public java.security.cert.X509Certificate getClientCertificate();
|
||||
method public java.lang.String getDomainSuffixMatch();
|
||||
method public int getEapMethod();
|
||||
@@ -21006,6 +21007,7 @@ package android.net.wifi {
|
||||
method public void setAltSubjectMatch(java.lang.String);
|
||||
method public void setAnonymousIdentity(java.lang.String);
|
||||
method public void setCaCertificate(java.security.cert.X509Certificate);
|
||||
method public void setCaCertificates(java.security.cert.X509Certificate[]);
|
||||
method public void setClientKeyEntry(java.security.PrivateKey, java.security.cert.X509Certificate);
|
||||
method public void setDomainSuffixMatch(java.lang.String);
|
||||
method public void setEapMethod(int);
|
||||
|
||||
@@ -15,12 +15,14 @@
|
||||
*/
|
||||
package android.net.wifi;
|
||||
|
||||
import android.annotation.Nullable;
|
||||
import android.os.Parcel;
|
||||
import android.os.Parcelable;
|
||||
import android.security.Credentials;
|
||||
import android.text.TextUtils;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.security.KeyFactory;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.security.PrivateKey;
|
||||
@@ -71,6 +73,13 @@ public class WifiEnterpriseConfig implements Parcelable {
|
||||
*/
|
||||
public static final String KEYSTORE_URI = "keystore://";
|
||||
|
||||
/**
|
||||
* String representing the keystore URI used for wpa_supplicant,
|
||||
* Unlike #KEYSTORE_URI, this supports a list of space-delimited aliases
|
||||
* @hide
|
||||
*/
|
||||
public static final String KEYSTORES_URI = "keystores://";
|
||||
|
||||
/**
|
||||
* String to set the engine value to when it should be enabled.
|
||||
* @hide
|
||||
@@ -103,6 +112,8 @@ public class WifiEnterpriseConfig implements Parcelable {
|
||||
public static final String PLMN_KEY = "plmn";
|
||||
/** @hide */
|
||||
public static final String PHASE1_KEY = "phase1";
|
||||
/** @hide */
|
||||
public static final String CA_CERT_ALIAS_DELIMITER = " ";
|
||||
|
||||
/** {@hide} */
|
||||
public static final String ENABLE_TLS_1_2 = "\"tls_disable_tlsv1_2=0\"";
|
||||
@@ -113,7 +124,7 @@ public class WifiEnterpriseConfig implements Parcelable {
|
||||
//By default, we enable TLS1.2. However, due to a known bug on some radius, we may disable it to
|
||||
// fall back to TLS 1.1.
|
||||
private boolean mTls12Enable = true;
|
||||
private X509Certificate mCaCert;
|
||||
private X509Certificate[] mCaCerts;
|
||||
private PrivateKey mClientPrivateKey;
|
||||
private X509Certificate mClientCertificate;
|
||||
|
||||
@@ -145,7 +156,7 @@ public class WifiEnterpriseConfig implements Parcelable {
|
||||
dest.writeString(entry.getValue());
|
||||
}
|
||||
|
||||
writeCertificate(dest, mCaCert);
|
||||
writeCertificates(dest, mCaCerts);
|
||||
|
||||
if (mClientPrivateKey != null) {
|
||||
String algorithm = mClientPrivateKey.getAlgorithm();
|
||||
@@ -161,6 +172,17 @@ public class WifiEnterpriseConfig implements Parcelable {
|
||||
dest.writeInt(mTls12Enable ? 1: 0);
|
||||
}
|
||||
|
||||
private void writeCertificates(Parcel dest, X509Certificate[] cert) {
|
||||
if (cert != null && cert.length != 0) {
|
||||
dest.writeInt(cert.length);
|
||||
for (int i = 0; i < cert.length; i++) {
|
||||
writeCertificate(dest, cert[i]);
|
||||
}
|
||||
} else {
|
||||
dest.writeInt(0);
|
||||
}
|
||||
}
|
||||
|
||||
private void writeCertificate(Parcel dest, X509Certificate cert) {
|
||||
if (cert != null) {
|
||||
try {
|
||||
@@ -186,7 +208,7 @@ public class WifiEnterpriseConfig implements Parcelable {
|
||||
enterpriseConfig.mFields.put(key, value);
|
||||
}
|
||||
|
||||
enterpriseConfig.mCaCert = readCertificate(in);
|
||||
enterpriseConfig.mCaCerts = readCertificates(in);
|
||||
|
||||
PrivateKey userKey = null;
|
||||
int len = in.readInt();
|
||||
@@ -210,6 +232,18 @@ public class WifiEnterpriseConfig implements Parcelable {
|
||||
return enterpriseConfig;
|
||||
}
|
||||
|
||||
private X509Certificate[] readCertificates(Parcel in) {
|
||||
X509Certificate[] certs = null;
|
||||
int len = in.readInt();
|
||||
if (len > 0) {
|
||||
certs = new X509Certificate[len];
|
||||
for (int i = 0; i < len; i++) {
|
||||
certs[i] = readCertificate(in);
|
||||
}
|
||||
}
|
||||
return certs;
|
||||
}
|
||||
|
||||
private X509Certificate readCertificate(Parcel in) {
|
||||
X509Certificate cert = null;
|
||||
int len = in.readInt();
|
||||
@@ -429,6 +463,36 @@ public class WifiEnterpriseConfig implements Parcelable {
|
||||
return getFieldValue(PASSWORD_KEY, "");
|
||||
}
|
||||
|
||||
/**
|
||||
* Encode a CA certificate alias so it does not contain illegal character.
|
||||
* @hide
|
||||
*/
|
||||
public static String encodeCaCertificateAlias(String alias) {
|
||||
byte[] bytes = alias.getBytes(StandardCharsets.UTF_8);
|
||||
StringBuilder sb = new StringBuilder(bytes.length * 2);
|
||||
for (byte o : bytes) {
|
||||
sb.append(String.format("%02x", o & 0xFF));
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Decode a previously-encoded CA certificate alias.
|
||||
* @hide
|
||||
*/
|
||||
public static String decodeCaCertificateAlias(String alias) {
|
||||
byte[] data = new byte[alias.length() >> 1];
|
||||
for (int n = 0, position = 0; n < alias.length(); n += 2, position++) {
|
||||
data[position] = (byte) Integer.parseInt(alias.substring(n, n + 2), 16);
|
||||
}
|
||||
try {
|
||||
return new String(data, StandardCharsets.UTF_8);
|
||||
} catch (NumberFormatException e) {
|
||||
e.printStackTrace();
|
||||
return alias;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set CA certificate alias.
|
||||
*
|
||||
@@ -442,6 +506,35 @@ public class WifiEnterpriseConfig implements Parcelable {
|
||||
setFieldValue(CA_CERT_KEY, alias, CA_CERT_PREFIX);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set CA certificate aliases. When creating installing the corresponding certificate to
|
||||
* the keystore, please use alias encoded by {@link #encodeCaCertificateAlias(String)}.
|
||||
*
|
||||
* <p> See the {@link android.security.KeyChain} for details on installing or choosing
|
||||
* a certificate.
|
||||
* </p>
|
||||
* @param aliases identifies the certificate
|
||||
* @hide
|
||||
*/
|
||||
public void setCaCertificateAliases(@Nullable String[] aliases) {
|
||||
if (aliases == null) {
|
||||
setFieldValue(CA_CERT_KEY, null, CA_CERT_PREFIX);
|
||||
} else if (aliases.length == 1) {
|
||||
// Backwards compatibility: use the original cert prefix if setting only one alias.
|
||||
setCaCertificateAlias(aliases[0]);
|
||||
} else {
|
||||
// Use KEYSTORES_URI which supports multiple aliases.
|
||||
StringBuilder sb = new StringBuilder();
|
||||
for (int i = 0; i < aliases.length; i++) {
|
||||
if (i > 0) {
|
||||
sb.append(CA_CERT_ALIAS_DELIMITER);
|
||||
}
|
||||
sb.append(encodeCaCertificateAlias(Credentials.CA_CERTIFICATE + aliases[i]));
|
||||
}
|
||||
setFieldValue(CA_CERT_KEY, sb.toString(), KEYSTORES_URI);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get CA certificate alias
|
||||
* @return alias to the CA certificate
|
||||
@@ -451,6 +544,32 @@ public class WifiEnterpriseConfig implements Parcelable {
|
||||
return getFieldValue(CA_CERT_KEY, CA_CERT_PREFIX);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get CA certificate aliases
|
||||
* @return alias to the CA certificate
|
||||
* @hide
|
||||
*/
|
||||
@Nullable public String[] getCaCertificateAliases() {
|
||||
String value = getFieldValue(CA_CERT_KEY, "");
|
||||
if (value.startsWith(CA_CERT_PREFIX)) {
|
||||
// Backwards compatibility: parse the original alias prefix.
|
||||
return new String[] {getFieldValue(CA_CERT_KEY, CA_CERT_PREFIX)};
|
||||
} else if (value.startsWith(KEYSTORES_URI)) {
|
||||
String values = value.substring(KEYSTORES_URI.length());
|
||||
|
||||
String[] aliases = TextUtils.split(values, CA_CERT_ALIAS_DELIMITER);
|
||||
for (int i = 0; i < aliases.length; i++) {
|
||||
aliases[i] = decodeCaCertificateAlias(aliases[i]);
|
||||
if (aliases[i].startsWith(Credentials.CA_CERTIFICATE)) {
|
||||
aliases[i] = aliases[i].substring(Credentials.CA_CERTIFICATE.length());
|
||||
}
|
||||
}
|
||||
return aliases.length != 0 ? aliases : null;
|
||||
} else {
|
||||
return TextUtils.isEmpty(value) ? null : new String[] {value};
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Specify a X.509 certificate that identifies the server.
|
||||
*
|
||||
@@ -462,31 +581,76 @@ public class WifiEnterpriseConfig implements Parcelable {
|
||||
* @param cert X.509 CA certificate
|
||||
* @throws IllegalArgumentException if not a CA certificate
|
||||
*/
|
||||
public void setCaCertificate(X509Certificate cert) {
|
||||
public void setCaCertificate(@Nullable X509Certificate cert) {
|
||||
if (cert != null) {
|
||||
if (cert.getBasicConstraints() >= 0) {
|
||||
mCaCert = cert;
|
||||
mCaCerts = new X509Certificate[] {cert};
|
||||
} else {
|
||||
throw new IllegalArgumentException("Not a CA certificate");
|
||||
}
|
||||
} else {
|
||||
mCaCert = null;
|
||||
mCaCerts = null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get CA certificate
|
||||
* Get CA certificate. If multiple CA certificates are configured previously,
|
||||
* return the first one.
|
||||
* @return X.509 CA certificate
|
||||
*/
|
||||
public X509Certificate getCaCertificate() {
|
||||
return mCaCert;
|
||||
@Nullable public X509Certificate getCaCertificate() {
|
||||
if (mCaCerts != null && mCaCerts.length > 0) {
|
||||
return mCaCerts[0];
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Specify a list of X.509 certificates that identifies the server. The validation
|
||||
* passes if the CA of server certificate matches one of the given certificates.
|
||||
|
||||
* <p>Default names are automatically assigned to the certificates and used
|
||||
* with this configuration. The framework takes care of installing the
|
||||
* certificates when the config is saved and removing the certificates when
|
||||
* the config is removed.
|
||||
*
|
||||
* @param certs X.509 CA certificates
|
||||
* @throws IllegalArgumentException if any of the provided certificates is
|
||||
* not a CA certificate
|
||||
*/
|
||||
public void setCaCertificates(@Nullable X509Certificate[] certs) {
|
||||
if (certs != null) {
|
||||
X509Certificate[] newCerts = new X509Certificate[certs.length];
|
||||
for (int i = 0; i < certs.length; i++) {
|
||||
if (certs[i].getBasicConstraints() >= 0) {
|
||||
newCerts[i] = certs[i];
|
||||
} else {
|
||||
throw new IllegalArgumentException("Not a CA certificate");
|
||||
}
|
||||
}
|
||||
mCaCerts = newCerts;
|
||||
} else {
|
||||
mCaCerts = null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get CA certificates.
|
||||
*/
|
||||
@Nullable public X509Certificate[] getCaCertificates() {
|
||||
if (mCaCerts != null || mCaCerts.length > 0) {
|
||||
return mCaCerts;
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @hide
|
||||
*/
|
||||
public void resetCaCertificate() {
|
||||
mCaCert = null;
|
||||
mCaCerts = null;
|
||||
}
|
||||
|
||||
/** Set Client certificate alias.
|
||||
|
||||
Reference in New Issue
Block a user