Support converting EAP-TTLS to/from PersistableBundle

Bug: 163604823
Test: FrameworksVcnTests(add new tests)
Change-Id: I1e338d9c8940636b38f4725787de30fbbc1323ec
This commit is contained in:
Yan Yan
2021-02-23 16:40:18 -08:00
parent 3344f916bd
commit a3d6e04d27
4 changed files with 152 additions and 3 deletions

View File

@@ -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);
}
}
}

View File

@@ -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);
}
}
}

View 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-----

View File

@@ -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);
}
}