Support converting EAP-TTLS to/from PersistableBundle
Bug: 163604823 Test: FrameworksVcnTests(add new tests) Change-Id: I1e338d9c8940636b38f4725787de30fbbc1323ec
This commit is contained in:
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
* Copyright (C) 2021 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package android.net.vcn.persistablebundleutils;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.InputStream;
|
||||
import java.security.cert.CertificateException;
|
||||
import java.security.cert.CertificateFactory;
|
||||
import java.security.cert.X509Certificate;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* CertUtils provides utility methods for constructing Certificate.
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
public class CertUtils {
|
||||
private static final String CERT_TYPE_X509 = "X.509";
|
||||
|
||||
/** Decodes an ASN.1 DER encoded Certificate */
|
||||
public static X509Certificate certificateFromByteArray(byte[] derEncoded) {
|
||||
Objects.requireNonNull(derEncoded, "derEncoded is null");
|
||||
|
||||
try {
|
||||
CertificateFactory certFactory = CertificateFactory.getInstance(CERT_TYPE_X509);
|
||||
InputStream in = new ByteArrayInputStream(derEncoded);
|
||||
return (X509Certificate) certFactory.generateCertificate(in);
|
||||
} catch (CertificateException e) {
|
||||
throw new IllegalArgumentException("Fail to decode certificate", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -26,12 +26,15 @@ import android.net.eap.EapSessionConfig.EapAkaPrimeConfig;
|
||||
import android.net.eap.EapSessionConfig.EapMethodConfig;
|
||||
import android.net.eap.EapSessionConfig.EapMsChapV2Config;
|
||||
import android.net.eap.EapSessionConfig.EapSimConfig;
|
||||
import android.net.eap.EapSessionConfig.EapTtlsConfig;
|
||||
import android.net.eap.EapSessionConfig.EapUiccConfig;
|
||||
import android.os.PersistableBundle;
|
||||
|
||||
import com.android.internal.annotations.VisibleForTesting;
|
||||
import com.android.server.vcn.util.PersistableBundleUtils;
|
||||
|
||||
import java.security.cert.CertificateEncodingException;
|
||||
import java.security.cert.X509Certificate;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
@@ -43,6 +46,7 @@ import java.util.Objects;
|
||||
public final class EapSessionConfigUtils {
|
||||
private static final String EAP_ID_KEY = "EAP_ID_KEY";
|
||||
private static final String EAP_SIM_CONFIG_KEY = "EAP_SIM_CONFIG_KEY";
|
||||
private static final String EAP_TTLS_CONFIG_KEY = "EAP_TTLS_CONFIG_KEY";
|
||||
private static final String EAP_AKA_CONFIG_KEY = "EAP_AKA_CONFIG_KEY";
|
||||
private static final String EAP_MSCHAP_V2_CONFIG_KEY = "EAP_MSCHAP_V2_CONFIG_KEY";
|
||||
private static final String EAP_AKA_PRIME_CONFIG_KEY = "EAP_AKA_PRIME_CONFIG_KEY";
|
||||
@@ -61,6 +65,12 @@ public final class EapSessionConfigUtils {
|
||||
EapSimConfigUtils.toPersistableBundle(config.getEapSimConfig()));
|
||||
}
|
||||
|
||||
if (config.getEapTtlsConfig() != null) {
|
||||
result.putPersistableBundle(
|
||||
EAP_TTLS_CONFIG_KEY,
|
||||
EapTtlsConfigUtils.toPersistableBundle(config.getEapTtlsConfig()));
|
||||
}
|
||||
|
||||
if (config.getEapAkaConfig() != null) {
|
||||
result.putPersistableBundle(
|
||||
EAP_AKA_CONFIG_KEY,
|
||||
@@ -79,8 +89,6 @@ public final class EapSessionConfigUtils {
|
||||
EapAkaPrimeConfigUtils.toPersistableBundle(config.getEapAkaPrimeConfig()));
|
||||
}
|
||||
|
||||
// TODO: Handle EAP-TTLS.
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -100,6 +108,11 @@ public final class EapSessionConfigUtils {
|
||||
EapSimConfigUtils.setBuilderByReadingPersistableBundle(simBundle, builder);
|
||||
}
|
||||
|
||||
final PersistableBundle ttlsBundle = in.getPersistableBundle(EAP_TTLS_CONFIG_KEY);
|
||||
if (ttlsBundle != null) {
|
||||
EapTtlsConfigUtils.setBuilderByReadingPersistableBundle(ttlsBundle, builder);
|
||||
}
|
||||
|
||||
final PersistableBundle akaBundle = in.getPersistableBundle(EAP_AKA_CONFIG_KEY);
|
||||
if (akaBundle != null) {
|
||||
EapAkaConfigUtils.setBuilderByReadingPersistableBundle(akaBundle, builder);
|
||||
@@ -115,7 +128,6 @@ public final class EapSessionConfigUtils {
|
||||
EapAkaPrimeConfigUtils.setBuilderByReadingPersistableBundle(akaPrimeBundle, builder);
|
||||
}
|
||||
|
||||
// TODO: Handle EAP-TTLS.
|
||||
return builder.build();
|
||||
}
|
||||
|
||||
@@ -214,4 +226,51 @@ public final class EapSessionConfigUtils {
|
||||
builder.setEapMsChapV2Config(in.getString(USERNAME_KEY), in.getString(PASSWORD_KEY));
|
||||
}
|
||||
}
|
||||
|
||||
private static final class EapTtlsConfigUtils extends EapMethodConfigUtils {
|
||||
private static final String TRUST_CERT_KEY = "TRUST_CERT_KEY";
|
||||
private static final String EAP_SESSION_CONFIG_KEY = "EAP_SESSION_CONFIG_KEY";
|
||||
|
||||
@NonNull
|
||||
public static PersistableBundle toPersistableBundle(@NonNull EapTtlsConfig config) {
|
||||
final PersistableBundle result = EapMethodConfigUtils.toPersistableBundle(config);
|
||||
try {
|
||||
if (config.getServerCaCert() != null) {
|
||||
final PersistableBundle caBundle =
|
||||
PersistableBundleUtils.fromByteArray(
|
||||
config.getServerCaCert().getEncoded());
|
||||
result.putPersistableBundle(TRUST_CERT_KEY, caBundle);
|
||||
}
|
||||
} catch (CertificateEncodingException e) {
|
||||
throw new IllegalStateException("Fail to encode the certificate");
|
||||
}
|
||||
|
||||
result.putPersistableBundle(
|
||||
EAP_SESSION_CONFIG_KEY,
|
||||
EapSessionConfigUtils.toPersistableBundle(config.getInnerEapSessionConfig()));
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public static void setBuilderByReadingPersistableBundle(
|
||||
@NonNull PersistableBundle in, @NonNull EapSessionConfig.Builder builder) {
|
||||
Objects.requireNonNull(in, "PersistableBundle was null");
|
||||
|
||||
final PersistableBundle caBundle = in.getPersistableBundle(TRUST_CERT_KEY);
|
||||
X509Certificate caCert = null;
|
||||
if (caBundle != null) {
|
||||
caCert =
|
||||
CertUtils.certificateFromByteArray(
|
||||
PersistableBundleUtils.toByteArray(caBundle));
|
||||
}
|
||||
|
||||
final PersistableBundle eapSessionConfigBundle =
|
||||
in.getPersistableBundle(EAP_SESSION_CONFIG_KEY);
|
||||
Objects.requireNonNull(eapSessionConfigBundle, "Inner EAP Session Config was null");
|
||||
final EapSessionConfig eapSessionConfig =
|
||||
EapSessionConfigUtils.fromPersistableBundle(eapSessionConfigBundle);
|
||||
|
||||
builder.setEapTtlsConfig(caCert, eapSessionConfig);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
20
tests/vcn/assets/self-signed-ca.pem
Normal file
20
tests/vcn/assets/self-signed-ca.pem
Normal file
@@ -0,0 +1,20 @@
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIIDPjCCAiagAwIBAgIICrKLpR7LxlowDQYJKoZIhvcNAQELBQAwPTELMAkGA1UE
|
||||
BhMCVVMxEDAOBgNVBAoTB0FuZHJvaWQxHDAaBgNVBAMTE2NhLnRlc3QuYW5kcm9p
|
||||
ZC5uZXQwHhcNMTkwNzE2MTcxNTUyWhcNMjkwNzEzMTcxNTUyWjA9MQswCQYDVQQG
|
||||
EwJVUzEQMA4GA1UEChMHQW5kcm9pZDEcMBoGA1UEAxMTY2EudGVzdC5hbmRyb2lk
|
||||
Lm5ldDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBANsvTwad2Nie0VOy
|
||||
Xb1VtHL0R760Jm4vr14JWMcX4oiE6jUdTNdXQ0CGb65wvulP2aEeukFH0D/cvBMR
|
||||
Bv9+haEwo9/grIXg9ALNKp+GfuZYw/dfnUMHFn3g2+SUgP6BoMZc4lkHktjkDKxp
|
||||
99Q6h4NP/ip1labkhBeB9+Z6l78LTixKRKspNITWASJed9bjzshYxKHi6dJy3maQ
|
||||
1LwYKmK7PEGRpoDoT8yZhFbxsVDUojGnJKH1RLXVOn/psG6dI/+IsbTipAttj5zc
|
||||
g2VAD56PZG2Jd+vsup+g4Dy72hyy242x5c/H2LKZn4X0B0B+IXyii/ZVc+DJldQ5
|
||||
JqplOL8CAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYw
|
||||
HQYDVR0OBBYEFGYUzuvZUaVJl8mcxejuFiUNGcTfMA0GCSqGSIb3DQEBCwUAA4IB
|
||||
AQDQYeqjvHsK2ZqSqxakDp0nu36Plbj48Wvx1ru7GW2faz7i0w/Zkxh06zniILCb
|
||||
QJRjDebSTHc5SSbCFrRTvqagaLDhbH42/hQncWqIoJqW+pmznJET4JiBO0sqzm05
|
||||
yQWsLI/h9Ir28Y2g5N+XPBU0VVVejQqH4iI0iwQx7y7ABssQ0Xa/K73VPbeGaKd6
|
||||
Prt4wjJvTlIL2yE2+0MggJ3F2rNptL5SDpg3g+4/YQ6wVRBFil95kUqplEsCtU4P
|
||||
t+8RghiEmsRx/8CywKfZ5Hex87ODhsSDmDApcefbd5gxoWVkqxZUkPcKwYv1ucm8
|
||||
u4r44fj4/9W0Zeooav5Yoh1q
|
||||
-----END CERTIFICATE-----
|
||||
@@ -23,13 +23,17 @@ import static org.junit.Assert.assertEquals;
|
||||
import android.net.eap.EapSessionConfig;
|
||||
import android.os.PersistableBundle;
|
||||
|
||||
import androidx.test.InstrumentationRegistry;
|
||||
import androidx.test.filters.SmallTest;
|
||||
import androidx.test.runner.AndroidJUnit4;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.security.cert.CertificateFactory;
|
||||
import java.security.cert.X509Certificate;
|
||||
|
||||
@RunWith(AndroidJUnit4.class)
|
||||
@SmallTest
|
||||
@@ -86,4 +90,24 @@ public class EapSessionConfigUtilsTest {
|
||||
|
||||
verifyPersistableBundleEncodeDecodeIsLossless(config);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSetEapTtlsEncodeDecodeIsLossless() throws Exception {
|
||||
final InputStream inputStream =
|
||||
InstrumentationRegistry.getContext()
|
||||
.getResources()
|
||||
.getAssets()
|
||||
.open("self-signed-ca.pem");
|
||||
final CertificateFactory factory = CertificateFactory.getInstance("X.509");
|
||||
final X509Certificate trustedCa =
|
||||
(X509Certificate) factory.generateCertificate(inputStream);
|
||||
|
||||
final EapSessionConfig innerConfig =
|
||||
new EapSessionConfig.Builder().setEapMsChapV2Config(USERNAME, PASSWORD).build();
|
||||
|
||||
final EapSessionConfig config =
|
||||
new EapSessionConfig.Builder().setEapTtlsConfig(trustedCa, innerConfig).build();
|
||||
|
||||
verifyPersistableBundleEncodeDecodeIsLossless(config);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user