Merge changes from topic "new-ipsec-api" am: a80fb3bbe6
Original change: https://android-review.googlesource.com/c/platform/frameworks/base/+/1398433 Change-Id: I074e1cc2d9b8e38d242c4a1c9b2176d3b8338774
This commit is contained in:
@@ -30051,9 +30051,12 @@ package android.net {
|
|||||||
method public int describeContents();
|
method public int describeContents();
|
||||||
method @NonNull public byte[] getKey();
|
method @NonNull public byte[] getKey();
|
||||||
method @NonNull public String getName();
|
method @NonNull public String getName();
|
||||||
|
method @NonNull public static java.util.Set<java.lang.String> getSupportedAlgorithms();
|
||||||
method public int getTruncationLengthBits();
|
method public int getTruncationLengthBits();
|
||||||
method public void writeToParcel(android.os.Parcel, int);
|
method public void writeToParcel(android.os.Parcel, int);
|
||||||
|
field public static final String AUTH_AES_XCBC = "xcbc(aes)";
|
||||||
field public static final String AUTH_CRYPT_AES_GCM = "rfc4106(gcm(aes))";
|
field public static final String AUTH_CRYPT_AES_GCM = "rfc4106(gcm(aes))";
|
||||||
|
field public static final String AUTH_CRYPT_CHACHA20_POLY1305 = "rfc7539esp(chacha20,poly1305)";
|
||||||
field public static final String AUTH_HMAC_MD5 = "hmac(md5)";
|
field public static final String AUTH_HMAC_MD5 = "hmac(md5)";
|
||||||
field public static final String AUTH_HMAC_SHA1 = "hmac(sha1)";
|
field public static final String AUTH_HMAC_SHA1 = "hmac(sha1)";
|
||||||
field public static final String AUTH_HMAC_SHA256 = "hmac(sha256)";
|
field public static final String AUTH_HMAC_SHA256 = "hmac(sha256)";
|
||||||
@@ -30061,6 +30064,7 @@ package android.net {
|
|||||||
field public static final String AUTH_HMAC_SHA512 = "hmac(sha512)";
|
field public static final String AUTH_HMAC_SHA512 = "hmac(sha512)";
|
||||||
field @NonNull public static final android.os.Parcelable.Creator<android.net.IpSecAlgorithm> CREATOR;
|
field @NonNull public static final android.os.Parcelable.Creator<android.net.IpSecAlgorithm> CREATOR;
|
||||||
field public static final String CRYPT_AES_CBC = "cbc(aes)";
|
field public static final String CRYPT_AES_CBC = "cbc(aes)";
|
||||||
|
field public static final String CRYPT_AES_CTR = "rfc3686(ctr(aes))";
|
||||||
}
|
}
|
||||||
|
|
||||||
public final class IpSecManager {
|
public final class IpSecManager {
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ package android.net;
|
|||||||
|
|
||||||
import android.annotation.NonNull;
|
import android.annotation.NonNull;
|
||||||
import android.annotation.StringDef;
|
import android.annotation.StringDef;
|
||||||
|
import android.content.res.Resources;
|
||||||
import android.os.Build;
|
import android.os.Build;
|
||||||
import android.os.Parcel;
|
import android.os.Parcel;
|
||||||
import android.os.Parcelable;
|
import android.os.Parcelable;
|
||||||
@@ -27,6 +28,12 @@ import com.android.internal.util.HexDump;
|
|||||||
import java.lang.annotation.Retention;
|
import java.lang.annotation.Retention;
|
||||||
import java.lang.annotation.RetentionPolicy;
|
import java.lang.annotation.RetentionPolicy;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Map.Entry;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This class represents a single algorithm that can be used by an {@link IpSecTransform}.
|
* This class represents a single algorithm that can be used by an {@link IpSecTransform}.
|
||||||
@@ -51,6 +58,27 @@ public final class IpSecAlgorithm implements Parcelable {
|
|||||||
*/
|
*/
|
||||||
public static final String CRYPT_AES_CBC = "cbc(aes)";
|
public static final String CRYPT_AES_CBC = "cbc(aes)";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* AES-CTR Encryption/Ciphering Algorithm.
|
||||||
|
*
|
||||||
|
* <p>Valid lengths for keying material are {160, 224, 288}.
|
||||||
|
*
|
||||||
|
* <p>As per <a href="https://tools.ietf.org/html/rfc3686#section-5.1">RFC3686 (Section
|
||||||
|
* 5.1)</a>, keying material consists of a 128, 192, or 256 bit AES key followed by a 32-bit
|
||||||
|
* nonce. RFC compliance requires that the nonce must be unique per security association.
|
||||||
|
*
|
||||||
|
* <p>This algorithm may be available on the device. Caller MUST check if it is supported before
|
||||||
|
* using it by calling {@link #getSupportedAlgorithms()} and checking if this algorithm is
|
||||||
|
* included in the returned algorithm set. The returned algorithm set will not change unless the
|
||||||
|
* device is rebooted. {@link IllegalArgumentException} will be thrown if this algorithm is
|
||||||
|
* requested on an unsupported device.
|
||||||
|
*
|
||||||
|
* <p>@see {@link #getSupportedAlgorithms()}
|
||||||
|
*/
|
||||||
|
// This algorithm may be available on devices released before Android 12, and is guaranteed
|
||||||
|
// to be available on devices first shipped with Android 12 or later.
|
||||||
|
public static final String CRYPT_AES_CTR = "rfc3686(ctr(aes))";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 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>
|
||||||
@@ -98,6 +126,25 @@ public final class IpSecAlgorithm implements Parcelable {
|
|||||||
*/
|
*/
|
||||||
public static final String AUTH_HMAC_SHA512 = "hmac(sha512)";
|
public static final String AUTH_HMAC_SHA512 = "hmac(sha512)";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* AES-XCBC Authentication/Integrity Algorithm.
|
||||||
|
*
|
||||||
|
* <p>Keys for this algorithm must be 128 bits in length.
|
||||||
|
*
|
||||||
|
* <p>The only valid truncation length is 96 bits.
|
||||||
|
*
|
||||||
|
* <p>This algorithm may be available on the device. Caller MUST check if it is supported before
|
||||||
|
* using it by calling {@link #getSupportedAlgorithms()} and checking if this algorithm is
|
||||||
|
* included in the returned algorithm set. The returned algorithm set will not change unless the
|
||||||
|
* device is rebooted. {@link IllegalArgumentException} will be thrown if this algorithm is
|
||||||
|
* requested on an unsupported device.
|
||||||
|
*
|
||||||
|
* <p>@see {@link #getSupportedAlgorithms()}
|
||||||
|
*/
|
||||||
|
// This algorithm may be available on devices released before Android 12, and is guaranteed
|
||||||
|
// to be available on devices first shipped with Android 12 or later.
|
||||||
|
public static final String AUTH_AES_XCBC = "xcbc(aes)";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* AES-GCM Authentication/Integrity + Encryption/Ciphering Algorithm.
|
* AES-GCM Authentication/Integrity + Encryption/Ciphering Algorithm.
|
||||||
*
|
*
|
||||||
@@ -111,19 +158,67 @@ public final class IpSecAlgorithm implements Parcelable {
|
|||||||
*/
|
*/
|
||||||
public static final String AUTH_CRYPT_AES_GCM = "rfc4106(gcm(aes))";
|
public static final String AUTH_CRYPT_AES_GCM = "rfc4106(gcm(aes))";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ChaCha20-Poly1305 Authentication/Integrity + Encryption/Ciphering Algorithm.
|
||||||
|
*
|
||||||
|
* <p>Keys for this algorithm must be 288 bits in length.
|
||||||
|
*
|
||||||
|
* <p>As per <a href="https://tools.ietf.org/html/rfc7634#section-2">RFC7634 (Section 2)</a>,
|
||||||
|
* keying material consists of a 256 bit key followed by a 32-bit salt. The salt is fixed per
|
||||||
|
* security association.
|
||||||
|
*
|
||||||
|
* <p>The only valid ICV (truncation) length is 128 bits.
|
||||||
|
*
|
||||||
|
* <p>This algorithm may be available on the device. Caller MUST check if it is supported before
|
||||||
|
* using it by calling {@link #getSupportedAlgorithms()} and checking if this algorithm is
|
||||||
|
* included in the returned algorithm set. The returned algorithm set will not change unless the
|
||||||
|
* device is rebooted. {@link IllegalArgumentException} will be thrown if this algorithm is
|
||||||
|
* requested on an unsupported device.
|
||||||
|
*
|
||||||
|
* <p>@see {@link #getSupportedAlgorithms()}
|
||||||
|
*/
|
||||||
|
// This algorithm may be available on devices released before Android 12, and is guaranteed
|
||||||
|
// to be available on devices first shipped with Android 12 or later.
|
||||||
|
public static final String AUTH_CRYPT_CHACHA20_POLY1305 = "rfc7539esp(chacha20,poly1305)";
|
||||||
|
|
||||||
/** @hide */
|
/** @hide */
|
||||||
@StringDef({
|
@StringDef({
|
||||||
CRYPT_AES_CBC,
|
CRYPT_AES_CBC,
|
||||||
|
CRYPT_AES_CTR,
|
||||||
AUTH_HMAC_MD5,
|
AUTH_HMAC_MD5,
|
||||||
AUTH_HMAC_SHA1,
|
AUTH_HMAC_SHA1,
|
||||||
AUTH_HMAC_SHA256,
|
AUTH_HMAC_SHA256,
|
||||||
AUTH_HMAC_SHA384,
|
AUTH_HMAC_SHA384,
|
||||||
AUTH_HMAC_SHA512,
|
AUTH_HMAC_SHA512,
|
||||||
AUTH_CRYPT_AES_GCM
|
AUTH_AES_XCBC,
|
||||||
|
AUTH_CRYPT_AES_GCM,
|
||||||
|
AUTH_CRYPT_CHACHA20_POLY1305
|
||||||
})
|
})
|
||||||
@Retention(RetentionPolicy.SOURCE)
|
@Retention(RetentionPolicy.SOURCE)
|
||||||
public @interface AlgorithmName {}
|
public @interface AlgorithmName {}
|
||||||
|
|
||||||
|
/** @hide */
|
||||||
|
@VisibleForTesting
|
||||||
|
public static final Map<String, Integer> ALGO_TO_REQUIRED_FIRST_SDK = new HashMap<>();
|
||||||
|
|
||||||
|
static {
|
||||||
|
ALGO_TO_REQUIRED_FIRST_SDK.put(CRYPT_AES_CBC, Build.VERSION_CODES.P);
|
||||||
|
ALGO_TO_REQUIRED_FIRST_SDK.put(AUTH_HMAC_MD5, Build.VERSION_CODES.P);
|
||||||
|
ALGO_TO_REQUIRED_FIRST_SDK.put(AUTH_HMAC_SHA1, Build.VERSION_CODES.P);
|
||||||
|
ALGO_TO_REQUIRED_FIRST_SDK.put(AUTH_HMAC_SHA256, Build.VERSION_CODES.P);
|
||||||
|
ALGO_TO_REQUIRED_FIRST_SDK.put(AUTH_HMAC_SHA384, Build.VERSION_CODES.P);
|
||||||
|
ALGO_TO_REQUIRED_FIRST_SDK.put(AUTH_HMAC_SHA512, Build.VERSION_CODES.P);
|
||||||
|
ALGO_TO_REQUIRED_FIRST_SDK.put(AUTH_CRYPT_AES_GCM, Build.VERSION_CODES.P);
|
||||||
|
|
||||||
|
// STOPSHIP: b/170424293 Use Build.VERSION_CODES.S when it is defined
|
||||||
|
ALGO_TO_REQUIRED_FIRST_SDK.put(CRYPT_AES_CTR, Build.VERSION_CODES.R + 1);
|
||||||
|
ALGO_TO_REQUIRED_FIRST_SDK.put(AUTH_AES_XCBC, Build.VERSION_CODES.R + 1);
|
||||||
|
ALGO_TO_REQUIRED_FIRST_SDK.put(AUTH_CRYPT_CHACHA20_POLY1305, Build.VERSION_CODES.R + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static final Set<String> ENABLED_ALGOS =
|
||||||
|
Collections.unmodifiableSet(loadAlgos(Resources.getSystem()));
|
||||||
|
|
||||||
private final String mName;
|
private final String mName;
|
||||||
private final byte[] mKey;
|
private final byte[] mKey;
|
||||||
private final int mTruncLenBits;
|
private final int mTruncLenBits;
|
||||||
@@ -137,6 +232,7 @@ public final class IpSecAlgorithm implements Parcelable {
|
|||||||
*
|
*
|
||||||
* @param algorithm name of the algorithm.
|
* @param algorithm name of the algorithm.
|
||||||
* @param key key padded to a multiple of 8 bits.
|
* @param key key padded to a multiple of 8 bits.
|
||||||
|
* @throws IllegalArgumentException if algorithm or key length is invalid.
|
||||||
*/
|
*/
|
||||||
public IpSecAlgorithm(@NonNull @AlgorithmName String algorithm, @NonNull byte[] key) {
|
public IpSecAlgorithm(@NonNull @AlgorithmName String algorithm, @NonNull byte[] key) {
|
||||||
this(algorithm, key, 0);
|
this(algorithm, key, 0);
|
||||||
@@ -152,6 +248,7 @@ public final class IpSecAlgorithm implements Parcelable {
|
|||||||
* @param algorithm name of the algorithm.
|
* @param algorithm name of the algorithm.
|
||||||
* @param key key padded to a multiple of 8 bits.
|
* @param key key padded to a multiple of 8 bits.
|
||||||
* @param truncLenBits number of bits of output hash to use.
|
* @param truncLenBits number of bits of output hash to use.
|
||||||
|
* @throws IllegalArgumentException if algorithm, key length or truncation length is invalid.
|
||||||
*/
|
*/
|
||||||
public IpSecAlgorithm(
|
public IpSecAlgorithm(
|
||||||
@NonNull @AlgorithmName String algorithm, @NonNull byte[] key, int truncLenBits) {
|
@NonNull @AlgorithmName String algorithm, @NonNull byte[] key, int truncLenBits) {
|
||||||
@@ -206,13 +303,59 @@ public final class IpSecAlgorithm implements Parcelable {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
private static void checkValidOrThrow(String name, int keyLen, int truncLen) {
|
/**
|
||||||
boolean isValidLen = true;
|
* Returns supported IPsec algorithms for the current device.
|
||||||
boolean isValidTruncLen = true;
|
*
|
||||||
|
* <p>Some algorithms may not be supported on old devices. Callers MUST check if an algorithm is
|
||||||
|
* supported before using it.
|
||||||
|
*/
|
||||||
|
@NonNull
|
||||||
|
public static Set<String> getSupportedAlgorithms() {
|
||||||
|
return ENABLED_ALGOS;
|
||||||
|
}
|
||||||
|
|
||||||
switch(name) {
|
/** @hide */
|
||||||
|
@VisibleForTesting
|
||||||
|
public static Set<String> loadAlgos(Resources systemResources) {
|
||||||
|
final Set<String> enabledAlgos = new HashSet<>();
|
||||||
|
|
||||||
|
// Load and validate the optional algorithm resource. Undefined or duplicate algorithms in
|
||||||
|
// the resource are not allowed.
|
||||||
|
final String[] resourceAlgos = systemResources.getStringArray(
|
||||||
|
com.android.internal.R.array.config_optionalIpSecAlgorithms);
|
||||||
|
for (String str : resourceAlgos) {
|
||||||
|
if (!ALGO_TO_REQUIRED_FIRST_SDK.containsKey(str) || !enabledAlgos.add(str)) {
|
||||||
|
// This error should be caught by CTS and never be thrown to API callers
|
||||||
|
throw new IllegalArgumentException("Invalid or repeated algorithm " + str);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (Entry<String, Integer> entry : ALGO_TO_REQUIRED_FIRST_SDK.entrySet()) {
|
||||||
|
if (Build.VERSION.FIRST_SDK_INT >= entry.getValue()) {
|
||||||
|
enabledAlgos.add(entry.getKey());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return enabledAlgos;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void checkValidOrThrow(String name, int keyLen, int truncLen) {
|
||||||
|
final boolean isValidLen;
|
||||||
|
final boolean isValidTruncLen;
|
||||||
|
|
||||||
|
if (!getSupportedAlgorithms().contains(name)) {
|
||||||
|
throw new IllegalArgumentException("Unsupported algorithm: " + name);
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (name) {
|
||||||
case CRYPT_AES_CBC:
|
case CRYPT_AES_CBC:
|
||||||
isValidLen = keyLen == 128 || keyLen == 192 || keyLen == 256;
|
isValidLen = keyLen == 128 || keyLen == 192 || keyLen == 256;
|
||||||
|
isValidTruncLen = true;
|
||||||
|
break;
|
||||||
|
case CRYPT_AES_CTR:
|
||||||
|
// The keying material for AES-CTR is a key plus a 32-bit salt
|
||||||
|
isValidLen = keyLen == 128 + 32 || keyLen == 192 + 32 || keyLen == 256 + 32;
|
||||||
|
isValidTruncLen = true;
|
||||||
break;
|
break;
|
||||||
case AUTH_HMAC_MD5:
|
case AUTH_HMAC_MD5:
|
||||||
isValidLen = keyLen == 128;
|
isValidLen = keyLen == 128;
|
||||||
@@ -234,12 +377,22 @@ public final class IpSecAlgorithm implements Parcelable {
|
|||||||
isValidLen = keyLen == 512;
|
isValidLen = keyLen == 512;
|
||||||
isValidTruncLen = truncLen >= 256 && truncLen <= 512;
|
isValidTruncLen = truncLen >= 256 && truncLen <= 512;
|
||||||
break;
|
break;
|
||||||
|
case AUTH_AES_XCBC:
|
||||||
|
isValidLen = keyLen == 128;
|
||||||
|
isValidTruncLen = truncLen == 96;
|
||||||
|
break;
|
||||||
case AUTH_CRYPT_AES_GCM:
|
case AUTH_CRYPT_AES_GCM:
|
||||||
// The keying material for GCM is a key plus a 32-bit salt
|
// The keying material for GCM is a key plus a 32-bit salt
|
||||||
isValidLen = keyLen == 128 + 32 || keyLen == 192 + 32 || keyLen == 256 + 32;
|
isValidLen = keyLen == 128 + 32 || keyLen == 192 + 32 || keyLen == 256 + 32;
|
||||||
isValidTruncLen = truncLen == 64 || truncLen == 96 || truncLen == 128;
|
isValidTruncLen = truncLen == 64 || truncLen == 96 || truncLen == 128;
|
||||||
break;
|
break;
|
||||||
|
case AUTH_CRYPT_CHACHA20_POLY1305:
|
||||||
|
// The keying material for ChaCha20Poly1305 is a key plus a 32-bit salt
|
||||||
|
isValidLen = keyLen == 256 + 32;
|
||||||
|
isValidTruncLen = truncLen == 128;
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
|
// Should never hit here.
|
||||||
throw new IllegalArgumentException("Couldn't find an algorithm: " + name);
|
throw new IllegalArgumentException("Couldn't find an algorithm: " + name);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -260,6 +413,7 @@ public final class IpSecAlgorithm implements Parcelable {
|
|||||||
case AUTH_HMAC_SHA256:
|
case AUTH_HMAC_SHA256:
|
||||||
case AUTH_HMAC_SHA384:
|
case AUTH_HMAC_SHA384:
|
||||||
case AUTH_HMAC_SHA512:
|
case AUTH_HMAC_SHA512:
|
||||||
|
case AUTH_AES_XCBC:
|
||||||
return true;
|
return true;
|
||||||
default:
|
default:
|
||||||
return false;
|
return false;
|
||||||
@@ -268,12 +422,24 @@ public final class IpSecAlgorithm implements Parcelable {
|
|||||||
|
|
||||||
/** @hide */
|
/** @hide */
|
||||||
public boolean isEncryption() {
|
public boolean isEncryption() {
|
||||||
return getName().equals(CRYPT_AES_CBC);
|
switch (getName()) {
|
||||||
|
case CRYPT_AES_CBC: // fallthrough
|
||||||
|
case CRYPT_AES_CTR:
|
||||||
|
return true;
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @hide */
|
/** @hide */
|
||||||
public boolean isAead() {
|
public boolean isAead() {
|
||||||
return getName().equals(AUTH_CRYPT_AES_GCM);
|
switch (getName()) {
|
||||||
|
case AUTH_CRYPT_AES_GCM: // fallthrough
|
||||||
|
case AUTH_CRYPT_CHACHA20_POLY1305:
|
||||||
|
return true;
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Because encryption keys are sensitive and userdebug builds are used by large user pools
|
// Because encryption keys are sensitive and userdebug builds are used by large user pools
|
||||||
|
|||||||
@@ -1663,6 +1663,21 @@
|
|||||||
-->
|
-->
|
||||||
</string-array>
|
</string-array>
|
||||||
|
|
||||||
|
<!-- Optional IPsec algorithms enabled by this device, defaulting to empty. OEMs can override
|
||||||
|
it by providing a list of algorithm names in an overlay config.xml file.
|
||||||
|
|
||||||
|
As Android releases new versions, more algorithms are becoming mandatory. Mandatory
|
||||||
|
algorithms will be automatically enabled on the device. Optional algorithms need
|
||||||
|
to be explicitly declared in this resource to be enabled.
|
||||||
|
* SDK level 28 makes the following algorithms mandatory : "cbc(aes)", "hmac(md5)",
|
||||||
|
"hmac(sha1)", "hmac(sha256)", "hmac(sha384)", "hmac(sha512)", "rfc4106(gcm(aes))"
|
||||||
|
* SDK level 30 makes the following algorithms mandatory : "rfc3686(ctr(aes))",
|
||||||
|
"xcbc(aes)", "rfc7539esp(chacha20,poly1305)"
|
||||||
|
-->
|
||||||
|
<string-array name="config_optionalIpSecAlgorithms" translatable="false">
|
||||||
|
<!-- Add algorithm here -->
|
||||||
|
</string-array>
|
||||||
|
|
||||||
<!-- Boolean indicating if current platform supports bluetooth SCO for off call
|
<!-- Boolean indicating if current platform supports bluetooth SCO for off call
|
||||||
use cases -->
|
use cases -->
|
||||||
<bool name="config_bluetooth_sco_off_call">true</bool>
|
<bool name="config_bluetooth_sco_off_call">true</bool>
|
||||||
|
|||||||
@@ -3186,6 +3186,9 @@
|
|||||||
<!-- Network Recommendation -->
|
<!-- Network Recommendation -->
|
||||||
<java-symbol type="string" name="config_defaultNetworkRecommendationProviderPackage" />
|
<java-symbol type="string" name="config_defaultNetworkRecommendationProviderPackage" />
|
||||||
|
|
||||||
|
<!-- Optional IPsec algorithms -->
|
||||||
|
<java-symbol type="array" name="config_optionalIpSecAlgorithms" />
|
||||||
|
|
||||||
<!-- Whether allow 3rd party apps on internal storage. -->
|
<!-- Whether allow 3rd party apps on internal storage. -->
|
||||||
<java-symbol type="bool" name="config_allow3rdPartyAppOnInternal" />
|
<java-symbol type="bool" name="config_allow3rdPartyAppOnInternal" />
|
||||||
|
|
||||||
|
|||||||
@@ -29830,9 +29830,12 @@ package android.net {
|
|||||||
method public int describeContents();
|
method public int describeContents();
|
||||||
method @NonNull public byte[] getKey();
|
method @NonNull public byte[] getKey();
|
||||||
method @NonNull public String getName();
|
method @NonNull public String getName();
|
||||||
|
method @NonNull public static java.util.Set<java.lang.String> getSupportedAlgorithms();
|
||||||
method public int getTruncationLengthBits();
|
method public int getTruncationLengthBits();
|
||||||
method public void writeToParcel(android.os.Parcel, int);
|
method public void writeToParcel(android.os.Parcel, int);
|
||||||
|
field public static final String AUTH_AES_XCBC = "xcbc(aes)";
|
||||||
field public static final String AUTH_CRYPT_AES_GCM = "rfc4106(gcm(aes))";
|
field public static final String AUTH_CRYPT_AES_GCM = "rfc4106(gcm(aes))";
|
||||||
|
field public static final String AUTH_CRYPT_CHACHA20_POLY1305 = "rfc7539esp(chacha20,poly1305)";
|
||||||
field public static final String AUTH_HMAC_MD5 = "hmac(md5)";
|
field public static final String AUTH_HMAC_MD5 = "hmac(md5)";
|
||||||
field public static final String AUTH_HMAC_SHA1 = "hmac(sha1)";
|
field public static final String AUTH_HMAC_SHA1 = "hmac(sha1)";
|
||||||
field public static final String AUTH_HMAC_SHA256 = "hmac(sha256)";
|
field public static final String AUTH_HMAC_SHA256 = "hmac(sha256)";
|
||||||
@@ -29840,6 +29843,7 @@ package android.net {
|
|||||||
field public static final String AUTH_HMAC_SHA512 = "hmac(sha512)";
|
field public static final String AUTH_HMAC_SHA512 = "hmac(sha512)";
|
||||||
field @NonNull public static final android.os.Parcelable.Creator<android.net.IpSecAlgorithm> CREATOR;
|
field @NonNull public static final android.os.Parcelable.Creator<android.net.IpSecAlgorithm> CREATOR;
|
||||||
field public static final String CRYPT_AES_CBC = "cbc(aes)";
|
field public static final String CRYPT_AES_CBC = "cbc(aes)";
|
||||||
|
field public static final String CRYPT_AES_CTR = "rfc3686(ctr(aes))";
|
||||||
}
|
}
|
||||||
|
|
||||||
public final class IpSecManager {
|
public final class IpSecManager {
|
||||||
|
|||||||
@@ -16,34 +16,50 @@
|
|||||||
|
|
||||||
package android.net;
|
package android.net;
|
||||||
|
|
||||||
|
import static android.net.IpSecAlgorithm.ALGO_TO_REQUIRED_FIRST_SDK;
|
||||||
|
|
||||||
|
import static org.junit.Assert.assertEquals;
|
||||||
import static org.junit.Assert.assertTrue;
|
import static org.junit.Assert.assertTrue;
|
||||||
import static org.junit.Assert.fail;
|
import static org.junit.Assert.fail;
|
||||||
|
import static org.mockito.Mockito.doReturn;
|
||||||
|
import static org.mockito.Mockito.mock;
|
||||||
|
|
||||||
|
import android.content.res.Resources;
|
||||||
|
import android.os.Build;
|
||||||
import android.os.Parcel;
|
import android.os.Parcel;
|
||||||
|
|
||||||
import androidx.test.filters.SmallTest;
|
import androidx.test.filters.SmallTest;
|
||||||
import androidx.test.runner.AndroidJUnit4;
|
import androidx.test.runner.AndroidJUnit4;
|
||||||
|
|
||||||
|
import com.android.internal.util.CollectionUtils;
|
||||||
|
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.junit.runner.RunWith;
|
import org.junit.runner.RunWith;
|
||||||
|
|
||||||
import java.util.AbstractMap.SimpleEntry;
|
import java.util.AbstractMap.SimpleEntry;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
import java.util.HashSet;
|
||||||
import java.util.Map.Entry;
|
import java.util.Map.Entry;
|
||||||
import java.util.Random;
|
import java.util.Random;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
/** Unit tests for {@link IpSecAlgorithm}. */
|
/** Unit tests for {@link IpSecAlgorithm}. */
|
||||||
@SmallTest
|
@SmallTest
|
||||||
@RunWith(AndroidJUnit4.class)
|
@RunWith(AndroidJUnit4.class)
|
||||||
public class IpSecAlgorithmTest {
|
public class IpSecAlgorithmTest {
|
||||||
|
|
||||||
private static final byte[] KEY_MATERIAL;
|
private static final byte[] KEY_MATERIAL;
|
||||||
|
|
||||||
|
private final Resources mMockResources = mock(Resources.class);
|
||||||
|
|
||||||
static {
|
static {
|
||||||
KEY_MATERIAL = new byte[128];
|
KEY_MATERIAL = new byte[128];
|
||||||
new Random().nextBytes(KEY_MATERIAL);
|
new Random().nextBytes(KEY_MATERIAL);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
private static byte[] generateKey(int keyLenInBits) {
|
||||||
|
return Arrays.copyOf(KEY_MATERIAL, keyLenInBits / 8);
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testNoTruncLen() throws Exception {
|
public void testNoTruncLen() throws Exception {
|
||||||
Entry<String, Integer>[] authAndAeadList =
|
Entry<String, Integer>[] authAndAeadList =
|
||||||
@@ -53,7 +69,7 @@ public class IpSecAlgorithmTest {
|
|||||||
new SimpleEntry<>(IpSecAlgorithm.AUTH_HMAC_SHA256, 256),
|
new SimpleEntry<>(IpSecAlgorithm.AUTH_HMAC_SHA256, 256),
|
||||||
new SimpleEntry<>(IpSecAlgorithm.AUTH_HMAC_SHA384, 384),
|
new SimpleEntry<>(IpSecAlgorithm.AUTH_HMAC_SHA384, 384),
|
||||||
new SimpleEntry<>(IpSecAlgorithm.AUTH_HMAC_SHA512, 512),
|
new SimpleEntry<>(IpSecAlgorithm.AUTH_HMAC_SHA512, 512),
|
||||||
new SimpleEntry<>(IpSecAlgorithm.AUTH_CRYPT_AES_GCM, 224)
|
new SimpleEntry<>(IpSecAlgorithm.AUTH_CRYPT_AES_GCM, 224),
|
||||||
};
|
};
|
||||||
|
|
||||||
// Expect auth and aead algorithms to throw errors if trunclen is omitted.
|
// Expect auth and aead algorithms to throw errors if trunclen is omitted.
|
||||||
@@ -70,6 +86,52 @@ public class IpSecAlgorithmTest {
|
|||||||
new IpSecAlgorithm(IpSecAlgorithm.CRYPT_AES_CBC, Arrays.copyOf(KEY_MATERIAL, 256 / 8));
|
new IpSecAlgorithm(IpSecAlgorithm.CRYPT_AES_CBC, Arrays.copyOf(KEY_MATERIAL, 256 / 8));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void checkAuthKeyAndTruncLenValidation(String algoName, int keyLen, int truncLen)
|
||||||
|
throws Exception {
|
||||||
|
new IpSecAlgorithm(algoName, generateKey(keyLen), truncLen);
|
||||||
|
|
||||||
|
try {
|
||||||
|
new IpSecAlgorithm(algoName, generateKey(keyLen));
|
||||||
|
fail("Expected exception on unprovided auth trunclen");
|
||||||
|
} catch (IllegalArgumentException pass) {
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
new IpSecAlgorithm(algoName, generateKey(keyLen + 8), truncLen);
|
||||||
|
fail("Invalid key length not validated");
|
||||||
|
} catch (IllegalArgumentException pass) {
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
new IpSecAlgorithm(algoName, generateKey(keyLen), truncLen + 1);
|
||||||
|
fail("Invalid truncation length not validated");
|
||||||
|
} catch (IllegalArgumentException pass) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void checkCryptKeyLenValidation(String algoName, int keyLen) throws Exception {
|
||||||
|
new IpSecAlgorithm(algoName, generateKey(keyLen));
|
||||||
|
|
||||||
|
try {
|
||||||
|
new IpSecAlgorithm(algoName, generateKey(keyLen + 8));
|
||||||
|
fail("Invalid key length not validated");
|
||||||
|
} catch (IllegalArgumentException pass) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testValidationForAlgosAddedInS() throws Exception {
|
||||||
|
if (Build.VERSION.FIRST_SDK_INT <= Build.VERSION_CODES.R) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int len : new int[] {160, 224, 288}) {
|
||||||
|
checkCryptKeyLenValidation(IpSecAlgorithm.CRYPT_AES_CTR, len);
|
||||||
|
}
|
||||||
|
checkAuthKeyAndTruncLenValidation(IpSecAlgorithm.AUTH_AES_XCBC, 128, 96);
|
||||||
|
checkAuthKeyAndTruncLenValidation(IpSecAlgorithm.AUTH_CRYPT_CHACHA20_POLY1305, 288, 128);
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testTruncLenValidation() throws Exception {
|
public void testTruncLenValidation() throws Exception {
|
||||||
for (int truncLen : new int[] {256, 512}) {
|
for (int truncLen : new int[] {256, 512}) {
|
||||||
@@ -127,4 +189,37 @@ public class IpSecAlgorithmTest {
|
|||||||
assertTrue("Parcel/Unparcel failed!", IpSecAlgorithm.equals(init, fin));
|
assertTrue("Parcel/Unparcel failed!", IpSecAlgorithm.equals(init, fin));
|
||||||
p.recycle();
|
p.recycle();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static Set<String> getMandatoryAlgos() {
|
||||||
|
return CollectionUtils.filter(
|
||||||
|
ALGO_TO_REQUIRED_FIRST_SDK.keySet(),
|
||||||
|
i -> Build.VERSION.FIRST_SDK_INT >= ALGO_TO_REQUIRED_FIRST_SDK.get(i));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Set<String> getOptionalAlgos() {
|
||||||
|
return CollectionUtils.filter(
|
||||||
|
ALGO_TO_REQUIRED_FIRST_SDK.keySet(),
|
||||||
|
i -> Build.VERSION.FIRST_SDK_INT < ALGO_TO_REQUIRED_FIRST_SDK.get(i));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testGetSupportedAlgorithms() throws Exception {
|
||||||
|
assertTrue(IpSecAlgorithm.getSupportedAlgorithms().containsAll(getMandatoryAlgos()));
|
||||||
|
assertTrue(ALGO_TO_REQUIRED_FIRST_SDK.keySet().containsAll(
|
||||||
|
IpSecAlgorithm.getSupportedAlgorithms()));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testLoadAlgos() throws Exception {
|
||||||
|
final Set<String> optionalAlgoSet = getOptionalAlgos();
|
||||||
|
final String[] optionalAlgos = optionalAlgoSet.toArray(new String[0]);
|
||||||
|
|
||||||
|
doReturn(optionalAlgos).when(mMockResources)
|
||||||
|
.getStringArray(com.android.internal.R.array.config_optionalIpSecAlgorithms);
|
||||||
|
|
||||||
|
final Set<String> enabledAlgos = new HashSet<>(IpSecAlgorithm.loadAlgos(mMockResources));
|
||||||
|
final Set<String> expectedAlgos = ALGO_TO_REQUIRED_FIRST_SDK.keySet();
|
||||||
|
|
||||||
|
assertEquals(expectedAlgos, enabledAlgos);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user