From 3981eb637679129418168406a456d7af0f9c787c Mon Sep 17 00:00:00 2001 From: Chiachang Wang Date: Wed, 26 Jan 2022 14:51:36 +0800 Subject: [PATCH] Support building Ikev2VpnProfile from an IkeTunnelConnectionParams Add a new builder constructor in Ikev2VpnProfile.Builder to allow building Ikev2VpnProfile from a IkeTunnelConnectionParams object. Bug: 184750836 Test: atest FrameworksNetTests Change-Id: I586e7b24c35a777d39402148036d25606a733e85 CTS-Coverage-Bug: 184750836 --- core/api/current.txt | 1 + core/java/android/net/Ikev2VpnProfile.java | 140 +++++++++++++++++++++ 2 files changed, 141 insertions(+) diff --git a/core/api/current.txt b/core/api/current.txt index d696bc7978254..ffd081083b824 100644 --- a/core/api/current.txt +++ b/core/api/current.txt @@ -26483,6 +26483,7 @@ package android.net { public static final class Ikev2VpnProfile.Builder { ctor public Ikev2VpnProfile.Builder(@NonNull String, @NonNull String); + ctor public Ikev2VpnProfile.Builder(@NonNull android.net.ipsec.ike.IkeTunnelConnectionParams); method @NonNull public android.net.Ikev2VpnProfile build(); method @NonNull public android.net.Ikev2VpnProfile.Builder setAllowedAlgorithms(@NonNull java.util.List); method @NonNull public android.net.Ikev2VpnProfile.Builder setAuthDigitalSignature(@NonNull java.security.cert.X509Certificate, @NonNull java.security.PrivateKey, @Nullable java.security.cert.X509Certificate); diff --git a/core/java/android/net/Ikev2VpnProfile.java b/core/java/android/net/Ikev2VpnProfile.java index 55541377a0bf4..0d036760f6519 100644 --- a/core/java/android/net/Ikev2VpnProfile.java +++ b/core/java/android/net/Ikev2VpnProfile.java @@ -25,6 +25,12 @@ import static android.net.IpSecAlgorithm.AUTH_HMAC_SHA384; import static android.net.IpSecAlgorithm.AUTH_HMAC_SHA512; import static android.net.IpSecAlgorithm.CRYPT_AES_CBC; import static android.net.IpSecAlgorithm.CRYPT_AES_CTR; +import static android.net.eap.EapSessionConfig.EapMsChapV2Config; +import static android.net.ipsec.ike.IkeSessionParams.IkeAuthConfig; +import static android.net.ipsec.ike.IkeSessionParams.IkeAuthDigitalSignLocalConfig; +import static android.net.ipsec.ike.IkeSessionParams.IkeAuthDigitalSignRemoteConfig; +import static android.net.ipsec.ike.IkeSessionParams.IkeAuthEapConfig; +import static android.net.ipsec.ike.IkeSessionParams.IkeAuthPskConfig; import static com.android.internal.annotations.VisibleForTesting.Visibility; import static com.android.internal.util.Preconditions.checkStringNotEmpty; @@ -34,6 +40,14 @@ import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.RequiresFeature; import android.content.pm.PackageManager; +import android.net.ipsec.ike.IkeFqdnIdentification; +import android.net.ipsec.ike.IkeIdentification; +import android.net.ipsec.ike.IkeIpv4AddrIdentification; +import android.net.ipsec.ike.IkeIpv6AddrIdentification; +import android.net.ipsec.ike.IkeKeyIdIdentification; +import android.net.ipsec.ike.IkeRfc822AddrIdentification; +import android.net.ipsec.ike.IkeSessionParams; +import android.net.ipsec.ike.IkeTunnelConnectionParams; import android.security.Credentials; import android.util.Log; @@ -644,6 +658,102 @@ public final class Ikev2VpnProfile extends PlatformVpnProfile { return Objects.requireNonNull(reference, String.format(messageTemplate, messageArgs)); } + private static void checkBuilderSetter(boolean constructedFromIkeTunConParams, + @NonNull String message) { + if (constructedFromIkeTunConParams) { + throw new IllegalArgumentException("Constructed using IkeTunnelConnectionParams " + + "should not set " + message); + } + } + + private static int getTypeFromIkeSession(@NonNull IkeSessionParams params) { + final IkeAuthConfig config = params.getLocalAuthConfig(); + if (config instanceof IkeAuthDigitalSignLocalConfig) { + return TYPE_IKEV2_IPSEC_RSA; + } else if (config instanceof IkeAuthEapConfig) { + return TYPE_IKEV2_IPSEC_USER_PASS; + } else if (config instanceof IkeAuthPskConfig) { + return TYPE_IKEV2_IPSEC_PSK; + } else { + throw new IllegalStateException("Invalid local IkeAuthConfig"); + } + } + + @Nullable + private static String getPasswordFromIkeSession(@NonNull IkeSessionParams params) { + if (!(params.getLocalAuthConfig() instanceof IkeAuthEapConfig)) return null; + + final IkeAuthEapConfig ikeAuthEapConfig = (IkeAuthEapConfig) params.getLocalAuthConfig(); + final EapMsChapV2Config eapMsChapV2Config = + ikeAuthEapConfig.getEapConfig().getEapMsChapV2Config(); + return (eapMsChapV2Config != null) ? eapMsChapV2Config.getPassword() : null; + } + + @Nullable + private static String getUsernameFromIkeSession(@NonNull IkeSessionParams params) { + if (!(params.getLocalAuthConfig() instanceof IkeAuthEapConfig)) return null; + + final IkeAuthEapConfig ikeAuthEapConfig = (IkeAuthEapConfig) params.getLocalAuthConfig(); + final EapMsChapV2Config eapMsChapV2Config = + ikeAuthEapConfig.getEapConfig().getEapMsChapV2Config(); + return (eapMsChapV2Config != null) ? eapMsChapV2Config.getUsername() : null; + } + + @Nullable + private static X509Certificate getUserCertFromIkeSession(@NonNull IkeSessionParams params) { + if (!(params.getLocalAuthConfig() instanceof IkeAuthDigitalSignLocalConfig)) return null; + + final IkeAuthDigitalSignLocalConfig config = + (IkeAuthDigitalSignLocalConfig) params.getLocalAuthConfig(); + return config.getClientEndCertificate(); + } + + @Nullable + private static X509Certificate getServerRootCaCertFromIkeSession( + @NonNull IkeSessionParams params) { + if (!(params.getRemoteAuthConfig() instanceof IkeAuthDigitalSignRemoteConfig)) return null; + + final IkeAuthDigitalSignRemoteConfig config = + (IkeAuthDigitalSignRemoteConfig) params.getRemoteAuthConfig(); + return config.getRemoteCaCert(); + } + + @Nullable + private static PrivateKey getRsaPrivateKeyFromIkeSession(@NonNull IkeSessionParams params) { + if (!(params.getLocalAuthConfig() instanceof IkeAuthDigitalSignLocalConfig)) return null; + + final IkeAuthDigitalSignLocalConfig config = + (IkeAuthDigitalSignLocalConfig) params.getLocalAuthConfig(); + return config.getPrivateKey(); + } + + @Nullable + private static byte[] getPresharedKeyFromIkeSession(@NonNull IkeSessionParams params) { + if (!(params.getLocalAuthConfig() instanceof IkeAuthPskConfig)) return null; + + final IkeAuthPskConfig config = (IkeAuthPskConfig) params.getLocalAuthConfig(); + return config.getPsk(); + } + + @NonNull + private static String getUserIdentityFromIkeSession(@NonNull IkeSessionParams params) { + final IkeIdentification ident = params.getLocalIdentification(); + // Refer to VpnIkev2Utils.parseIkeIdentification(). + if (ident instanceof IkeKeyIdIdentification) { + return "@#" + new String(((IkeKeyIdIdentification) ident).keyId); + } else if (ident instanceof IkeRfc822AddrIdentification) { + return "@@" + ((IkeRfc822AddrIdentification) ident).rfc822Name; + } else if (ident instanceof IkeFqdnIdentification) { + return "@" + ((IkeFqdnIdentification) ident).fqdn; + } else if (ident instanceof IkeIpv4AddrIdentification) { + return ((IkeIpv4AddrIdentification) ident).ipv4Address.getHostAddress(); + } else if (ident instanceof IkeIpv6AddrIdentification) { + return ((IkeIpv6AddrIdentification) ident).ipv6Address.getHostAddress(); + } else { + throw new IllegalArgumentException("Unknown IkeIdentification to get user identity"); + } + } + /** A incremental builder for IKEv2 VPN profiles */ public static final class Builder { private int mType = -1; @@ -671,6 +781,7 @@ public final class Ikev2VpnProfile extends PlatformVpnProfile { private int mMaxMtu = PlatformVpnProfile.MAX_MTU_DEFAULT; private boolean mIsRestrictedToTestNetworks = false; private boolean mExcludeLocalRoutes = false; + @Nullable private IkeTunnelConnectionParams mIkeTunConnParams; /** * Creates a new builder with the basic parameters of an IKEv2/IPsec VPN. @@ -687,6 +798,32 @@ public final class Ikev2VpnProfile extends PlatformVpnProfile { mUserIdentity = identity; } + /** + * Creates a new builder from a {@link IkeTunnelConnectionParams} + * + * @param ikeTunConnParams the {@link IkeTunnelConnectionParams} contains IKEv2 + * configurations + */ + @RequiresFeature(PackageManager.FEATURE_IPSEC_TUNNELS) + public Builder(@NonNull IkeTunnelConnectionParams ikeTunConnParams) { + checkNotNull(ikeTunConnParams, MISSING_PARAM_MSG_TMPL, "ikeTunConnParams"); + + mIkeTunConnParams = ikeTunConnParams; + + final IkeSessionParams ikeSessionParams = mIkeTunConnParams.getIkeSessionParams(); + mServerAddr = ikeSessionParams.getServerHostname(); + + mType = getTypeFromIkeSession(ikeSessionParams); + mUserCert = getUserCertFromIkeSession(ikeSessionParams); + mServerRootCaCert = getServerRootCaCertFromIkeSession(ikeSessionParams); + mRsaPrivateKey = getRsaPrivateKeyFromIkeSession(ikeSessionParams); + mServerRootCaCert = getServerRootCaCertFromIkeSession(ikeSessionParams); + mUsername = getUsernameFromIkeSession(ikeSessionParams); + mPassword = getPasswordFromIkeSession(ikeSessionParams); + mPresharedKey = getPresharedKeyFromIkeSession(ikeSessionParams); + mUserIdentity = getUserIdentityFromIkeSession(ikeSessionParams); + } + private void resetAuthParams() { mPresharedKey = null; mServerRootCaCert = null; @@ -719,6 +856,7 @@ public final class Ikev2VpnProfile extends PlatformVpnProfile { @Nullable X509Certificate serverRootCa) { checkNotNull(user, MISSING_PARAM_MSG_TMPL, "user"); checkNotNull(pass, MISSING_PARAM_MSG_TMPL, "pass"); + checkBuilderSetter(mIkeTunConnParams != null, "authUsernamePassword"); // Test to make sure all auth params can be encoded safely. if (serverRootCa != null) checkCert(serverRootCa); @@ -755,6 +893,7 @@ public final class Ikev2VpnProfile extends PlatformVpnProfile { @Nullable X509Certificate serverRootCa) { checkNotNull(userCert, MISSING_PARAM_MSG_TMPL, "userCert"); checkNotNull(key, MISSING_PARAM_MSG_TMPL, "key"); + checkBuilderSetter(mIkeTunConnParams != null, "authDigitalSignature"); // Test to make sure all auth params can be encoded safely. checkCert(userCert); @@ -782,6 +921,7 @@ public final class Ikev2VpnProfile extends PlatformVpnProfile { @RequiresFeature(PackageManager.FEATURE_IPSEC_TUNNELS) public Builder setAuthPsk(@NonNull byte[] psk) { checkNotNull(psk, MISSING_PARAM_MSG_TMPL, "psk"); + checkBuilderSetter(mIkeTunConnParams != null, "authPsk"); resetAuthParams(); mPresharedKey = psk;