diff --git a/core/java/android/net/vcn/persistablebundleutils/IkeSessionParamsUtils.java b/core/java/android/net/vcn/persistablebundleutils/IkeSessionParamsUtils.java index 6f957c55b5dc2..7f0c3280ea373 100644 --- a/core/java/android/net/vcn/persistablebundleutils/IkeSessionParamsUtils.java +++ b/core/java/android/net/vcn/persistablebundleutils/IkeSessionParamsUtils.java @@ -19,11 +19,13 @@ package android.net.vcn.persistablebundleutils; import static com.android.internal.annotations.VisibleForTesting.Visibility; import android.annotation.NonNull; +import android.net.eap.EapSessionConfig; import android.net.ipsec.ike.IkeSaProposal; import android.net.ipsec.ike.IkeSessionParams; import android.net.ipsec.ike.IkeSessionParams.IkeAuthConfig; import android.net.ipsec.ike.IkeSessionParams.IkeAuthDigitalSignLocalConfig; import android.net.ipsec.ike.IkeSessionParams.IkeAuthDigitalSignRemoteConfig; +import android.net.ipsec.ike.IkeSessionParams.IkeAuthEapConfig; import android.net.ipsec.ike.IkeSessionParams.IkeAuthPskConfig; import android.os.PersistableBundle; @@ -160,11 +162,13 @@ public final class IkeSessionParamsUtils { IkeAuthDigitalSignRemoteConfig config = (IkeAuthDigitalSignRemoteConfig) authConfig; return IkeAuthDigitalSignConfigUtils.toPersistableBundle( config, createPersistableBundle(IKE_AUTH_METHOD_PUB_KEY_SIGNATURE)); + } else if (authConfig instanceof IkeAuthEapConfig) { + IkeAuthEapConfig config = (IkeAuthEapConfig) authConfig; + return IkeAuthEapConfigUtils.toPersistableBundle( + config, createPersistableBundle(IKE_AUTH_METHOD_EAP)); } else { throw new IllegalStateException("Invalid IkeAuthConfig subclass"); } - - // TODO: Handle EAP auth and digital signature based auth. } private static PersistableBundle createPersistableBundle(int type) { @@ -191,7 +195,7 @@ public final class IkeSessionParamsUtils { } IkeAuthPskConfigUtils.setBuilderByReadingPersistableBundle( localAuthBundle, remoteAuthBundle, builder); - break; + return; case IKE_AUTH_METHOD_PUB_KEY_SIGNATURE: if (remoteMethodType != IKE_AUTH_METHOD_PUB_KEY_SIGNATURE) { throw new IllegalArgumentException( @@ -200,12 +204,21 @@ public final class IkeSessionParamsUtils { } IkeAuthDigitalSignConfigUtils.setBuilderByReadingPersistableBundle( localAuthBundle, remoteAuthBundle, builder); - break; + return; + case IKE_AUTH_METHOD_EAP: + if (remoteMethodType != IKE_AUTH_METHOD_PUB_KEY_SIGNATURE) { + throw new IllegalArgumentException( + "When using EAP for local authentication, expect remote auth" + + " method to be digital signature based, but was " + + remoteMethodType); + } + IkeAuthEapConfigUtils.setBuilderByReadingPersistableBundle( + localAuthBundle, remoteAuthBundle, builder); + return; default: throw new IllegalArgumentException( "Invalid EAP method type " + localMethodType); } - // TODO: Handle EAP auth and digital signature based auth. } } @@ -339,4 +352,41 @@ public final class IkeSessionParamsUtils { builder.setAuthDigitalSignature(caCert, endCert, certList, privateKey); } } + + private static final class IkeAuthEapConfigUtils { + private static final String EAP_CONFIG_KEY = "EAP_CONFIG_KEY"; + + @NonNull + public static PersistableBundle toPersistableBundle( + @NonNull IkeAuthEapConfig config, @NonNull PersistableBundle result) { + result.putPersistableBundle( + EAP_CONFIG_KEY, + EapSessionConfigUtils.toPersistableBundle(config.getEapConfig())); + return result; + } + + public static void setBuilderByReadingPersistableBundle( + @NonNull PersistableBundle localAuthBundle, + @NonNull PersistableBundle remoteAuthBundle, + @NonNull IkeSessionParams.Builder builder) { + // Deserialize localAuth + final PersistableBundle eapBundle = + localAuthBundle.getPersistableBundle(EAP_CONFIG_KEY); + Objects.requireNonNull(eapBundle, "EAP Config was null"); + final EapSessionConfig eapConfig = + EapSessionConfigUtils.fromPersistableBundle(eapBundle); + + // Deserialize remoteAuth + final PersistableBundle trustCertBundle = + remoteAuthBundle.getPersistableBundle( + IkeAuthDigitalSignConfigUtils.TRUST_CERT_KEY); + + X509Certificate serverCaCert = null; + if (trustCertBundle != null) { + final byte[] encodedCaCert = PersistableBundleUtils.toByteArray(trustCertBundle); + serverCaCert = CertUtils.certificateFromByteArray(encodedCaCert); + } + builder.setAuthEap(serverCaCert, eapConfig); + } + } } diff --git a/tests/vcn/java/android/net/vcn/persistablebundleutils/IkeSessionParamsUtilsTest.java b/tests/vcn/java/android/net/vcn/persistablebundleutils/IkeSessionParamsUtilsTest.java index d857aaedf6a37..720d44a5b6fb5 100644 --- a/tests/vcn/java/android/net/vcn/persistablebundleutils/IkeSessionParamsUtilsTest.java +++ b/tests/vcn/java/android/net/vcn/persistablebundleutils/IkeSessionParamsUtilsTest.java @@ -16,9 +16,12 @@ package android.net.vcn.persistablebundleutils; +import static android.telephony.TelephonyManager.APPTYPE_USIM; + import static org.junit.Assert.assertEquals; import android.net.InetAddresses; +import android.net.eap.EapSessionConfig; import android.net.ipsec.ike.IkeFqdnIdentification; import android.net.ipsec.ike.IkeSessionParams; import android.os.PersistableBundle; @@ -36,6 +39,7 @@ import org.junit.runner.RunWith; import java.io.InputStream; import java.io.InputStreamReader; import java.net.InetAddress; +import java.nio.charset.StandardCharsets; import java.security.cert.CertificateFactory; import java.security.cert.X509Certificate; import java.security.interfaces.RSAPrivateKey; @@ -133,4 +137,22 @@ public class IkeSessionParamsUtilsTest { .build(); verifyPersistableBundleEncodeDecodeIsLossless(params); } + + @Test + public void testEncodeRecodeParamsWithEapAuth() throws Exception { + final X509Certificate serverCaCert = createCertFromPemFile("self-signed-ca.pem"); + + final byte[] eapId = "test@android.net".getBytes(StandardCharsets.US_ASCII); + final int subId = 1; + final EapSessionConfig eapConfig = + new EapSessionConfig.Builder() + .setEapIdentity(eapId) + .setEapSimConfig(subId, APPTYPE_USIM) + .setEapAkaConfig(subId, APPTYPE_USIM) + .build(); + + final IkeSessionParams params = + createBuilderMinimum().setAuthEap(serverCaCert, eapConfig).build(); + verifyPersistableBundleEncodeDecodeIsLossless(params); + } }