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

Commit f14e3e03 authored by Yan Yan's avatar Yan Yan
Browse files

Support converting IkeSaProposal to/from PersistableBundle

Bug: 163604823
Test: FrameworksVcnTests(new tests added)
Change-Id: I108e5a946296f65bbe92549464aa68a2ec453659
parent 2a9bfb28
Loading
Loading
Loading
Loading
+87 −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.IkeSaProposal;
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 IkeSaProposal to/from PersistableBundle.
 *
 * @hide
 */
@VisibleForTesting(visibility = Visibility.PRIVATE)
public final class IkeSaProposalUtils extends SaProposalUtilsBase {
    private static final String PRF_KEY = "PRF_KEY";

    /** Serializes an IkeSaProposal to a PersistableBundle. */
    @NonNull
    public static PersistableBundle toPersistableBundle(IkeSaProposal proposal) {
        final PersistableBundle result = SaProposalUtilsBase.toPersistableBundle(proposal);

        final int[] prfArray =
                proposal.getPseudorandomFunctions().stream().mapToInt(i -> i).toArray();
        result.putIntArray(PRF_KEY, prfArray);

        return result;
    }

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

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

        final PersistableBundle encryptionBundle = in.getPersistableBundle(ENCRYPT_ALGO_KEY);
        Objects.requireNonNull(encryptionBundle, "Encryption algo bundle was null");
        final List<EncryptionAlgoKeyLenPair> encryptList =
                PersistableBundleUtils.toList(encryptionBundle, EncryptionAlgoKeyLenPair::new);
        for (EncryptionAlgoKeyLenPair t : encryptList) {
            builder.addEncryptionAlgorithm(t.encryptionAlgo, t.keyLen);
        }

        final int[] integrityAlgoIdArray = in.getIntArray(INTEGRITY_ALGO_KEY);
        Objects.requireNonNull(integrityAlgoIdArray, "Integrity algo array was null");
        for (int algo : integrityAlgoIdArray) {
            builder.addIntegrityAlgorithm(algo);
        }

        final int[] dhGroupArray = in.getIntArray(DH_GROUP_KEY);
        Objects.requireNonNull(dhGroupArray, "DH Group array was null");
        for (int dh : dhGroupArray) {
            builder.addDhGroup(dh);
        }

        final int[] prfArray = in.getIntArray(PRF_KEY);
        Objects.requireNonNull(prfArray, "PRF array was null");
        for (int prf : prfArray) {
            builder.addPseudorandomFunction(prf);
        }

        return builder.build();
    }
}
+96 −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 android.annotation.NonNull;
import android.net.ipsec.ike.SaProposal;
import android.os.PersistableBundle;
import android.util.Pair;

import com.android.server.vcn.util.PersistableBundleUtils;

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

/**
 * Abstract utility class to convert SaProposal to/from PersistableBundle.
 *
 * @hide
 */
abstract class SaProposalUtilsBase {
    static final String ENCRYPT_ALGO_KEY = "ENCRYPT_ALGO_KEY";
    static final String INTEGRITY_ALGO_KEY = "INTEGRITY_ALGO_KEY";
    static final String DH_GROUP_KEY = "DH_GROUP_KEY";

    static class EncryptionAlgoKeyLenPair {
        private static final String ALGO_KEY = "ALGO_KEY";
        private static final String KEY_LEN_KEY = "KEY_LEN_KEY";

        public final int encryptionAlgo;
        public final int keyLen;

        EncryptionAlgoKeyLenPair(int encryptionAlgo, int keyLen) {
            this.encryptionAlgo = encryptionAlgo;
            this.keyLen = keyLen;
        }

        EncryptionAlgoKeyLenPair(PersistableBundle in) {
            Objects.requireNonNull(in, "PersistableBundle was null");

            this.encryptionAlgo = in.getInt(ALGO_KEY);
            this.keyLen = in.getInt(KEY_LEN_KEY);
        }

        public PersistableBundle toPersistableBundle() {
            final PersistableBundle result = new PersistableBundle();

            result.putInt(ALGO_KEY, encryptionAlgo);
            result.putInt(KEY_LEN_KEY, keyLen);

            return result;
        }
    }

    /**
     * Serializes common info of a SaProposal to a PersistableBundle.
     *
     * @hide
     */
    @NonNull
    static PersistableBundle toPersistableBundle(SaProposal proposal) {
        final PersistableBundle result = new PersistableBundle();

        final List<EncryptionAlgoKeyLenPair> encryptAlgoKeyLenPairs = new ArrayList<>();
        for (Pair<Integer, Integer> pair : proposal.getEncryptionAlgorithms()) {
            encryptAlgoKeyLenPairs.add(new EncryptionAlgoKeyLenPair(pair.first, pair.second));
        }
        final PersistableBundle encryptionBundle =
                PersistableBundleUtils.fromList(
                        encryptAlgoKeyLenPairs, EncryptionAlgoKeyLenPair::toPersistableBundle);
        result.putPersistableBundle(ENCRYPT_ALGO_KEY, encryptionBundle);

        final int[] integrityAlgoIdArray =
                proposal.getIntegrityAlgorithms().stream().mapToInt(i -> i).toArray();
        result.putIntArray(INTEGRITY_ALGO_KEY, integrityAlgoIdArray);

        final int[] dhGroupArray = proposal.getDhGroups().stream().mapToInt(i -> i).toArray();
        result.putIntArray(DH_GROUP_KEY, dhGroupArray);

        return result;
    }
}
+55 −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.ipsec.ike.IkeSaProposal;
import android.net.ipsec.ike.SaProposal;
import android.os.PersistableBundle;

import androidx.test.filters.SmallTest;
import androidx.test.runner.AndroidJUnit4;

import org.junit.Test;
import org.junit.runner.RunWith;

@RunWith(AndroidJUnit4.class)
@SmallTest
public class SaProposalUtilsTest {
    @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 PersistableBundle bundle = IkeSaProposalUtils.toPersistableBundle(proposal);
        final SaProposal resultProposal = IkeSaProposalUtils.fromPersistableBundle(bundle);

        assertEquals(proposal, resultProposal);
    }
}