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

Commit 64f62938 authored by Android Build Merger (Role)'s avatar Android Build Merger (Role) Committed by Android (Google) Code Review
Browse files

Merge "Merge "Validate IpSecAlgorithm Length" am: 68b81299 am: 5e3d66e7 am: 7a8f0dc0"

parents 05c1a6ca b8ab1d40
Loading
Loading
Loading
Loading
+50 −22
Original line number Original line Diff line number Diff line
@@ -21,6 +21,7 @@ import android.os.Build;
import android.os.Parcel;
import android.os.Parcel;
import android.os.Parcelable;
import android.os.Parcelable;


import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.util.HexDump;
import com.android.internal.util.HexDump;


import java.lang.annotation.Retention;
import java.lang.annotation.Retention;
@@ -34,6 +35,8 @@ import java.util.Arrays;
 * Internet Protocol</a>
 * Internet Protocol</a>
 */
 */
public final class IpSecAlgorithm implements Parcelable {
public final class IpSecAlgorithm implements Parcelable {
    private static final String TAG = "IpSecAlgorithm";

    /**
    /**
     * AES-CBC Encryption/Ciphering Algorithm.
     * AES-CBC Encryption/Ciphering Algorithm.
     *
     *
@@ -45,6 +48,7 @@ public final class IpSecAlgorithm implements Parcelable {
     * MD5 HMAC Authentication/Integrity Algorithm. <b>This algorithm is not recommended for use in
     * MD5 HMAC Authentication/Integrity Algorithm. <b>This algorithm is not recommended for use in
     * new applications and is provided for legacy compatibility with 3gpp infrastructure.</b>
     * new applications and is provided for legacy compatibility with 3gpp infrastructure.</b>
     *
     *
     * <p>Keys for this algorithm must be 128 bits in length.
     * <p>Valid truncation lengths are multiples of 8 bits from 96 to (default) 128.
     * <p>Valid truncation lengths are multiples of 8 bits from 96 to (default) 128.
     */
     */
    public static final String AUTH_HMAC_MD5 = "hmac(md5)";
    public static final String AUTH_HMAC_MD5 = "hmac(md5)";
@@ -53,6 +57,7 @@ public final class IpSecAlgorithm implements Parcelable {
     * SHA1 HMAC Authentication/Integrity Algorithm. <b>This algorithm is not recommended for use in
     * SHA1 HMAC Authentication/Integrity Algorithm. <b>This algorithm is not recommended for use in
     * new applications and is provided for legacy compatibility with 3gpp infrastructure.</b>
     * new applications and is provided for legacy compatibility with 3gpp infrastructure.</b>
     *
     *
     * <p>Keys for this algorithm must be 160 bits in length.
     * <p>Valid truncation lengths are multiples of 8 bits from 96 to (default) 160.
     * <p>Valid truncation lengths are multiples of 8 bits from 96 to (default) 160.
     */
     */
    public static final String AUTH_HMAC_SHA1 = "hmac(sha1)";
    public static final String AUTH_HMAC_SHA1 = "hmac(sha1)";
@@ -60,6 +65,7 @@ public final class IpSecAlgorithm implements Parcelable {
    /**
    /**
     * SHA256 HMAC Authentication/Integrity Algorithm.
     * SHA256 HMAC Authentication/Integrity Algorithm.
     *
     *
     * <p>Keys for this algorithm must be 256 bits in length.
     * <p>Valid truncation lengths are multiples of 8 bits from 96 to (default) 256.
     * <p>Valid truncation lengths are multiples of 8 bits from 96 to (default) 256.
     */
     */
    public static final String AUTH_HMAC_SHA256 = "hmac(sha256)";
    public static final String AUTH_HMAC_SHA256 = "hmac(sha256)";
@@ -67,6 +73,7 @@ public final class IpSecAlgorithm implements Parcelable {
    /**
    /**
     * SHA384 HMAC Authentication/Integrity Algorithm.
     * SHA384 HMAC Authentication/Integrity Algorithm.
     *
     *
     * <p>Keys for this algorithm must be 384 bits in length.
     * <p>Valid truncation lengths are multiples of 8 bits from 192 to (default) 384.
     * <p>Valid truncation lengths are multiples of 8 bits from 192 to (default) 384.
     */
     */
    public static final String AUTH_HMAC_SHA384 = "hmac(sha384)";
    public static final String AUTH_HMAC_SHA384 = "hmac(sha384)";
@@ -74,6 +81,7 @@ public final class IpSecAlgorithm implements Parcelable {
    /**
    /**
     * SHA512 HMAC Authentication/Integrity Algorithm.
     * SHA512 HMAC Authentication/Integrity Algorithm.
     *
     *
     * <p>Keys for this algorithm must be 512 bits in length.
     * <p>Valid truncation lengths are multiples of 8 bits from 256 to (default) 512.
     * <p>Valid truncation lengths are multiples of 8 bits from 256 to (default) 512.
     */
     */
    public static final String AUTH_HMAC_SHA512 = "hmac(sha512)";
    public static final String AUTH_HMAC_SHA512 = "hmac(sha512)";
@@ -130,12 +138,10 @@ public final class IpSecAlgorithm implements Parcelable {
     * @param truncLenBits number of bits of output hash to use.
     * @param truncLenBits number of bits of output hash to use.
     */
     */
    public IpSecAlgorithm(@AlgorithmName String algorithm, @NonNull byte[] key, int truncLenBits) {
    public IpSecAlgorithm(@AlgorithmName String algorithm, @NonNull byte[] key, int truncLenBits) {
        if (!isTruncationLengthValid(algorithm, truncLenBits)) {
            throw new IllegalArgumentException("Unknown algorithm or invalid length");
        }
        mName = algorithm;
        mName = algorithm;
        mKey = key.clone();
        mKey = key.clone();
        mTruncLenBits = Math.min(truncLenBits, key.length * 8);
        mTruncLenBits = truncLenBits;
        checkValidOrThrow(mName, mKey.length * 8, mTruncLenBits);
    }
    }


    /** Get the algorithm name */
    /** Get the algorithm name */
@@ -169,7 +175,11 @@ public final class IpSecAlgorithm implements Parcelable {
    public static final Parcelable.Creator<IpSecAlgorithm> CREATOR =
    public static final Parcelable.Creator<IpSecAlgorithm> CREATOR =
            new Parcelable.Creator<IpSecAlgorithm>() {
            new Parcelable.Creator<IpSecAlgorithm>() {
                public IpSecAlgorithm createFromParcel(Parcel in) {
                public IpSecAlgorithm createFromParcel(Parcel in) {
                    return new IpSecAlgorithm(in);
                    final String name = in.readString();
                    final byte[] key = in.createByteArray();
                    final int truncLenBits = in.readInt();

                    return new IpSecAlgorithm(name, key, truncLenBits);
                }
                }


                public IpSecAlgorithm[] newArray(int size) {
                public IpSecAlgorithm[] newArray(int size) {
@@ -177,30 +187,47 @@ public final class IpSecAlgorithm implements Parcelable {
                }
                }
            };
            };


    private IpSecAlgorithm(Parcel in) {
    private static void checkValidOrThrow(String name, int keyLen, int truncLen) {
        mName = in.readString();
        boolean isValidLen = true;
        mKey = in.createByteArray();
        boolean isValidTruncLen = true;
        mTruncLenBits = in.readInt();
    }


    private static boolean isTruncationLengthValid(String algo, int truncLenBits) {
        switch(name) {
        switch (algo) {
            case CRYPT_AES_CBC:
            case CRYPT_AES_CBC:
                return (truncLenBits == 128 || truncLenBits == 192 || truncLenBits == 256);
                isValidLen = keyLen == 128 || keyLen == 192 || keyLen == 256;
                break;
            case AUTH_HMAC_MD5:
            case AUTH_HMAC_MD5:
                return (truncLenBits >= 96 && truncLenBits <= 128);
                isValidLen = keyLen == 128;
                isValidTruncLen = truncLen >= 96 && truncLen <= 128;
                break;
            case AUTH_HMAC_SHA1:
            case AUTH_HMAC_SHA1:
                return (truncLenBits >= 96 && truncLenBits <= 160);
                isValidLen = keyLen == 160;
                isValidTruncLen = truncLen >= 96 && truncLen <= 160;
                break;
            case AUTH_HMAC_SHA256:
            case AUTH_HMAC_SHA256:
                return (truncLenBits >= 96 && truncLenBits <= 256);
                isValidLen = keyLen == 256;
                isValidTruncLen = truncLen >= 96 && truncLen <= 256;
                break;
            case AUTH_HMAC_SHA384:
            case AUTH_HMAC_SHA384:
                return (truncLenBits >= 192 && truncLenBits <= 384);
                isValidLen = keyLen == 384;
                isValidTruncLen = truncLen >= 192 && truncLen <= 384;
                break;
            case AUTH_HMAC_SHA512:
            case AUTH_HMAC_SHA512:
                return (truncLenBits >= 256 && truncLenBits <= 512);
                isValidLen = keyLen == 512;
                isValidTruncLen = truncLen >= 256 && truncLen <= 512;
                break;
            case AUTH_CRYPT_AES_GCM:
            case AUTH_CRYPT_AES_GCM:
                return (truncLenBits == 64 || truncLenBits == 96 || truncLenBits == 128);
                // The keying material for GCM is a key plus a 32-bit salt
                isValidLen = keyLen == 128 + 32 || keyLen == 192 + 32 || keyLen == 256 + 32;
                break;
            default:
            default:
                return false;
                throw new IllegalArgumentException("Couldn't find an algorithm: " + name);
        }

        if (!isValidLen) {
            throw new IllegalArgumentException("Invalid key material keyLength: " + keyLen);
        }
        if (!isValidTruncLen) {
            throw new IllegalArgumentException("Invalid truncation keyLength: " + truncLen);
        }
        }
    }
    }


@@ -217,8 +244,9 @@ public final class IpSecAlgorithm implements Parcelable {
                .toString();
                .toString();
    }
    }


    /** package */
    /** @hide */
    static boolean equals(IpSecAlgorithm lhs, IpSecAlgorithm rhs) {
    @VisibleForTesting
    public static boolean equals(IpSecAlgorithm lhs, IpSecAlgorithm rhs) {
        if (lhs == null || rhs == null) return (lhs == rhs);
        if (lhs == null || rhs == null) return (lhs == rhs);
        return (lhs.mName.equals(rhs.mName)
        return (lhs.mName.equals(rhs.mName)
                && Arrays.equals(lhs.mKey, rhs.mKey)
                && Arrays.equals(lhs.mKey, rhs.mKey)
+115 −0
Original line number Original line Diff line number Diff line
/*
 * Copyright (C) 2017 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;

import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;

import android.os.Parcel;
import android.support.test.filters.SmallTest;
import android.support.test.runner.AndroidJUnit4;
import java.util.Arrays;
import java.util.Random;
import org.junit.Test;
import org.junit.runner.RunWith;

/** Unit tests for {@link IpSecAlgorithm}. */
@SmallTest
@RunWith(AndroidJUnit4.class)
public class IpSecAlgorithmTest {

    private static final byte[] KEY_MATERIAL;

    static {
        KEY_MATERIAL = new byte[128];
        new Random().nextBytes(KEY_MATERIAL);
    };

    @Test
    public void testDefaultTruncLen() throws Exception {
        IpSecAlgorithm explicit =
                new IpSecAlgorithm(
                        IpSecAlgorithm.AUTH_HMAC_SHA256, Arrays.copyOf(KEY_MATERIAL, 256 / 8), 256);
        IpSecAlgorithm implicit =
                new IpSecAlgorithm(
                        IpSecAlgorithm.AUTH_HMAC_SHA256, Arrays.copyOf(KEY_MATERIAL, 256 / 8));
        assertTrue(
                "Default Truncation Length Incorrect, Explicit: "
                        + explicit
                        + "implicit: "
                        + implicit,
                IpSecAlgorithm.equals(explicit, implicit));
    }

    @Test
    public void testTruncLenValidation() throws Exception {
        for (int truncLen : new int[] {256, 512}) {
            new IpSecAlgorithm(
                    IpSecAlgorithm.AUTH_HMAC_SHA512,
                    Arrays.copyOf(KEY_MATERIAL, 512 / 8),
                    truncLen);
        }

        for (int truncLen : new int[] {255, 513}) {
            try {
                new IpSecAlgorithm(
                        IpSecAlgorithm.AUTH_HMAC_SHA512,
                        Arrays.copyOf(KEY_MATERIAL, 512 / 8),
                        truncLen);
                fail("Invalid truncation length not validated");
            } catch (IllegalArgumentException pass) {
            }
        }
    }

    @Test
    public void testLenValidation() throws Exception {
        for (int len : new int[] {128, 192, 256}) {
            new IpSecAlgorithm(IpSecAlgorithm.CRYPT_AES_CBC, Arrays.copyOf(KEY_MATERIAL, len / 8));
        }
        try {
            new IpSecAlgorithm(IpSecAlgorithm.CRYPT_AES_CBC, Arrays.copyOf(KEY_MATERIAL, 384 / 8));
            fail("Invalid key length not validated");
        } catch (IllegalArgumentException pass) {
        }
    }

    @Test
    public void testAlgoNameValidation() throws Exception {
        try {
            new IpSecAlgorithm("rot13", Arrays.copyOf(KEY_MATERIAL, 128 / 8));
            fail("Invalid algorithm name not validated");
        } catch (IllegalArgumentException pass) {
        }
    }

    @Test
    public void testParcelUnparcel() throws Exception {
        IpSecAlgorithm init =
                new IpSecAlgorithm(
                        IpSecAlgorithm.AUTH_HMAC_SHA512, Arrays.copyOf(KEY_MATERIAL, 512 / 8), 256);

        Parcel p = Parcel.obtain();
        p.setDataPosition(0);
        init.writeToParcel(p, 0);

        p.setDataPosition(0);
        IpSecAlgorithm fin = IpSecAlgorithm.CREATOR.createFromParcel(p);
        assertTrue("Parcel/Unparcel failed!", IpSecAlgorithm.equals(init, fin));
        p.recycle();
    }
}
+2 −2
Original line number Original line Diff line number Diff line
@@ -71,7 +71,7 @@ public class IpSecConfigTest {
        c.setAuthentication(
        c.setAuthentication(
                IpSecTransform.DIRECTION_OUT,
                IpSecTransform.DIRECTION_OUT,
                new IpSecAlgorithm(
                new IpSecAlgorithm(
                        IpSecAlgorithm.AUTH_HMAC_SHA1,
                        IpSecAlgorithm.AUTH_HMAC_MD5,
                        new byte[] {1, 2, 3, 4, 5, 6, 7, 8, 9, 0xA, 0xB, 0xC, 0xD, 0xE, 0xF, 0}));
                        new byte[] {1, 2, 3, 4, 5, 6, 7, 8, 9, 0xA, 0xB, 0xC, 0xD, 0xE, 0xF, 0}));
        c.setSpiResourceId(IpSecTransform.DIRECTION_OUT, 1984);
        c.setSpiResourceId(IpSecTransform.DIRECTION_OUT, 1984);
        c.setEncryption(
        c.setEncryption(
@@ -82,7 +82,7 @@ public class IpSecConfigTest {
        c.setAuthentication(
        c.setAuthentication(
                IpSecTransform.DIRECTION_IN,
                IpSecTransform.DIRECTION_IN,
                new IpSecAlgorithm(
                new IpSecAlgorithm(
                        IpSecAlgorithm.AUTH_HMAC_SHA1,
                        IpSecAlgorithm.AUTH_HMAC_MD5,
                        new byte[] {1, 2, 3, 4, 5, 6, 7, 8, 9, 0xA, 0xB, 0xC, 0xD, 0xE, 0xF, 1}));
                        new byte[] {1, 2, 3, 4, 5, 6, 7, 8, 9, 0xA, 0xB, 0xC, 0xD, 0xE, 0xF, 1}));
        c.setSpiResourceId(IpSecTransform.DIRECTION_IN, 99);
        c.setSpiResourceId(IpSecTransform.DIRECTION_IN, 99);
        assertParcelingIsLossless(c);
        assertParcelingIsLossless(c);