Move IpSec associated files to f/b/packages/ConnectivityT
IpSecService is going to be moved into Connectivity mainline module.
Move all ipsec associated files to packages/ConnectivityT so that
it can be easily migrate these files to connectivity module after
clearing the hidden API usages.
Bug: 204153604
Test: build pass
FrameworksNetTests
CtsNetTestCases
Change-Id: I562b47f18e345988a2638cf886f86818f9144b91
This commit is contained in:
78
framework-t/src/android/net/IIpSecService.aidl
Normal file
78
framework-t/src/android/net/IIpSecService.aidl
Normal file
@@ -0,0 +1,78 @@
|
||||
/*
|
||||
** Copyright 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 android.net.LinkAddress;
|
||||
import android.net.Network;
|
||||
import android.net.IpSecConfig;
|
||||
import android.net.IpSecUdpEncapResponse;
|
||||
import android.net.IpSecSpiResponse;
|
||||
import android.net.IpSecTransformResponse;
|
||||
import android.net.IpSecTunnelInterfaceResponse;
|
||||
import android.os.Bundle;
|
||||
import android.os.IBinder;
|
||||
import android.os.ParcelFileDescriptor;
|
||||
|
||||
/**
|
||||
* @hide
|
||||
*/
|
||||
interface IIpSecService
|
||||
{
|
||||
IpSecSpiResponse allocateSecurityParameterIndex(
|
||||
in String destinationAddress, int requestedSpi, in IBinder binder);
|
||||
|
||||
void releaseSecurityParameterIndex(int resourceId);
|
||||
|
||||
IpSecUdpEncapResponse openUdpEncapsulationSocket(int port, in IBinder binder);
|
||||
|
||||
void closeUdpEncapsulationSocket(int resourceId);
|
||||
|
||||
IpSecTunnelInterfaceResponse createTunnelInterface(
|
||||
in String localAddr,
|
||||
in String remoteAddr,
|
||||
in Network underlyingNetwork,
|
||||
in IBinder binder,
|
||||
in String callingPackage);
|
||||
|
||||
void addAddressToTunnelInterface(
|
||||
int tunnelResourceId,
|
||||
in LinkAddress localAddr,
|
||||
in String callingPackage);
|
||||
|
||||
void removeAddressFromTunnelInterface(
|
||||
int tunnelResourceId,
|
||||
in LinkAddress localAddr,
|
||||
in String callingPackage);
|
||||
|
||||
void setNetworkForTunnelInterface(
|
||||
int tunnelResourceId, in Network underlyingNetwork, in String callingPackage);
|
||||
|
||||
void deleteTunnelInterface(int resourceId, in String callingPackage);
|
||||
|
||||
IpSecTransformResponse createTransform(
|
||||
in IpSecConfig c, in IBinder binder, in String callingPackage);
|
||||
|
||||
void deleteTransform(int transformId);
|
||||
|
||||
void applyTransportModeTransform(
|
||||
in ParcelFileDescriptor socket, int direction, int transformId);
|
||||
|
||||
void applyTunnelModeTransform(
|
||||
int tunnelResourceId, int direction, int transformResourceId, in String callingPackage);
|
||||
|
||||
void removeTransportModeTransforms(in ParcelFileDescriptor socket);
|
||||
}
|
||||
500
framework-t/src/android/net/IpSecAlgorithm.java
Normal file
500
framework-t/src/android/net/IpSecAlgorithm.java
Normal file
@@ -0,0 +1,500 @@
|
||||
/*
|
||||
* 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 android.annotation.NonNull;
|
||||
import android.annotation.StringDef;
|
||||
import android.content.res.Resources;
|
||||
import android.os.Build;
|
||||
import android.os.Parcel;
|
||||
import android.os.Parcelable;
|
||||
|
||||
import com.android.internal.annotations.VisibleForTesting;
|
||||
import com.android.internal.util.HexDump;
|
||||
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
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}.
|
||||
*
|
||||
* @see <a href="https://tools.ietf.org/html/rfc4301">RFC 4301, Security Architecture for the
|
||||
* Internet Protocol</a>
|
||||
*/
|
||||
public final class IpSecAlgorithm implements Parcelable {
|
||||
private static final String TAG = "IpSecAlgorithm";
|
||||
|
||||
/**
|
||||
* Null cipher.
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
public static final String CRYPT_NULL = "ecb(cipher_null)";
|
||||
|
||||
/**
|
||||
* AES-CBC Encryption/Ciphering Algorithm.
|
||||
*
|
||||
* <p>Valid lengths for this key are {128, 192, 256}.
|
||||
*/
|
||||
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
|
||||
* 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 128.
|
||||
*/
|
||||
public static final String AUTH_HMAC_MD5 = "hmac(md5)";
|
||||
|
||||
/**
|
||||
* 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>
|
||||
*
|
||||
* <p>Keys for this algorithm must be 160 bits in length.
|
||||
*
|
||||
* <p>Valid truncation lengths are multiples of 8 bits from 96 to 160.
|
||||
*/
|
||||
public static final String AUTH_HMAC_SHA1 = "hmac(sha1)";
|
||||
|
||||
/**
|
||||
* 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 256.
|
||||
*/
|
||||
public static final String AUTH_HMAC_SHA256 = "hmac(sha256)";
|
||||
|
||||
/**
|
||||
* 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 384.
|
||||
*/
|
||||
public static final String AUTH_HMAC_SHA384 = "hmac(sha384)";
|
||||
|
||||
/**
|
||||
* 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 512.
|
||||
*/
|
||||
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-CMAC 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_CMAC = "cmac(aes)";
|
||||
|
||||
/**
|
||||
* AES-GCM Authentication/Integrity + Encryption/Ciphering Algorithm.
|
||||
*
|
||||
* <p>Valid lengths for keying material are {160, 224, 288}.
|
||||
*
|
||||
* <p>As per <a href="https://tools.ietf.org/html/rfc4106#section-8.1">RFC4106 (Section
|
||||
* 8.1)</a>, keying material consists of a 128, 192, or 256 bit AES key followed by a 32-bit
|
||||
* salt. RFC compliance requires that the salt must be unique per invocation with the same key.
|
||||
*
|
||||
* <p>Valid ICV (truncation) lengths are {64, 96, 128}.
|
||||
*/
|
||||
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 */
|
||||
@StringDef({
|
||||
CRYPT_AES_CBC,
|
||||
CRYPT_AES_CTR,
|
||||
AUTH_HMAC_MD5,
|
||||
AUTH_HMAC_SHA1,
|
||||
AUTH_HMAC_SHA256,
|
||||
AUTH_HMAC_SHA384,
|
||||
AUTH_HMAC_SHA512,
|
||||
AUTH_AES_XCBC,
|
||||
AUTH_AES_CMAC,
|
||||
AUTH_CRYPT_AES_GCM,
|
||||
AUTH_CRYPT_CHACHA20_POLY1305
|
||||
})
|
||||
@Retention(RetentionPolicy.SOURCE)
|
||||
public @interface AlgorithmName {}
|
||||
|
||||
/** @hide */
|
||||
@VisibleForTesting
|
||||
public static final Map<String, Integer> ALGO_TO_REQUIRED_FIRST_SDK = new HashMap<>();
|
||||
|
||||
private static final int SDK_VERSION_ZERO = 0;
|
||||
|
||||
static {
|
||||
ALGO_TO_REQUIRED_FIRST_SDK.put(CRYPT_AES_CBC, SDK_VERSION_ZERO);
|
||||
ALGO_TO_REQUIRED_FIRST_SDK.put(AUTH_HMAC_MD5, SDK_VERSION_ZERO);
|
||||
ALGO_TO_REQUIRED_FIRST_SDK.put(AUTH_HMAC_SHA1, SDK_VERSION_ZERO);
|
||||
ALGO_TO_REQUIRED_FIRST_SDK.put(AUTH_HMAC_SHA256, SDK_VERSION_ZERO);
|
||||
ALGO_TO_REQUIRED_FIRST_SDK.put(AUTH_HMAC_SHA384, SDK_VERSION_ZERO);
|
||||
ALGO_TO_REQUIRED_FIRST_SDK.put(AUTH_HMAC_SHA512, SDK_VERSION_ZERO);
|
||||
ALGO_TO_REQUIRED_FIRST_SDK.put(AUTH_CRYPT_AES_GCM, SDK_VERSION_ZERO);
|
||||
|
||||
ALGO_TO_REQUIRED_FIRST_SDK.put(CRYPT_AES_CTR, Build.VERSION_CODES.S);
|
||||
ALGO_TO_REQUIRED_FIRST_SDK.put(AUTH_AES_XCBC, Build.VERSION_CODES.S);
|
||||
ALGO_TO_REQUIRED_FIRST_SDK.put(AUTH_AES_CMAC, Build.VERSION_CODES.S);
|
||||
ALGO_TO_REQUIRED_FIRST_SDK.put(AUTH_CRYPT_CHACHA20_POLY1305, Build.VERSION_CODES.S);
|
||||
}
|
||||
|
||||
private static final Set<String> ENABLED_ALGOS =
|
||||
Collections.unmodifiableSet(loadAlgos(Resources.getSystem()));
|
||||
|
||||
private final String mName;
|
||||
private final byte[] mKey;
|
||||
private final int mTruncLenBits;
|
||||
|
||||
/**
|
||||
* Creates an IpSecAlgorithm of one of the supported types. Supported algorithm names are
|
||||
* defined as constants in this class.
|
||||
*
|
||||
* <p>For algorithms that produce an integrity check value, the truncation length is a required
|
||||
* parameter. See {@link #IpSecAlgorithm(String algorithm, byte[] key, int truncLenBits)}
|
||||
*
|
||||
* @param algorithm name of the algorithm.
|
||||
* @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) {
|
||||
this(algorithm, key, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an IpSecAlgorithm of one of the supported types. Supported algorithm names are
|
||||
* defined as constants in this class.
|
||||
*
|
||||
* <p>This constructor only supports algorithms that use a truncation length. i.e.
|
||||
* Authentication and Authenticated Encryption algorithms.
|
||||
*
|
||||
* @param algorithm name of the algorithm.
|
||||
* @param key key padded to a multiple of 8 bits.
|
||||
* @param truncLenBits number of bits of output hash to use.
|
||||
* @throws IllegalArgumentException if algorithm, key length or truncation length is invalid.
|
||||
*/
|
||||
public IpSecAlgorithm(
|
||||
@NonNull @AlgorithmName String algorithm, @NonNull byte[] key, int truncLenBits) {
|
||||
mName = algorithm;
|
||||
mKey = key.clone();
|
||||
mTruncLenBits = truncLenBits;
|
||||
checkValidOrThrow(mName, mKey.length * 8, mTruncLenBits);
|
||||
}
|
||||
|
||||
/** Get the algorithm name */
|
||||
@NonNull
|
||||
public String getName() {
|
||||
return mName;
|
||||
}
|
||||
|
||||
/** Get the key for this algorithm */
|
||||
@NonNull
|
||||
public byte[] getKey() {
|
||||
return mKey.clone();
|
||||
}
|
||||
|
||||
/** Get the truncation length of this algorithm, in bits */
|
||||
public int getTruncationLengthBits() {
|
||||
return mTruncLenBits;
|
||||
}
|
||||
|
||||
/* Parcelable Implementation */
|
||||
public int describeContents() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** Write to parcel */
|
||||
public void writeToParcel(Parcel out, int flags) {
|
||||
out.writeString(mName);
|
||||
out.writeByteArray(mKey);
|
||||
out.writeInt(mTruncLenBits);
|
||||
}
|
||||
|
||||
/** Parcelable Creator */
|
||||
public static final @android.annotation.NonNull Parcelable.Creator<IpSecAlgorithm> CREATOR =
|
||||
new Parcelable.Creator<IpSecAlgorithm>() {
|
||||
public IpSecAlgorithm createFromParcel(Parcel 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) {
|
||||
return new IpSecAlgorithm[size];
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns supported IPsec algorithms for the current device.
|
||||
*
|
||||
* <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;
|
||||
}
|
||||
|
||||
/** @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.DEVICE_INITIAL_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:
|
||||
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;
|
||||
case AUTH_HMAC_MD5:
|
||||
isValidLen = keyLen == 128;
|
||||
isValidTruncLen = truncLen >= 96 && truncLen <= 128;
|
||||
break;
|
||||
case AUTH_HMAC_SHA1:
|
||||
isValidLen = keyLen == 160;
|
||||
isValidTruncLen = truncLen >= 96 && truncLen <= 160;
|
||||
break;
|
||||
case AUTH_HMAC_SHA256:
|
||||
isValidLen = keyLen == 256;
|
||||
isValidTruncLen = truncLen >= 96 && truncLen <= 256;
|
||||
break;
|
||||
case AUTH_HMAC_SHA384:
|
||||
isValidLen = keyLen == 384;
|
||||
isValidTruncLen = truncLen >= 192 && truncLen <= 384;
|
||||
break;
|
||||
case AUTH_HMAC_SHA512:
|
||||
isValidLen = keyLen == 512;
|
||||
isValidTruncLen = truncLen >= 256 && truncLen <= 512;
|
||||
break;
|
||||
case AUTH_AES_XCBC:
|
||||
isValidLen = keyLen == 128;
|
||||
isValidTruncLen = truncLen == 96;
|
||||
break;
|
||||
case AUTH_AES_CMAC:
|
||||
isValidLen = keyLen == 128;
|
||||
isValidTruncLen = truncLen == 96;
|
||||
break;
|
||||
case AUTH_CRYPT_AES_GCM:
|
||||
// The keying material for GCM is a key plus a 32-bit salt
|
||||
isValidLen = keyLen == 128 + 32 || keyLen == 192 + 32 || keyLen == 256 + 32;
|
||||
isValidTruncLen = truncLen == 64 || truncLen == 96 || truncLen == 128;
|
||||
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:
|
||||
// Should never hit here.
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
/** @hide */
|
||||
public boolean isAuthentication() {
|
||||
switch (getName()) {
|
||||
// Fallthrough
|
||||
case AUTH_HMAC_MD5:
|
||||
case AUTH_HMAC_SHA1:
|
||||
case AUTH_HMAC_SHA256:
|
||||
case AUTH_HMAC_SHA384:
|
||||
case AUTH_HMAC_SHA512:
|
||||
case AUTH_AES_XCBC:
|
||||
case AUTH_AES_CMAC:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/** @hide */
|
||||
public boolean isEncryption() {
|
||||
switch (getName()) {
|
||||
case CRYPT_AES_CBC: // fallthrough
|
||||
case CRYPT_AES_CTR:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/** @hide */
|
||||
public boolean isAead() {
|
||||
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
|
||||
// such as beta testers, we only allow sensitive info such as keys on eng builds.
|
||||
private static boolean isUnsafeBuild() {
|
||||
return Build.IS_DEBUGGABLE && Build.IS_ENG;
|
||||
}
|
||||
|
||||
@Override
|
||||
@NonNull
|
||||
public String toString() {
|
||||
return new StringBuilder()
|
||||
.append("{mName=")
|
||||
.append(mName)
|
||||
.append(", mKey=")
|
||||
.append(isUnsafeBuild() ? HexDump.toHexString(mKey) : "<hidden>")
|
||||
.append(", mTruncLenBits=")
|
||||
.append(mTruncLenBits)
|
||||
.append("}")
|
||||
.toString();
|
||||
}
|
||||
|
||||
/** @hide */
|
||||
@VisibleForTesting
|
||||
public static boolean equals(IpSecAlgorithm lhs, IpSecAlgorithm rhs) {
|
||||
if (lhs == null || rhs == null) return (lhs == rhs);
|
||||
return (lhs.mName.equals(rhs.mName)
|
||||
&& Arrays.equals(lhs.mKey, rhs.mKey)
|
||||
&& lhs.mTruncLenBits == rhs.mTruncLenBits);
|
||||
}
|
||||
};
|
||||
20
framework-t/src/android/net/IpSecConfig.aidl
Normal file
20
framework-t/src/android/net/IpSecConfig.aidl
Normal file
@@ -0,0 +1,20 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
/** @hide */
|
||||
parcelable IpSecConfig;
|
||||
358
framework-t/src/android/net/IpSecConfig.java
Normal file
358
framework-t/src/android/net/IpSecConfig.java
Normal file
@@ -0,0 +1,358 @@
|
||||
/*
|
||||
* 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 android.annotation.Nullable;
|
||||
import android.os.Parcel;
|
||||
import android.os.Parcelable;
|
||||
|
||||
import com.android.internal.annotations.VisibleForTesting;
|
||||
|
||||
/**
|
||||
* This class encapsulates all the configuration parameters needed to create IPsec transforms and
|
||||
* policies.
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
public final class IpSecConfig implements Parcelable {
|
||||
private static final String TAG = "IpSecConfig";
|
||||
|
||||
// MODE_TRANSPORT or MODE_TUNNEL
|
||||
private int mMode = IpSecTransform.MODE_TRANSPORT;
|
||||
|
||||
// Preventing this from being null simplifies Java->Native binder
|
||||
private String mSourceAddress = "";
|
||||
|
||||
// Preventing this from being null simplifies Java->Native binder
|
||||
private String mDestinationAddress = "";
|
||||
|
||||
// The underlying Network that represents the "gateway" Network
|
||||
// for outbound packets. It may also be used to select packets.
|
||||
private Network mNetwork;
|
||||
|
||||
// Minimum requirements for identifying a transform
|
||||
// SPI identifying the IPsec SA in packet processing
|
||||
// and a destination IP address
|
||||
private int mSpiResourceId = IpSecManager.INVALID_RESOURCE_ID;
|
||||
|
||||
// Encryption Algorithm
|
||||
private IpSecAlgorithm mEncryption;
|
||||
|
||||
// Authentication Algorithm
|
||||
private IpSecAlgorithm mAuthentication;
|
||||
|
||||
// Authenticated Encryption Algorithm
|
||||
private IpSecAlgorithm mAuthenticatedEncryption;
|
||||
|
||||
// For tunnel mode IPv4 UDP Encapsulation
|
||||
// IpSecTransform#ENCAP_ESP_*, such as ENCAP_ESP_OVER_UDP_IKE
|
||||
private int mEncapType = IpSecTransform.ENCAP_NONE;
|
||||
private int mEncapSocketResourceId = IpSecManager.INVALID_RESOURCE_ID;
|
||||
private int mEncapRemotePort;
|
||||
|
||||
// An interval, in seconds between the NattKeepalive packets
|
||||
private int mNattKeepaliveInterval;
|
||||
|
||||
// XFRM mark and mask; defaults to 0 (no mark/mask)
|
||||
private int mMarkValue;
|
||||
private int mMarkMask;
|
||||
|
||||
// XFRM interface id
|
||||
private int mXfrmInterfaceId;
|
||||
|
||||
/** Set the mode for this IPsec transform */
|
||||
public void setMode(int mode) {
|
||||
mMode = mode;
|
||||
}
|
||||
|
||||
/** Set the source IP addres for this IPsec transform */
|
||||
public void setSourceAddress(String sourceAddress) {
|
||||
mSourceAddress = sourceAddress;
|
||||
}
|
||||
|
||||
/** Set the destination IP address for this IPsec transform */
|
||||
public void setDestinationAddress(String destinationAddress) {
|
||||
mDestinationAddress = destinationAddress;
|
||||
}
|
||||
|
||||
/** Set the SPI by resource ID */
|
||||
public void setSpiResourceId(int resourceId) {
|
||||
mSpiResourceId = resourceId;
|
||||
}
|
||||
|
||||
/** Set the encryption algorithm */
|
||||
public void setEncryption(IpSecAlgorithm encryption) {
|
||||
mEncryption = encryption;
|
||||
}
|
||||
|
||||
/** Set the authentication algorithm */
|
||||
public void setAuthentication(IpSecAlgorithm authentication) {
|
||||
mAuthentication = authentication;
|
||||
}
|
||||
|
||||
/** Set the authenticated encryption algorithm */
|
||||
public void setAuthenticatedEncryption(IpSecAlgorithm authenticatedEncryption) {
|
||||
mAuthenticatedEncryption = authenticatedEncryption;
|
||||
}
|
||||
|
||||
/** Set the underlying network that will carry traffic for this transform */
|
||||
public void setNetwork(Network network) {
|
||||
mNetwork = network;
|
||||
}
|
||||
|
||||
public void setEncapType(int encapType) {
|
||||
mEncapType = encapType;
|
||||
}
|
||||
|
||||
public void setEncapSocketResourceId(int resourceId) {
|
||||
mEncapSocketResourceId = resourceId;
|
||||
}
|
||||
|
||||
public void setEncapRemotePort(int port) {
|
||||
mEncapRemotePort = port;
|
||||
}
|
||||
|
||||
public void setNattKeepaliveInterval(int interval) {
|
||||
mNattKeepaliveInterval = interval;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the mark value
|
||||
*
|
||||
* <p>Internal (System server) use only. Marks passed in by users will be overwritten or
|
||||
* ignored.
|
||||
*/
|
||||
public void setMarkValue(int mark) {
|
||||
mMarkValue = mark;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the mark mask
|
||||
*
|
||||
* <p>Internal (System server) use only. Marks passed in by users will be overwritten or
|
||||
* ignored.
|
||||
*/
|
||||
public void setMarkMask(int mask) {
|
||||
mMarkMask = mask;
|
||||
}
|
||||
|
||||
public void setXfrmInterfaceId(int xfrmInterfaceId) {
|
||||
mXfrmInterfaceId = xfrmInterfaceId;
|
||||
}
|
||||
|
||||
// Transport or Tunnel
|
||||
public int getMode() {
|
||||
return mMode;
|
||||
}
|
||||
|
||||
public String getSourceAddress() {
|
||||
return mSourceAddress;
|
||||
}
|
||||
|
||||
public int getSpiResourceId() {
|
||||
return mSpiResourceId;
|
||||
}
|
||||
|
||||
public String getDestinationAddress() {
|
||||
return mDestinationAddress;
|
||||
}
|
||||
|
||||
public IpSecAlgorithm getEncryption() {
|
||||
return mEncryption;
|
||||
}
|
||||
|
||||
public IpSecAlgorithm getAuthentication() {
|
||||
return mAuthentication;
|
||||
}
|
||||
|
||||
public IpSecAlgorithm getAuthenticatedEncryption() {
|
||||
return mAuthenticatedEncryption;
|
||||
}
|
||||
|
||||
public Network getNetwork() {
|
||||
return mNetwork;
|
||||
}
|
||||
|
||||
public int getEncapType() {
|
||||
return mEncapType;
|
||||
}
|
||||
|
||||
public int getEncapSocketResourceId() {
|
||||
return mEncapSocketResourceId;
|
||||
}
|
||||
|
||||
public int getEncapRemotePort() {
|
||||
return mEncapRemotePort;
|
||||
}
|
||||
|
||||
public int getNattKeepaliveInterval() {
|
||||
return mNattKeepaliveInterval;
|
||||
}
|
||||
|
||||
public int getMarkValue() {
|
||||
return mMarkValue;
|
||||
}
|
||||
|
||||
public int getMarkMask() {
|
||||
return mMarkMask;
|
||||
}
|
||||
|
||||
public int getXfrmInterfaceId() {
|
||||
return mXfrmInterfaceId;
|
||||
}
|
||||
|
||||
// Parcelable Methods
|
||||
|
||||
@Override
|
||||
public int describeContents() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeToParcel(Parcel out, int flags) {
|
||||
out.writeInt(mMode);
|
||||
out.writeString(mSourceAddress);
|
||||
out.writeString(mDestinationAddress);
|
||||
out.writeParcelable(mNetwork, flags);
|
||||
out.writeInt(mSpiResourceId);
|
||||
out.writeParcelable(mEncryption, flags);
|
||||
out.writeParcelable(mAuthentication, flags);
|
||||
out.writeParcelable(mAuthenticatedEncryption, flags);
|
||||
out.writeInt(mEncapType);
|
||||
out.writeInt(mEncapSocketResourceId);
|
||||
out.writeInt(mEncapRemotePort);
|
||||
out.writeInt(mNattKeepaliveInterval);
|
||||
out.writeInt(mMarkValue);
|
||||
out.writeInt(mMarkMask);
|
||||
out.writeInt(mXfrmInterfaceId);
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
public IpSecConfig() {}
|
||||
|
||||
/** Copy constructor */
|
||||
@VisibleForTesting
|
||||
public IpSecConfig(IpSecConfig c) {
|
||||
mMode = c.mMode;
|
||||
mSourceAddress = c.mSourceAddress;
|
||||
mDestinationAddress = c.mDestinationAddress;
|
||||
mNetwork = c.mNetwork;
|
||||
mSpiResourceId = c.mSpiResourceId;
|
||||
mEncryption = c.mEncryption;
|
||||
mAuthentication = c.mAuthentication;
|
||||
mAuthenticatedEncryption = c.mAuthenticatedEncryption;
|
||||
mEncapType = c.mEncapType;
|
||||
mEncapSocketResourceId = c.mEncapSocketResourceId;
|
||||
mEncapRemotePort = c.mEncapRemotePort;
|
||||
mNattKeepaliveInterval = c.mNattKeepaliveInterval;
|
||||
mMarkValue = c.mMarkValue;
|
||||
mMarkMask = c.mMarkMask;
|
||||
mXfrmInterfaceId = c.mXfrmInterfaceId;
|
||||
}
|
||||
|
||||
private IpSecConfig(Parcel in) {
|
||||
mMode = in.readInt();
|
||||
mSourceAddress = in.readString();
|
||||
mDestinationAddress = in.readString();
|
||||
mNetwork = (Network) in.readParcelable(Network.class.getClassLoader());
|
||||
mSpiResourceId = in.readInt();
|
||||
mEncryption =
|
||||
(IpSecAlgorithm) in.readParcelable(IpSecAlgorithm.class.getClassLoader());
|
||||
mAuthentication =
|
||||
(IpSecAlgorithm) in.readParcelable(IpSecAlgorithm.class.getClassLoader());
|
||||
mAuthenticatedEncryption =
|
||||
(IpSecAlgorithm) in.readParcelable(IpSecAlgorithm.class.getClassLoader());
|
||||
mEncapType = in.readInt();
|
||||
mEncapSocketResourceId = in.readInt();
|
||||
mEncapRemotePort = in.readInt();
|
||||
mNattKeepaliveInterval = in.readInt();
|
||||
mMarkValue = in.readInt();
|
||||
mMarkMask = in.readInt();
|
||||
mXfrmInterfaceId = in.readInt();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
StringBuilder strBuilder = new StringBuilder();
|
||||
strBuilder
|
||||
.append("{mMode=")
|
||||
.append(mMode == IpSecTransform.MODE_TUNNEL ? "TUNNEL" : "TRANSPORT")
|
||||
.append(", mSourceAddress=")
|
||||
.append(mSourceAddress)
|
||||
.append(", mDestinationAddress=")
|
||||
.append(mDestinationAddress)
|
||||
.append(", mNetwork=")
|
||||
.append(mNetwork)
|
||||
.append(", mEncapType=")
|
||||
.append(mEncapType)
|
||||
.append(", mEncapSocketResourceId=")
|
||||
.append(mEncapSocketResourceId)
|
||||
.append(", mEncapRemotePort=")
|
||||
.append(mEncapRemotePort)
|
||||
.append(", mNattKeepaliveInterval=")
|
||||
.append(mNattKeepaliveInterval)
|
||||
.append("{mSpiResourceId=")
|
||||
.append(mSpiResourceId)
|
||||
.append(", mEncryption=")
|
||||
.append(mEncryption)
|
||||
.append(", mAuthentication=")
|
||||
.append(mAuthentication)
|
||||
.append(", mAuthenticatedEncryption=")
|
||||
.append(mAuthenticatedEncryption)
|
||||
.append(", mMarkValue=")
|
||||
.append(mMarkValue)
|
||||
.append(", mMarkMask=")
|
||||
.append(mMarkMask)
|
||||
.append(", mXfrmInterfaceId=")
|
||||
.append(mXfrmInterfaceId)
|
||||
.append("}");
|
||||
|
||||
return strBuilder.toString();
|
||||
}
|
||||
|
||||
public static final @android.annotation.NonNull Parcelable.Creator<IpSecConfig> CREATOR =
|
||||
new Parcelable.Creator<IpSecConfig>() {
|
||||
public IpSecConfig createFromParcel(Parcel in) {
|
||||
return new IpSecConfig(in);
|
||||
}
|
||||
|
||||
public IpSecConfig[] newArray(int size) {
|
||||
return new IpSecConfig[size];
|
||||
}
|
||||
};
|
||||
|
||||
@Override
|
||||
public boolean equals(@Nullable Object other) {
|
||||
if (!(other instanceof IpSecConfig)) return false;
|
||||
final IpSecConfig rhs = (IpSecConfig) other;
|
||||
return (mMode == rhs.mMode
|
||||
&& mSourceAddress.equals(rhs.mSourceAddress)
|
||||
&& mDestinationAddress.equals(rhs.mDestinationAddress)
|
||||
&& ((mNetwork != null && mNetwork.equals(rhs.mNetwork))
|
||||
|| (mNetwork == rhs.mNetwork))
|
||||
&& mEncapType == rhs.mEncapType
|
||||
&& mEncapSocketResourceId == rhs.mEncapSocketResourceId
|
||||
&& mEncapRemotePort == rhs.mEncapRemotePort
|
||||
&& mNattKeepaliveInterval == rhs.mNattKeepaliveInterval
|
||||
&& mSpiResourceId == rhs.mSpiResourceId
|
||||
&& IpSecAlgorithm.equals(mEncryption, rhs.mEncryption)
|
||||
&& IpSecAlgorithm.equals(mAuthenticatedEncryption, rhs.mAuthenticatedEncryption)
|
||||
&& IpSecAlgorithm.equals(mAuthentication, rhs.mAuthentication)
|
||||
&& mMarkValue == rhs.mMarkValue
|
||||
&& mMarkMask == rhs.mMarkMask
|
||||
&& mXfrmInterfaceId == rhs.mXfrmInterfaceId);
|
||||
}
|
||||
}
|
||||
1034
framework-t/src/android/net/IpSecManager.java
Normal file
1034
framework-t/src/android/net/IpSecManager.java
Normal file
File diff suppressed because it is too large
Load Diff
20
framework-t/src/android/net/IpSecSpiResponse.aidl
Normal file
20
framework-t/src/android/net/IpSecSpiResponse.aidl
Normal file
@@ -0,0 +1,20 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
/** @hide */
|
||||
parcelable IpSecSpiResponse;
|
||||
78
framework-t/src/android/net/IpSecSpiResponse.java
Normal file
78
framework-t/src/android/net/IpSecSpiResponse.java
Normal file
@@ -0,0 +1,78 @@
|
||||
/*
|
||||
* 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 android.os.Parcel;
|
||||
import android.os.Parcelable;
|
||||
|
||||
/**
|
||||
* This class is used to return an SPI and corresponding status from the IpSecService to an
|
||||
* IpSecManager.SecurityParameterIndex.
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
public final class IpSecSpiResponse implements Parcelable {
|
||||
private static final String TAG = "IpSecSpiResponse";
|
||||
|
||||
public final int resourceId;
|
||||
public final int status;
|
||||
public final int spi;
|
||||
// Parcelable Methods
|
||||
|
||||
@Override
|
||||
public int describeContents() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeToParcel(Parcel out, int flags) {
|
||||
out.writeInt(status);
|
||||
out.writeInt(resourceId);
|
||||
out.writeInt(spi);
|
||||
}
|
||||
|
||||
public IpSecSpiResponse(int inStatus, int inResourceId, int inSpi) {
|
||||
status = inStatus;
|
||||
resourceId = inResourceId;
|
||||
spi = inSpi;
|
||||
}
|
||||
|
||||
public IpSecSpiResponse(int inStatus) {
|
||||
if (inStatus == IpSecManager.Status.OK) {
|
||||
throw new IllegalArgumentException("Valid status implies other args must be provided");
|
||||
}
|
||||
status = inStatus;
|
||||
resourceId = IpSecManager.INVALID_RESOURCE_ID;
|
||||
spi = IpSecManager.INVALID_SECURITY_PARAMETER_INDEX;
|
||||
}
|
||||
|
||||
private IpSecSpiResponse(Parcel in) {
|
||||
status = in.readInt();
|
||||
resourceId = in.readInt();
|
||||
spi = in.readInt();
|
||||
}
|
||||
|
||||
public static final @android.annotation.NonNull Parcelable.Creator<IpSecSpiResponse> CREATOR =
|
||||
new Parcelable.Creator<IpSecSpiResponse>() {
|
||||
public IpSecSpiResponse createFromParcel(Parcel in) {
|
||||
return new IpSecSpiResponse(in);
|
||||
}
|
||||
|
||||
public IpSecSpiResponse[] newArray(int size) {
|
||||
return new IpSecSpiResponse[size];
|
||||
}
|
||||
};
|
||||
}
|
||||
421
framework-t/src/android/net/IpSecTransform.java
Normal file
421
framework-t/src/android/net/IpSecTransform.java
Normal file
@@ -0,0 +1,421 @@
|
||||
/*
|
||||
* 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 android.net.IpSecManager.INVALID_RESOURCE_ID;
|
||||
|
||||
import android.annotation.IntDef;
|
||||
import android.annotation.NonNull;
|
||||
import android.annotation.Nullable;
|
||||
import android.annotation.RequiresFeature;
|
||||
import android.annotation.RequiresPermission;
|
||||
import android.annotation.SystemApi;
|
||||
import android.content.Context;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.os.Binder;
|
||||
import android.os.IBinder;
|
||||
import android.os.RemoteException;
|
||||
import android.os.ServiceManager;
|
||||
import android.os.ServiceSpecificException;
|
||||
import android.util.Log;
|
||||
|
||||
import com.android.internal.annotations.VisibleForTesting;
|
||||
import com.android.internal.util.Preconditions;
|
||||
|
||||
import dalvik.system.CloseGuard;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.net.InetAddress;
|
||||
|
||||
/**
|
||||
* This class represents a transform, which roughly corresponds to an IPsec Security Association.
|
||||
*
|
||||
* <p>Transforms are created using {@link IpSecTransform.Builder}. Each {@code IpSecTransform}
|
||||
* object encapsulates the properties and state of an IPsec security association. That includes,
|
||||
* but is not limited to, algorithm choice, key material, and allocated system resources.
|
||||
*
|
||||
* @see <a href="https://tools.ietf.org/html/rfc4301">RFC 4301, Security Architecture for the
|
||||
* Internet Protocol</a>
|
||||
*/
|
||||
public final class IpSecTransform implements AutoCloseable {
|
||||
private static final String TAG = "IpSecTransform";
|
||||
|
||||
/** @hide */
|
||||
public static final int MODE_TRANSPORT = 0;
|
||||
|
||||
/** @hide */
|
||||
public static final int MODE_TUNNEL = 1;
|
||||
|
||||
/** @hide */
|
||||
public static final int ENCAP_NONE = 0;
|
||||
|
||||
/**
|
||||
* IPsec traffic will be encapsulated within UDP, but with 8 zero-value bytes between the UDP
|
||||
* header and payload. This prevents traffic from being interpreted as ESP or IKEv2.
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
public static final int ENCAP_ESPINUDP_NON_IKE = 1;
|
||||
|
||||
/**
|
||||
* IPsec traffic will be encapsulated within UDP as per
|
||||
* <a href="https://tools.ietf.org/html/rfc3948">RFC 3498</a>.
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
public static final int ENCAP_ESPINUDP = 2;
|
||||
|
||||
/** @hide */
|
||||
@IntDef(value = {ENCAP_NONE, ENCAP_ESPINUDP, ENCAP_ESPINUDP_NON_IKE})
|
||||
@Retention(RetentionPolicy.SOURCE)
|
||||
public @interface EncapType {}
|
||||
|
||||
/** @hide */
|
||||
@VisibleForTesting
|
||||
public IpSecTransform(Context context, IpSecConfig config) {
|
||||
mContext = context;
|
||||
mConfig = new IpSecConfig(config);
|
||||
mResourceId = INVALID_RESOURCE_ID;
|
||||
}
|
||||
|
||||
private IIpSecService getIpSecService() {
|
||||
IBinder b = ServiceManager.getService(android.content.Context.IPSEC_SERVICE);
|
||||
if (b == null) {
|
||||
throw new RemoteException("Failed to connect to IpSecService")
|
||||
.rethrowAsRuntimeException();
|
||||
}
|
||||
|
||||
return IIpSecService.Stub.asInterface(b);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks the result status and throws an appropriate exception if the status is not Status.OK.
|
||||
*/
|
||||
private void checkResultStatus(int status)
|
||||
throws IOException, IpSecManager.ResourceUnavailableException,
|
||||
IpSecManager.SpiUnavailableException {
|
||||
switch (status) {
|
||||
case IpSecManager.Status.OK:
|
||||
return;
|
||||
// TODO: Pass Error string back from bundle so that errors can be more specific
|
||||
case IpSecManager.Status.RESOURCE_UNAVAILABLE:
|
||||
throw new IpSecManager.ResourceUnavailableException(
|
||||
"Failed to allocate a new IpSecTransform");
|
||||
case IpSecManager.Status.SPI_UNAVAILABLE:
|
||||
Log.wtf(TAG, "Attempting to use an SPI that was somehow not reserved");
|
||||
// Fall through
|
||||
default:
|
||||
throw new IllegalStateException(
|
||||
"Failed to Create a Transform with status code " + status);
|
||||
}
|
||||
}
|
||||
|
||||
private IpSecTransform activate()
|
||||
throws IOException, IpSecManager.ResourceUnavailableException,
|
||||
IpSecManager.SpiUnavailableException {
|
||||
synchronized (this) {
|
||||
try {
|
||||
IIpSecService svc = getIpSecService();
|
||||
IpSecTransformResponse result = svc.createTransform(
|
||||
mConfig, new Binder(), mContext.getOpPackageName());
|
||||
int status = result.status;
|
||||
checkResultStatus(status);
|
||||
mResourceId = result.resourceId;
|
||||
Log.d(TAG, "Added Transform with Id " + mResourceId);
|
||||
mCloseGuard.open("build");
|
||||
} catch (ServiceSpecificException e) {
|
||||
throw IpSecManager.rethrowUncheckedExceptionFromServiceSpecificException(e);
|
||||
} catch (RemoteException e) {
|
||||
throw e.rethrowAsRuntimeException();
|
||||
}
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Standard equals.
|
||||
*/
|
||||
public boolean equals(@Nullable Object other) {
|
||||
if (this == other) return true;
|
||||
if (!(other instanceof IpSecTransform)) return false;
|
||||
final IpSecTransform rhs = (IpSecTransform) other;
|
||||
return getConfig().equals(rhs.getConfig()) && mResourceId == rhs.mResourceId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Deactivate this {@code IpSecTransform} and free allocated resources.
|
||||
*
|
||||
* <p>Deactivating a transform while it is still applied to a socket will result in errors on
|
||||
* that socket. Make sure to remove transforms by calling {@link
|
||||
* IpSecManager#removeTransportModeTransforms}. Note, removing an {@code IpSecTransform} from a
|
||||
* socket will not deactivate it (because one transform may be applied to multiple sockets).
|
||||
*
|
||||
* <p>It is safe to call this method on a transform that has already been deactivated.
|
||||
*/
|
||||
public void close() {
|
||||
Log.d(TAG, "Removing Transform with Id " + mResourceId);
|
||||
|
||||
// Always safe to attempt cleanup
|
||||
if (mResourceId == INVALID_RESOURCE_ID) {
|
||||
mCloseGuard.close();
|
||||
return;
|
||||
}
|
||||
try {
|
||||
IIpSecService svc = getIpSecService();
|
||||
svc.deleteTransform(mResourceId);
|
||||
} catch (RemoteException e) {
|
||||
throw e.rethrowAsRuntimeException();
|
||||
} catch (Exception e) {
|
||||
// On close we swallow all random exceptions since failure to close is not
|
||||
// actionable by the user.
|
||||
Log.e(TAG, "Failed to close " + this + ", Exception=" + e);
|
||||
} finally {
|
||||
mResourceId = INVALID_RESOURCE_ID;
|
||||
mCloseGuard.close();
|
||||
}
|
||||
}
|
||||
|
||||
/** Check that the transform was closed properly. */
|
||||
@Override
|
||||
protected void finalize() throws Throwable {
|
||||
if (mCloseGuard != null) {
|
||||
mCloseGuard.warnIfOpen();
|
||||
}
|
||||
close();
|
||||
}
|
||||
|
||||
/* Package */
|
||||
IpSecConfig getConfig() {
|
||||
return mConfig;
|
||||
}
|
||||
|
||||
private final IpSecConfig mConfig;
|
||||
private int mResourceId;
|
||||
private final Context mContext;
|
||||
private final CloseGuard mCloseGuard = CloseGuard.get();
|
||||
|
||||
/** @hide */
|
||||
@VisibleForTesting
|
||||
public int getResourceId() {
|
||||
return mResourceId;
|
||||
}
|
||||
|
||||
/**
|
||||
* A callback class to provide status information regarding a NAT-T keepalive session
|
||||
*
|
||||
* <p>Use this callback to receive status information regarding a NAT-T keepalive session
|
||||
* by registering it when calling {@link #startNattKeepalive}.
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
public static class NattKeepaliveCallback {
|
||||
/** The specified {@code Network} is not connected. */
|
||||
public static final int ERROR_INVALID_NETWORK = 1;
|
||||
/** The hardware does not support this request. */
|
||||
public static final int ERROR_HARDWARE_UNSUPPORTED = 2;
|
||||
/** The hardware returned an error. */
|
||||
public static final int ERROR_HARDWARE_ERROR = 3;
|
||||
|
||||
/** The requested keepalive was successfully started. */
|
||||
public void onStarted() {}
|
||||
/** The keepalive was successfully stopped. */
|
||||
public void onStopped() {}
|
||||
/** An error occurred. */
|
||||
public void onError(int error) {}
|
||||
}
|
||||
|
||||
/** This class is used to build {@link IpSecTransform} objects. */
|
||||
public static class Builder {
|
||||
private Context mContext;
|
||||
private IpSecConfig mConfig;
|
||||
|
||||
/**
|
||||
* Set the encryption algorithm.
|
||||
*
|
||||
* <p>Encryption is mutually exclusive with authenticated encryption.
|
||||
*
|
||||
* @param algo {@link IpSecAlgorithm} specifying the encryption to be applied.
|
||||
*/
|
||||
@NonNull
|
||||
public IpSecTransform.Builder setEncryption(@NonNull IpSecAlgorithm algo) {
|
||||
// TODO: throw IllegalArgumentException if algo is not an encryption algorithm.
|
||||
Preconditions.checkNotNull(algo);
|
||||
mConfig.setEncryption(algo);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the authentication (integrity) algorithm.
|
||||
*
|
||||
* <p>Authentication is mutually exclusive with authenticated encryption.
|
||||
*
|
||||
* @param algo {@link IpSecAlgorithm} specifying the authentication to be applied.
|
||||
*/
|
||||
@NonNull
|
||||
public IpSecTransform.Builder setAuthentication(@NonNull IpSecAlgorithm algo) {
|
||||
// TODO: throw IllegalArgumentException if algo is not an authentication algorithm.
|
||||
Preconditions.checkNotNull(algo);
|
||||
mConfig.setAuthentication(algo);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the authenticated encryption algorithm.
|
||||
*
|
||||
* <p>The Authenticated Encryption (AE) class of algorithms are also known as
|
||||
* Authenticated Encryption with Associated Data (AEAD) algorithms, or Combined mode
|
||||
* algorithms (as referred to in
|
||||
* <a href="https://tools.ietf.org/html/rfc4301">RFC 4301</a>).
|
||||
*
|
||||
* <p>Authenticated encryption is mutually exclusive with encryption and authentication.
|
||||
*
|
||||
* @param algo {@link IpSecAlgorithm} specifying the authenticated encryption algorithm to
|
||||
* be applied.
|
||||
*/
|
||||
@NonNull
|
||||
public IpSecTransform.Builder setAuthenticatedEncryption(@NonNull IpSecAlgorithm algo) {
|
||||
Preconditions.checkNotNull(algo);
|
||||
mConfig.setAuthenticatedEncryption(algo);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add UDP encapsulation to an IPv4 transform.
|
||||
*
|
||||
* <p>This allows IPsec traffic to pass through a NAT.
|
||||
*
|
||||
* @see <a href="https://tools.ietf.org/html/rfc3948">RFC 3948, UDP Encapsulation of IPsec
|
||||
* ESP Packets</a>
|
||||
* @see <a href="https://tools.ietf.org/html/rfc7296#section-2.23">RFC 7296 section 2.23,
|
||||
* NAT Traversal of IKEv2</a>
|
||||
* @param localSocket a socket for sending and receiving encapsulated traffic
|
||||
* @param remotePort the UDP port number of the remote host that will send and receive
|
||||
* encapsulated traffic. In the case of IKEv2, this should be port 4500.
|
||||
*/
|
||||
@NonNull
|
||||
public IpSecTransform.Builder setIpv4Encapsulation(
|
||||
@NonNull IpSecManager.UdpEncapsulationSocket localSocket, int remotePort) {
|
||||
Preconditions.checkNotNull(localSocket);
|
||||
mConfig.setEncapType(ENCAP_ESPINUDP);
|
||||
if (localSocket.getResourceId() == INVALID_RESOURCE_ID) {
|
||||
throw new IllegalArgumentException("Invalid UdpEncapsulationSocket");
|
||||
}
|
||||
mConfig.setEncapSocketResourceId(localSocket.getResourceId());
|
||||
mConfig.setEncapRemotePort(remotePort);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Build a transport mode {@link IpSecTransform}.
|
||||
*
|
||||
* <p>This builds and activates a transport mode transform. Note that an active transform
|
||||
* will not affect any network traffic until it has been applied to one or more sockets.
|
||||
*
|
||||
* @see IpSecManager#applyTransportModeTransform
|
||||
* @param sourceAddress the source {@code InetAddress} of traffic on sockets that will use
|
||||
* this transform; this address must belong to the Network used by all sockets that
|
||||
* utilize this transform; if provided, then only traffic originating from the
|
||||
* specified source address will be processed.
|
||||
* @param spi a unique {@link IpSecManager.SecurityParameterIndex} to identify transformed
|
||||
* traffic
|
||||
* @throws IllegalArgumentException indicating that a particular combination of transform
|
||||
* properties is invalid
|
||||
* @throws IpSecManager.ResourceUnavailableException indicating that too many transforms
|
||||
* are active
|
||||
* @throws IpSecManager.SpiUnavailableException indicating the rare case where an SPI
|
||||
* collides with an existing transform
|
||||
* @throws IOException indicating other errors
|
||||
*/
|
||||
@NonNull
|
||||
public IpSecTransform buildTransportModeTransform(
|
||||
@NonNull InetAddress sourceAddress,
|
||||
@NonNull IpSecManager.SecurityParameterIndex spi)
|
||||
throws IpSecManager.ResourceUnavailableException,
|
||||
IpSecManager.SpiUnavailableException, IOException {
|
||||
Preconditions.checkNotNull(sourceAddress);
|
||||
Preconditions.checkNotNull(spi);
|
||||
if (spi.getResourceId() == INVALID_RESOURCE_ID) {
|
||||
throw new IllegalArgumentException("Invalid SecurityParameterIndex");
|
||||
}
|
||||
mConfig.setMode(MODE_TRANSPORT);
|
||||
mConfig.setSourceAddress(sourceAddress.getHostAddress());
|
||||
mConfig.setSpiResourceId(spi.getResourceId());
|
||||
// FIXME: modifying a builder after calling build can change the built transform.
|
||||
return new IpSecTransform(mContext, mConfig).activate();
|
||||
}
|
||||
|
||||
/**
|
||||
* Build and return an {@link IpSecTransform} object as a Tunnel Mode Transform. Some
|
||||
* parameters have interdependencies that are checked at build time.
|
||||
*
|
||||
* @param sourceAddress the {@link InetAddress} that provides the source address for this
|
||||
* IPsec tunnel. This is almost certainly an address belonging to the {@link Network}
|
||||
* that will originate the traffic, which is set as the {@link #setUnderlyingNetwork}.
|
||||
* @param spi a unique {@link IpSecManager.SecurityParameterIndex} to identify transformed
|
||||
* traffic
|
||||
* @throws IllegalArgumentException indicating that a particular combination of transform
|
||||
* properties is invalid.
|
||||
* @throws IpSecManager.ResourceUnavailableException indicating that too many transforms
|
||||
* are active
|
||||
* @throws IpSecManager.SpiUnavailableException indicating the rare case where an SPI
|
||||
* collides with an existing transform
|
||||
* @throws IOException indicating other errors
|
||||
* @hide
|
||||
*/
|
||||
@SystemApi
|
||||
@NonNull
|
||||
@RequiresFeature(PackageManager.FEATURE_IPSEC_TUNNELS)
|
||||
@RequiresPermission(android.Manifest.permission.MANAGE_IPSEC_TUNNELS)
|
||||
public IpSecTransform buildTunnelModeTransform(
|
||||
@NonNull InetAddress sourceAddress,
|
||||
@NonNull IpSecManager.SecurityParameterIndex spi)
|
||||
throws IpSecManager.ResourceUnavailableException,
|
||||
IpSecManager.SpiUnavailableException, IOException {
|
||||
Preconditions.checkNotNull(sourceAddress);
|
||||
Preconditions.checkNotNull(spi);
|
||||
if (spi.getResourceId() == INVALID_RESOURCE_ID) {
|
||||
throw new IllegalArgumentException("Invalid SecurityParameterIndex");
|
||||
}
|
||||
mConfig.setMode(MODE_TUNNEL);
|
||||
mConfig.setSourceAddress(sourceAddress.getHostAddress());
|
||||
mConfig.setSpiResourceId(spi.getResourceId());
|
||||
return new IpSecTransform(mContext, mConfig).activate();
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new IpSecTransform.Builder.
|
||||
*
|
||||
* @param context current context
|
||||
*/
|
||||
public Builder(@NonNull Context context) {
|
||||
Preconditions.checkNotNull(context);
|
||||
mContext = context;
|
||||
mConfig = new IpSecConfig();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return new StringBuilder()
|
||||
.append("IpSecTransform{resourceId=")
|
||||
.append(mResourceId)
|
||||
.append("}")
|
||||
.toString();
|
||||
}
|
||||
}
|
||||
20
framework-t/src/android/net/IpSecTransformResponse.aidl
Normal file
20
framework-t/src/android/net/IpSecTransformResponse.aidl
Normal file
@@ -0,0 +1,20 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
/** @hide */
|
||||
parcelable IpSecTransformResponse;
|
||||
73
framework-t/src/android/net/IpSecTransformResponse.java
Normal file
73
framework-t/src/android/net/IpSecTransformResponse.java
Normal file
@@ -0,0 +1,73 @@
|
||||
/*
|
||||
* 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 android.os.Parcel;
|
||||
import android.os.Parcelable;
|
||||
|
||||
/**
|
||||
* This class is used to return an IpSecTransform resource Id and and corresponding status from the
|
||||
* IpSecService to an IpSecTransform object.
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
public final class IpSecTransformResponse implements Parcelable {
|
||||
private static final String TAG = "IpSecTransformResponse";
|
||||
|
||||
public final int resourceId;
|
||||
public final int status;
|
||||
// Parcelable Methods
|
||||
|
||||
@Override
|
||||
public int describeContents() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeToParcel(Parcel out, int flags) {
|
||||
out.writeInt(status);
|
||||
out.writeInt(resourceId);
|
||||
}
|
||||
|
||||
public IpSecTransformResponse(int inStatus) {
|
||||
if (inStatus == IpSecManager.Status.OK) {
|
||||
throw new IllegalArgumentException("Valid status implies other args must be provided");
|
||||
}
|
||||
status = inStatus;
|
||||
resourceId = IpSecManager.INVALID_RESOURCE_ID;
|
||||
}
|
||||
|
||||
public IpSecTransformResponse(int inStatus, int inResourceId) {
|
||||
status = inStatus;
|
||||
resourceId = inResourceId;
|
||||
}
|
||||
|
||||
private IpSecTransformResponse(Parcel in) {
|
||||
status = in.readInt();
|
||||
resourceId = in.readInt();
|
||||
}
|
||||
|
||||
public static final @android.annotation.NonNull Parcelable.Creator<IpSecTransformResponse> CREATOR =
|
||||
new Parcelable.Creator<IpSecTransformResponse>() {
|
||||
public IpSecTransformResponse createFromParcel(Parcel in) {
|
||||
return new IpSecTransformResponse(in);
|
||||
}
|
||||
|
||||
public IpSecTransformResponse[] newArray(int size) {
|
||||
return new IpSecTransformResponse[size];
|
||||
}
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
/*
|
||||
* Copyright (C) 2018 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;
|
||||
|
||||
/** @hide */
|
||||
parcelable IpSecTunnelInterfaceResponse;
|
||||
@@ -0,0 +1,78 @@
|
||||
/*
|
||||
* Copyright (C) 2018 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 android.os.Parcel;
|
||||
import android.os.Parcelable;
|
||||
|
||||
/**
|
||||
* This class is used to return an IpSecTunnelInterface resource Id and and corresponding status
|
||||
* from the IpSecService to an IpSecTunnelInterface object.
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
public final class IpSecTunnelInterfaceResponse implements Parcelable {
|
||||
private static final String TAG = "IpSecTunnelInterfaceResponse";
|
||||
|
||||
public final int resourceId;
|
||||
public final String interfaceName;
|
||||
public final int status;
|
||||
// Parcelable Methods
|
||||
|
||||
@Override
|
||||
public int describeContents() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeToParcel(Parcel out, int flags) {
|
||||
out.writeInt(status);
|
||||
out.writeInt(resourceId);
|
||||
out.writeString(interfaceName);
|
||||
}
|
||||
|
||||
public IpSecTunnelInterfaceResponse(int inStatus) {
|
||||
if (inStatus == IpSecManager.Status.OK) {
|
||||
throw new IllegalArgumentException("Valid status implies other args must be provided");
|
||||
}
|
||||
status = inStatus;
|
||||
resourceId = IpSecManager.INVALID_RESOURCE_ID;
|
||||
interfaceName = "";
|
||||
}
|
||||
|
||||
public IpSecTunnelInterfaceResponse(int inStatus, int inResourceId, String inInterfaceName) {
|
||||
status = inStatus;
|
||||
resourceId = inResourceId;
|
||||
interfaceName = inInterfaceName;
|
||||
}
|
||||
|
||||
private IpSecTunnelInterfaceResponse(Parcel in) {
|
||||
status = in.readInt();
|
||||
resourceId = in.readInt();
|
||||
interfaceName = in.readString();
|
||||
}
|
||||
|
||||
public static final @android.annotation.NonNull Parcelable.Creator<IpSecTunnelInterfaceResponse> CREATOR =
|
||||
new Parcelable.Creator<IpSecTunnelInterfaceResponse>() {
|
||||
public IpSecTunnelInterfaceResponse createFromParcel(Parcel in) {
|
||||
return new IpSecTunnelInterfaceResponse(in);
|
||||
}
|
||||
|
||||
public IpSecTunnelInterfaceResponse[] newArray(int size) {
|
||||
return new IpSecTunnelInterfaceResponse[size];
|
||||
}
|
||||
};
|
||||
}
|
||||
20
framework-t/src/android/net/IpSecUdpEncapResponse.aidl
Normal file
20
framework-t/src/android/net/IpSecUdpEncapResponse.aidl
Normal file
@@ -0,0 +1,20 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
/** @hide */
|
||||
parcelable IpSecUdpEncapResponse;
|
||||
96
framework-t/src/android/net/IpSecUdpEncapResponse.java
Normal file
96
framework-t/src/android/net/IpSecUdpEncapResponse.java
Normal file
@@ -0,0 +1,96 @@
|
||||
/*
|
||||
* 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 android.os.Parcel;
|
||||
import android.os.ParcelFileDescriptor;
|
||||
import android.os.Parcelable;
|
||||
import java.io.FileDescriptor;
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* This class is used to return a UDP Socket and corresponding status from the IpSecService to an
|
||||
* IpSecManager.UdpEncapsulationSocket.
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
public final class IpSecUdpEncapResponse implements Parcelable {
|
||||
private static final String TAG = "IpSecUdpEncapResponse";
|
||||
|
||||
public final int resourceId;
|
||||
public final int port;
|
||||
public final int status;
|
||||
// There is a weird asymmetry with FileDescriptor: you can write a FileDescriptor
|
||||
// but you read a ParcelFileDescriptor. To circumvent this, when we receive a FD
|
||||
// from the user, we immediately create a ParcelFileDescriptor DUP, which we invalidate
|
||||
// on writeParcel() by setting the flag to do close-on-write.
|
||||
// TODO: tests to ensure this doesn't leak
|
||||
public final ParcelFileDescriptor fileDescriptor;
|
||||
|
||||
// Parcelable Methods
|
||||
|
||||
@Override
|
||||
public int describeContents() {
|
||||
return (fileDescriptor != null) ? Parcelable.CONTENTS_FILE_DESCRIPTOR : 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeToParcel(Parcel out, int flags) {
|
||||
out.writeInt(status);
|
||||
out.writeInt(resourceId);
|
||||
out.writeInt(port);
|
||||
out.writeParcelable(fileDescriptor, Parcelable.PARCELABLE_WRITE_RETURN_VALUE);
|
||||
}
|
||||
|
||||
public IpSecUdpEncapResponse(int inStatus) {
|
||||
if (inStatus == IpSecManager.Status.OK) {
|
||||
throw new IllegalArgumentException("Valid status implies other args must be provided");
|
||||
}
|
||||
status = inStatus;
|
||||
resourceId = IpSecManager.INVALID_RESOURCE_ID;
|
||||
port = -1;
|
||||
fileDescriptor = null; // yes I know it's redundant, but readability
|
||||
}
|
||||
|
||||
public IpSecUdpEncapResponse(int inStatus, int inResourceId, int inPort, FileDescriptor inFd)
|
||||
throws IOException {
|
||||
if (inStatus == IpSecManager.Status.OK && inFd == null) {
|
||||
throw new IllegalArgumentException("Valid status implies FD must be non-null");
|
||||
}
|
||||
status = inStatus;
|
||||
resourceId = inResourceId;
|
||||
port = inPort;
|
||||
fileDescriptor = (status == IpSecManager.Status.OK) ? ParcelFileDescriptor.dup(inFd) : null;
|
||||
}
|
||||
|
||||
private IpSecUdpEncapResponse(Parcel in) {
|
||||
status = in.readInt();
|
||||
resourceId = in.readInt();
|
||||
port = in.readInt();
|
||||
fileDescriptor = in.readParcelable(ParcelFileDescriptor.class.getClassLoader());
|
||||
}
|
||||
|
||||
public static final @android.annotation.NonNull Parcelable.Creator<IpSecUdpEncapResponse> CREATOR =
|
||||
new Parcelable.Creator<IpSecUdpEncapResponse>() {
|
||||
public IpSecUdpEncapResponse createFromParcel(Parcel in) {
|
||||
return new IpSecUdpEncapResponse(in);
|
||||
}
|
||||
|
||||
public IpSecUdpEncapResponse[] newArray(int size) {
|
||||
return new IpSecUdpEncapResponse[size];
|
||||
}
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user