diff options
author | Yan Yan <evitayan@google.com> | 2021-02-24 10:31:18 -0800 |
---|---|---|
committer | Yan Yan <evitayan@google.com> | 2021-03-04 12:37:43 -0800 |
commit | 2f0f6b575c8f00fba9c87cadc58ddb8b058529af (patch) | |
tree | d66caaa4209f4a5a801e38881ae6e436da5e1c5b | |
parent | 67b0387dc7192eb68a62fc60e912c1c04832c9d8 (diff) |
Support converting IkeAuthConfig to/from PersistableBundle
Bug: 163604823
Test: FrameworksVcnTests(add new tests)
Change-Id: I97d9a7db423711dbccea412b96f069fe1dbd2779
3 files changed, 218 insertions, 15 deletions
diff --git a/core/java/android/net/vcn/persistablebundleutils/IkeSessionParamsUtils.java b/core/java/android/net/vcn/persistablebundleutils/IkeSessionParamsUtils.java index 2d292c830807..3527f3e2523d 100644 --- a/core/java/android/net/vcn/persistablebundleutils/IkeSessionParamsUtils.java +++ b/core/java/android/net/vcn/persistablebundleutils/IkeSessionParamsUtils.java @@ -21,11 +21,14 @@ import static com.android.internal.annotations.VisibleForTesting.Visibility; import android.annotation.NonNull; 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.IkeAuthPskConfig; import android.os.PersistableBundle; import com.android.internal.annotations.VisibleForTesting; import com.android.server.vcn.util.PersistableBundleUtils; +import java.util.Arrays; import java.util.List; import java.util.Objects; @@ -40,6 +43,8 @@ public final class IkeSessionParamsUtils { private static final String SA_PROPOSALS_KEY = "SA_PROPOSALS_KEY"; private static final String LOCAL_ID_KEY = "LOCAL_ID_KEY"; private static final String REMOTE_ID_KEY = "REMOTE_ID_KEY"; + private static final String LOCAL_AUTH_KEY = "LOCAL_AUTH_KEY"; + private static final String REMOTE_AUTH_KEY = "REMOTE_AUTH_KEY"; private static final String RETRANS_TIMEOUTS_KEY = "RETRANS_TIMEOUTS_KEY"; private static final String HARD_LIFETIME_SEC_KEY = "HARD_LIFETIME_SEC_KEY"; private static final String SOFT_LIFETIME_SEC_KEY = "SOFT_LIFETIME_SEC_KEY"; @@ -71,13 +76,18 @@ public final class IkeSessionParamsUtils { REMOTE_ID_KEY, IkeIdentificationUtils.toPersistableBundle(params.getRemoteIdentification())); + result.putPersistableBundle( + LOCAL_AUTH_KEY, AuthConfigUtils.toPersistableBundle(params.getLocalAuthConfig())); + result.putPersistableBundle( + REMOTE_AUTH_KEY, AuthConfigUtils.toPersistableBundle(params.getRemoteAuthConfig())); + result.putIntArray(RETRANS_TIMEOUTS_KEY, params.getRetransmissionTimeoutsMillis()); result.putInt(HARD_LIFETIME_SEC_KEY, params.getHardLifetimeSeconds()); result.putInt(SOFT_LIFETIME_SEC_KEY, params.getSoftLifetimeSeconds()); result.putInt(DPD_DELAY_SEC_KEY, params.getDpdDelaySeconds()); result.putInt(NATT_KEEPALIVE_DELAY_SEC_KEY, params.getNattKeepAliveDelaySeconds()); - // TODO: Handle authentication configuration, configuration requests and IKE options. + // TODO: Handle configuration requests and IKE options. return result; } @@ -107,14 +117,105 @@ public final class IkeSessionParamsUtils { IkeIdentificationUtils.fromPersistableBundle( in.getPersistableBundle(REMOTE_ID_KEY))); + AuthConfigUtils.setBuilderByReadingPersistableBundle( + in.getPersistableBundle(LOCAL_AUTH_KEY), + in.getPersistableBundle(REMOTE_AUTH_KEY), + builder); + builder.setRetransmissionTimeoutsMillis(in.getIntArray(RETRANS_TIMEOUTS_KEY)); builder.setLifetimeSeconds( in.getInt(HARD_LIFETIME_SEC_KEY), in.getInt(SOFT_LIFETIME_SEC_KEY)); builder.setDpdDelaySeconds(in.getInt(DPD_DELAY_SEC_KEY)); builder.setNattKeepAliveDelaySeconds(in.getInt(NATT_KEEPALIVE_DELAY_SEC_KEY)); - // TODO: Handle authentication configuration, configuration requests and IKE options. + // TODO: Handle configuration requests and IKE options. return builder.build(); } + + private static final class AuthConfigUtils { + private static final int IKE_AUTH_METHOD_PSK = 1; + private static final int IKE_AUTH_METHOD_PUB_KEY_SIGNATURE = 2; + private static final int IKE_AUTH_METHOD_EAP = 3; + + private static final String AUTH_METHOD_KEY = "AUTH_METHOD_KEY"; + + @NonNull + public static PersistableBundle toPersistableBundle(@NonNull IkeAuthConfig authConfig) { + if (authConfig instanceof IkeAuthPskConfig) { + IkeAuthPskConfig config = (IkeAuthPskConfig) authConfig; + return IkeAuthPskConfigUtils.toPersistableBundle( + config, createPersistableBundle(IKE_AUTH_METHOD_PSK)); + } else { + throw new IllegalStateException("Invalid IkeAuthConfig subclass"); + } + + // TODO: Handle EAP auth and digital signature based auth. + } + + private static PersistableBundle createPersistableBundle(int type) { + final PersistableBundle result = new PersistableBundle(); + result.putInt(AUTH_METHOD_KEY, type); + return result; + } + + public static void setBuilderByReadingPersistableBundle( + @NonNull PersistableBundle localAuthBundle, + @NonNull PersistableBundle remoteAuthBundle, + @NonNull IkeSessionParams.Builder builder) { + Objects.requireNonNull(localAuthBundle, "localAuthBundle was null"); + Objects.requireNonNull(remoteAuthBundle, "remoteAuthBundle was null"); + + final int localMethodType = localAuthBundle.getInt(AUTH_METHOD_KEY); + final int remoteMethodType = remoteAuthBundle.getInt(AUTH_METHOD_KEY); + switch (localMethodType) { + case IKE_AUTH_METHOD_PSK: + if (remoteMethodType != IKE_AUTH_METHOD_PSK) { + throw new IllegalArgumentException( + "Expect remote auth method to be PSK based, but was " + + remoteMethodType); + } + IkeAuthPskConfigUtils.setBuilderByReadingPersistableBundle( + localAuthBundle, remoteAuthBundle, builder); + break; + default: + throw new IllegalArgumentException( + "Invalid EAP method type " + localMethodType); + } + // TODO: Handle EAP auth and digital signature based auth. + } + } + + private static final class IkeAuthPskConfigUtils { + private static final String PSK_KEY = "PSK_KEY"; + + @NonNull + public static PersistableBundle toPersistableBundle( + @NonNull IkeAuthPskConfig config, @NonNull PersistableBundle result) { + result.putPersistableBundle( + PSK_KEY, PersistableBundleUtils.fromByteArray(config.getPsk())); + return result; + } + + public static void setBuilderByReadingPersistableBundle( + @NonNull PersistableBundle localAuthBundle, + @NonNull PersistableBundle remoteAuthBundle, + @NonNull IkeSessionParams.Builder builder) { + Objects.requireNonNull(localAuthBundle, "localAuthBundle was null"); + Objects.requireNonNull(remoteAuthBundle, "remoteAuthBundle was null"); + + final PersistableBundle localPskBundle = localAuthBundle.getPersistableBundle(PSK_KEY); + final PersistableBundle remotePskBundle = + remoteAuthBundle.getPersistableBundle(PSK_KEY); + Objects.requireNonNull(localAuthBundle, "Local PSK was null"); + Objects.requireNonNull(remoteAuthBundle, "Remote PSK was null"); + + final byte[] localPsk = PersistableBundleUtils.toByteArray(localPskBundle); + final byte[] remotePsk = PersistableBundleUtils.toByteArray(remotePskBundle); + if (!Arrays.equals(localPsk, remotePsk)) { + throw new IllegalArgumentException("Local PSK and remote PSK are different"); + } + builder.setAuthPsk(localPsk); + } + } } diff --git a/tests/vcn/java/android/net/vcn/persistablebundleutils/IkeSessionParamsUtilsTest.java b/tests/vcn/java/android/net/vcn/persistablebundleutils/IkeSessionParamsUtilsTest.java new file mode 100644 index 000000000000..be93d4e75375 --- /dev/null +++ b/tests/vcn/java/android/net/vcn/persistablebundleutils/IkeSessionParamsUtilsTest.java @@ -0,0 +1,98 @@ +/* + * 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 static org.junit.Assert.assertEquals; + +import android.net.InetAddresses; +import android.net.ipsec.ike.IkeFqdnIdentification; +import android.net.ipsec.ike.IkeSessionParams; +import android.os.PersistableBundle; + +import androidx.test.filters.SmallTest; +import androidx.test.runner.AndroidJUnit4; + +import org.junit.Test; +import org.junit.runner.RunWith; + +import java.net.InetAddress; +import java.util.concurrent.TimeUnit; + +@RunWith(AndroidJUnit4.class) +@SmallTest +public class IkeSessionParamsUtilsTest { + private static IkeSessionParams.Builder createBuilderMinimum() { + final InetAddress serverAddress = InetAddresses.parseNumericAddress("192.0.2.100"); + + return new IkeSessionParams.Builder() + .setServerHostname(serverAddress.getHostAddress()) + .addSaProposal(SaProposalUtilsTest.buildTestIkeSaProposal()) + .setLocalIdentification(new IkeFqdnIdentification("client.test.android.net")) + .setRemoteIdentification(new IkeFqdnIdentification("server.test.android.net")) + .setAuthPsk("psk".getBytes()); + } + + private static void verifyPersistableBundleEncodeDecodeIsLossless(IkeSessionParams params) { + final PersistableBundle bundle = IkeSessionParamsUtils.toPersistableBundle(params); + final IkeSessionParams result = IkeSessionParamsUtils.fromPersistableBundle(bundle); + + assertEquals(result, params); + } + + @Test + public void testEncodeRecodeParamsWithLifetimes() throws Exception { + final int hardLifetime = (int) TimeUnit.HOURS.toSeconds(20L); + final int softLifetime = (int) TimeUnit.HOURS.toSeconds(10L); + final IkeSessionParams params = + createBuilderMinimum().setLifetimeSeconds(hardLifetime, softLifetime).build(); + verifyPersistableBundleEncodeDecodeIsLossless(params); + } + + @Test + public void testEncodeRecodeParamsWithDpdDelay() throws Exception { + final int dpdDelay = (int) TimeUnit.MINUTES.toSeconds(10L); + final IkeSessionParams params = createBuilderMinimum().setDpdDelaySeconds(dpdDelay).build(); + + verifyPersistableBundleEncodeDecodeIsLossless(params); + } + + @Test + public void testEncodeRecodeParamsWithNattKeepalive() throws Exception { + final int nattKeepAliveDelay = (int) TimeUnit.MINUTES.toSeconds(5L); + final IkeSessionParams params = + createBuilderMinimum().setNattKeepAliveDelaySeconds(nattKeepAliveDelay).build(); + + verifyPersistableBundleEncodeDecodeIsLossless(params); + } + + @Test + public void testEncodeRecodeParamsWithRetransmissionTimeouts() throws Exception { + final int[] retransmissionTimeout = new int[] {500, 500, 500, 500, 500, 500}; + final IkeSessionParams params = + createBuilderMinimum() + .setRetransmissionTimeoutsMillis(retransmissionTimeout) + .build(); + + verifyPersistableBundleEncodeDecodeIsLossless(params); + } + + @Test + public void testEncodeRecodeParamsWithAuthPsk() throws Exception { + final IkeSessionParams params = createBuilderMinimum().setAuthPsk("psk".getBytes()).build(); + verifyPersistableBundleEncodeDecodeIsLossless(params); + } +} diff --git a/tests/vcn/java/android/net/vcn/persistablebundleutils/SaProposalUtilsTest.java b/tests/vcn/java/android/net/vcn/persistablebundleutils/SaProposalUtilsTest.java index 8ae8692b4f75..664044a9e7d4 100644 --- a/tests/vcn/java/android/net/vcn/persistablebundleutils/SaProposalUtilsTest.java +++ b/tests/vcn/java/android/net/vcn/persistablebundleutils/SaProposalUtilsTest.java @@ -32,21 +32,25 @@ import org.junit.runner.RunWith; @RunWith(AndroidJUnit4.class) @SmallTest public class SaProposalUtilsTest { + /** Package private so that IkeSessionParamsUtilsTest can use it */ + static IkeSaProposal buildTestIkeSaProposal() { + return new IkeSaProposal.Builder() + .addEncryptionAlgorithm( + SaProposal.ENCRYPTION_ALGORITHM_3DES, SaProposal.KEY_LEN_UNUSED) + .addEncryptionAlgorithm( + SaProposal.ENCRYPTION_ALGORITHM_AES_CBC, SaProposal.KEY_LEN_AES_128) + .addIntegrityAlgorithm(SaProposal.INTEGRITY_ALGORITHM_HMAC_SHA1_96) + .addIntegrityAlgorithm(SaProposal.INTEGRITY_ALGORITHM_HMAC_SHA2_256_128) + .addPseudorandomFunction(SaProposal.PSEUDORANDOM_FUNCTION_AES128_XCBC) + .addPseudorandomFunction(SaProposal.PSEUDORANDOM_FUNCTION_SHA2_256) + .addDhGroup(SaProposal.DH_GROUP_1024_BIT_MODP) + .addDhGroup(SaProposal.DH_GROUP_3072_BIT_MODP) + .build(); + } + @Test public void testPersistableBundleEncodeDecodeIsLosslessIkeProposal() throws Exception { - final IkeSaProposal proposal = - new IkeSaProposal.Builder() - .addEncryptionAlgorithm( - SaProposal.ENCRYPTION_ALGORITHM_3DES, SaProposal.KEY_LEN_UNUSED) - .addEncryptionAlgorithm( - SaProposal.ENCRYPTION_ALGORITHM_AES_CBC, SaProposal.KEY_LEN_AES_128) - .addIntegrityAlgorithm(SaProposal.INTEGRITY_ALGORITHM_HMAC_SHA1_96) - .addIntegrityAlgorithm(SaProposal.INTEGRITY_ALGORITHM_HMAC_SHA2_256_128) - .addPseudorandomFunction(SaProposal.PSEUDORANDOM_FUNCTION_AES128_XCBC) - .addPseudorandomFunction(SaProposal.PSEUDORANDOM_FUNCTION_SHA2_256) - .addDhGroup(SaProposal.DH_GROUP_1024_BIT_MODP) - .addDhGroup(SaProposal.DH_GROUP_3072_BIT_MODP) - .build(); + final IkeSaProposal proposal = buildTestIkeSaProposal(); final PersistableBundle bundle = IkeSaProposalUtils.toPersistableBundle(proposal); final SaProposal resultProposal = IkeSaProposalUtils.fromPersistableBundle(bundle); |