Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 32fed896 authored by Yan Yan's avatar Yan Yan
Browse files

Support converting TunnelModeChildSessionParams to/from PersistableBundle

Bug: 163604823
Test: FrameworksVcnTests(add new tests)
Change-Id: I4d27ac37ce750930cefa73de25e5deea74591d0e
parent 6ce7d0db
Loading
Loading
Loading
Loading
+117 −0
Original line number Diff line number Diff line
/*
 * 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 com.android.internal.annotations.VisibleForTesting.Visibility;

import android.annotation.NonNull;
import android.net.ipsec.ike.ChildSaProposal;
import android.net.ipsec.ike.IkeTrafficSelector;
import android.net.ipsec.ike.TunnelModeChildSessionParams;
import android.os.PersistableBundle;

import com.android.internal.annotations.VisibleForTesting;
import com.android.server.vcn.util.PersistableBundleUtils;

import java.util.List;
import java.util.Objects;

/**
 * Provides utility methods to convert TunnelModeChildSessionParams to/from PersistableBundle.
 *
 * @hide
 */
@VisibleForTesting(visibility = Visibility.PRIVATE)
public final class TunnelModeChildSessionParamsUtils {
    private static final String INBOUND_TS_KEY = "INBOUND_TS_KEY";
    private static final String OUTBOUND_TS_KEY = "OUTBOUND_TS_KEY";
    private static final String SA_PROPOSALS_KEY = "SA_PROPOSALS_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";

    /** Serializes a TunnelModeChildSessionParams to a PersistableBundle. */
    @NonNull
    public static PersistableBundle toPersistableBundle(TunnelModeChildSessionParams params) {
        final PersistableBundle result = new PersistableBundle();

        final PersistableBundle saProposalBundle =
                PersistableBundleUtils.fromList(
                        params.getSaProposals(), ChildSaProposalUtils::toPersistableBundle);
        result.putPersistableBundle(SA_PROPOSALS_KEY, saProposalBundle);

        final PersistableBundle inTsBundle =
                PersistableBundleUtils.fromList(
                        params.getInboundTrafficSelectors(),
                        IkeTrafficSelectorUtils::toPersistableBundle);
        result.putPersistableBundle(INBOUND_TS_KEY, inTsBundle);

        final PersistableBundle outTsBundle =
                PersistableBundleUtils.fromList(
                        params.getOutboundTrafficSelectors(),
                        IkeTrafficSelectorUtils::toPersistableBundle);
        result.putPersistableBundle(OUTBOUND_TS_KEY, outTsBundle);

        result.putInt(HARD_LIFETIME_SEC_KEY, params.getHardLifetimeSeconds());
        result.putInt(SOFT_LIFETIME_SEC_KEY, params.getSoftLifetimeSeconds());

        // TODO: b/163604823 Support serializing configuration requests.

        return result;
    }

    private static List<IkeTrafficSelector> getTsFromPersistableBundle(
            PersistableBundle in, String key) {
        PersistableBundle tsBundle = in.getPersistableBundle(key);
        Objects.requireNonNull(tsBundle, "Value for key " + key + " was null");
        return PersistableBundleUtils.toList(
                tsBundle, IkeTrafficSelectorUtils::fromPersistableBundle);
    }

    /** Constructs a TunnelModeChildSessionParams by deserializing a PersistableBundle. */
    @NonNull
    public static TunnelModeChildSessionParams fromPersistableBundle(
            @NonNull PersistableBundle in) {
        Objects.requireNonNull(in, "PersistableBundle was null");

        final TunnelModeChildSessionParams.Builder builder =
                new TunnelModeChildSessionParams.Builder();

        final PersistableBundle proposalBundle = in.getPersistableBundle(SA_PROPOSALS_KEY);
        Objects.requireNonNull(proposalBundle, "SA proposal was null");
        final List<ChildSaProposal> proposals =
                PersistableBundleUtils.toList(
                        proposalBundle, ChildSaProposalUtils::fromPersistableBundle);
        for (ChildSaProposal p : proposals) {
            builder.addSaProposal(p);
        }

        for (IkeTrafficSelector ts : getTsFromPersistableBundle(in, INBOUND_TS_KEY)) {
            builder.addInboundTrafficSelectors(ts);
        }

        for (IkeTrafficSelector ts : getTsFromPersistableBundle(in, OUTBOUND_TS_KEY)) {
            builder.addOutboundTrafficSelectors(ts);
        }

        builder.setLifetimeSeconds(
                in.getInt(HARD_LIFETIME_SEC_KEY), in.getInt(SOFT_LIFETIME_SEC_KEY));

        // TODO: b/163604823 Support deserializing configuration requests.

        return builder.build();
    }
}
+13 −11
Original line number Diff line number Diff line
@@ -54,19 +54,21 @@ public class SaProposalUtilsTest {
        assertEquals(proposal, resultProposal);
    }

    @Test
    public void testPersistableBundleEncodeDecodeIsLosslessChildProposal() throws Exception {
        final ChildSaProposal proposal =
                new ChildSaProposal.Builder()
    /** Package private so that TunnelModeChildSessionParamsUtilsTest can use it */
    static ChildSaProposal buildTestChildSaProposal() {
        return new ChildSaProposal.Builder()
                .addEncryptionAlgorithm(
                                SaProposal.ENCRYPTION_ALGORITHM_AES_GCM_12,
                                SaProposal.KEY_LEN_AES_128)
                        SaProposal.ENCRYPTION_ALGORITHM_AES_GCM_12, SaProposal.KEY_LEN_AES_128)
                .addEncryptionAlgorithm(
                                SaProposal.ENCRYPTION_ALGORITHM_AES_GCM_12,
                                SaProposal.KEY_LEN_AES_192)
                        SaProposal.ENCRYPTION_ALGORITHM_AES_GCM_12, SaProposal.KEY_LEN_AES_192)
                .addDhGroup(SaProposal.DH_GROUP_1024_BIT_MODP)
                .addDhGroup(SaProposal.DH_GROUP_4096_BIT_MODP)
                .build();
    }

    @Test
    public void testPersistableBundleEncodeDecodeIsLosslessChildProposal() throws Exception {
        final ChildSaProposal proposal = buildTestChildSaProposal();

        final PersistableBundle bundle = ChildSaProposalUtils.toPersistableBundle(proposal);
        final SaProposal resultProposal = ChildSaProposalUtils.fromPersistableBundle(bundle);
+91 −0
Original line number Diff line number Diff line
/*
 * 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.ChildSaProposal;
import android.net.ipsec.ike.IkeTrafficSelector;
import android.net.ipsec.ike.TunnelModeChildSessionParams;
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.util.concurrent.TimeUnit;

@RunWith(AndroidJUnit4.class)
@SmallTest
public class TunnelModeChildSessionParamsUtilsTest {
    private TunnelModeChildSessionParams.Builder createBuilderMinimum() {
        final ChildSaProposal saProposal = SaProposalUtilsTest.buildTestChildSaProposal();
        return new TunnelModeChildSessionParams.Builder().addSaProposal(saProposal);
    }

    private static void verifyPersistableBundleEncodeDecodeIsLossless(
            TunnelModeChildSessionParams params) {
        final PersistableBundle bundle =
                TunnelModeChildSessionParamsUtils.toPersistableBundle(params);
        final TunnelModeChildSessionParams result =
                TunnelModeChildSessionParamsUtils.fromPersistableBundle(bundle);

        assertEquals(params, result);
    }

    @Test
    public void testMinimumParamsEncodeDecodeIsLossless() throws Exception {
        final TunnelModeChildSessionParams sessionParams = createBuilderMinimum().build();
        verifyPersistableBundleEncodeDecodeIsLossless(sessionParams);
    }

    @Test
    public void testSetTsEncodeDecodeIsLossless() throws Exception {
        final IkeTrafficSelector tsInbound =
                new IkeTrafficSelector(
                        16,
                        65520,
                        InetAddresses.parseNumericAddress("192.0.2.100"),
                        InetAddresses.parseNumericAddress("192.0.2.101"));
        final IkeTrafficSelector tsOutbound =
                new IkeTrafficSelector(
                        32,
                        256,
                        InetAddresses.parseNumericAddress("192.0.2.200"),
                        InetAddresses.parseNumericAddress("192.0.2.255"));

        final TunnelModeChildSessionParams sessionParams =
                createBuilderMinimum()
                        .addInboundTrafficSelectors(tsInbound)
                        .addOutboundTrafficSelectors(tsOutbound)
                        .build();
        verifyPersistableBundleEncodeDecodeIsLossless(sessionParams);
    }

    @Test
    public void testSetLifetimesEncodeDecodeIsLossless() throws Exception {
        final int hardLifetime = (int) TimeUnit.HOURS.toSeconds(3L);
        final int softLifetime = (int) TimeUnit.HOURS.toSeconds(1L);

        final TunnelModeChildSessionParams sessionParams =
                createBuilderMinimum().setLifetimeSeconds(hardLifetime, softLifetime).build();
        verifyPersistableBundleEncodeDecodeIsLossless(sessionParams);
    }
}