Merge "Javadoc cleanup of IpSecManager API." am: d09d106ec0 am: f96bfee165
am: 3947cda36f
Change-Id: Id10e39da5495f9367332cbc5c754506fc64f3c75
This commit is contained in:
@@ -15,6 +15,7 @@
|
|||||||
*/
|
*/
|
||||||
package android.net;
|
package android.net;
|
||||||
|
|
||||||
|
import android.annotation.NonNull;
|
||||||
import android.annotation.StringDef;
|
import android.annotation.StringDef;
|
||||||
import android.os.Build;
|
import android.os.Build;
|
||||||
import android.os.Parcel;
|
import android.os.Parcel;
|
||||||
@@ -27,8 +28,10 @@ import java.lang.annotation.RetentionPolicy;
|
|||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* IpSecAlgorithm specifies a single algorithm that can be applied to an IpSec Transform. Refer to
|
* This class represents a single algorithm that can be used by an {@link IpSecTransform}.
|
||||||
* RFC 4301.
|
*
|
||||||
|
* @see <a href="https://tools.ietf.org/html/rfc4301">RFC 4301, Security Architecture for the
|
||||||
|
* Internet Protocol</a>
|
||||||
*/
|
*/
|
||||||
public final class IpSecAlgorithm implements Parcelable {
|
public final class IpSecAlgorithm implements Parcelable {
|
||||||
/**
|
/**
|
||||||
@@ -39,16 +42,16 @@ public final class IpSecAlgorithm implements Parcelable {
|
|||||||
public static final String CRYPT_AES_CBC = "cbc(aes)";
|
public static final String CRYPT_AES_CBC = "cbc(aes)";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* MD5 HMAC Authentication/Integrity Algorithm. This algorithm is not recommended for use in new
|
* MD5 HMAC Authentication/Integrity Algorithm. <b>This algorithm is not recommended for use in
|
||||||
* applications and is provided for legacy compatibility with 3gpp infrastructure.
|
* new applications and is provided for legacy compatibility with 3gpp infrastructure.</b>
|
||||||
*
|
*
|
||||||
* <p>Valid truncation lengths are multiples of 8 bits from 96 to (default) 128.
|
* <p>Valid truncation lengths are multiples of 8 bits from 96 to (default) 128.
|
||||||
*/
|
*/
|
||||||
public static final String AUTH_HMAC_MD5 = "hmac(md5)";
|
public static final String AUTH_HMAC_MD5 = "hmac(md5)";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* SHA1 HMAC Authentication/Integrity Algorithm. This algorithm is not recommended for use in
|
* SHA1 HMAC Authentication/Integrity Algorithm. <b>This algorithm is not recommended for use in
|
||||||
* new applications and is provided for legacy compatibility with 3gpp infrastructure.
|
* new applications and is provided for legacy compatibility with 3gpp infrastructure.</b>
|
||||||
*
|
*
|
||||||
* <p>Valid truncation lengths are multiples of 8 bits from 96 to (default) 160.
|
* <p>Valid truncation lengths are multiples of 8 bits from 96 to (default) 160.
|
||||||
*/
|
*/
|
||||||
@@ -69,7 +72,7 @@ public final class IpSecAlgorithm implements Parcelable {
|
|||||||
public static final String AUTH_HMAC_SHA384 = "hmac(sha384)";
|
public static final String AUTH_HMAC_SHA384 = "hmac(sha384)";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* SHA512 HMAC Authentication/Integrity Algorithm
|
* SHA512 HMAC Authentication/Integrity Algorithm.
|
||||||
*
|
*
|
||||||
* <p>Valid truncation lengths are multiples of 8 bits from 256 to (default) 512.
|
* <p>Valid truncation lengths are multiples of 8 bits from 256 to (default) 512.
|
||||||
*/
|
*/
|
||||||
@@ -80,9 +83,9 @@ public final class IpSecAlgorithm implements Parcelable {
|
|||||||
*
|
*
|
||||||
* <p>Valid lengths for keying material are {160, 224, 288}.
|
* <p>Valid lengths for keying material are {160, 224, 288}.
|
||||||
*
|
*
|
||||||
* <p>As per RFC4106 (Section 8.1), keying material consists of a 128, 192, or 256 bit AES key
|
* <p>As per <a href="https://tools.ietf.org/html/rfc4106#section-8.1">RFC4106 (Section
|
||||||
* followed by a 32-bit salt. RFC compliance requires that the salt must be unique per
|
* 8.1)</a>, keying material consists of a 128, 192, or 256 bit AES key followed by a 32-bit
|
||||||
* invocation with the same key.
|
* 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}.
|
* <p>Valid ICV (truncation) lengths are {64, 96, 128}.
|
||||||
*/
|
*/
|
||||||
@@ -105,48 +108,47 @@ public final class IpSecAlgorithm implements Parcelable {
|
|||||||
private final int mTruncLenBits;
|
private final int mTruncLenBits;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Specify a IpSecAlgorithm of one of the supported types including the truncation length of the
|
* Creates an IpSecAlgorithm of one of the supported types. Supported algorithm names are
|
||||||
* algorithm
|
* defined as constants in this class.
|
||||||
*
|
*
|
||||||
* @param algorithm type for IpSec.
|
* @param algorithm name of the algorithm.
|
||||||
* @param key non-null Key padded to a multiple of 8 bits.
|
* @param key key padded to a multiple of 8 bits.
|
||||||
*/
|
*/
|
||||||
public IpSecAlgorithm(String algorithm, byte[] key) {
|
public IpSecAlgorithm(@AlgorithmName String algorithm, @NonNull byte[] key) {
|
||||||
this(algorithm, key, key.length * 8);
|
this(algorithm, key, key.length * 8);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Specify a IpSecAlgorithm of one of the supported types including the truncation length of the
|
* Creates an IpSecAlgorithm of one of the supported types. Supported algorithm names are
|
||||||
* algorithm
|
* defined as constants in this class.
|
||||||
*
|
*
|
||||||
* @param algoName precise name of the algorithm to be used.
|
* <p>This constructor only supports algorithms that use a truncation length. i.e.
|
||||||
* @param key non-null Key padded to a multiple of 8 bits.
|
* Authentication and Authenticated Encryption algorithms.
|
||||||
* @param truncLenBits the number of bits of output hash to use; only meaningful for
|
*
|
||||||
* Authentication or Authenticated Encryption (equivalent to ICV length).
|
* @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.
|
||||||
*/
|
*/
|
||||||
public IpSecAlgorithm(@AlgorithmName String algoName, byte[] key, int truncLenBits) {
|
public IpSecAlgorithm(@AlgorithmName String algorithm, @NonNull byte[] key, int truncLenBits) {
|
||||||
if (!isTruncationLengthValid(algoName, truncLenBits)) {
|
if (!isTruncationLengthValid(algorithm, truncLenBits)) {
|
||||||
throw new IllegalArgumentException("Unknown algorithm or invalid length");
|
throw new IllegalArgumentException("Unknown algorithm or invalid length");
|
||||||
}
|
}
|
||||||
mName = algoName;
|
mName = algorithm;
|
||||||
mKey = key.clone();
|
mKey = key.clone();
|
||||||
mTruncLenBits = Math.min(truncLenBits, key.length * 8);
|
mTruncLenBits = Math.min(truncLenBits, key.length * 8);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Retrieve the algorithm name */
|
/** Get the algorithm name */
|
||||||
public String getName() {
|
public String getName() {
|
||||||
return mName;
|
return mName;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Retrieve the key for this algorithm */
|
/** Get the key for this algorithm */
|
||||||
public byte[] getKey() {
|
public byte[] getKey() {
|
||||||
return mKey.clone();
|
return mKey.clone();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/** Get the truncation length of this algorithm, in bits */
|
||||||
* Retrieve the truncation length, in bits, for the key in this algo. By default this will be
|
|
||||||
* the length in bits of the key.
|
|
||||||
*/
|
|
||||||
public int getTruncationLengthBits() {
|
public int getTruncationLengthBits() {
|
||||||
return mTruncLenBits;
|
return mTruncLenBits;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,7 +20,12 @@ import android.os.Parcelable;
|
|||||||
|
|
||||||
import com.android.internal.annotations.VisibleForTesting;
|
import com.android.internal.annotations.VisibleForTesting;
|
||||||
|
|
||||||
/** @hide */
|
/**
|
||||||
|
* This class encapsulates all the configuration parameters needed to create IPsec transforms and
|
||||||
|
* policies.
|
||||||
|
*
|
||||||
|
* @hide
|
||||||
|
*/
|
||||||
public final class IpSecConfig implements Parcelable {
|
public final class IpSecConfig implements Parcelable {
|
||||||
private static final String TAG = "IpSecConfig";
|
private static final String TAG = "IpSecConfig";
|
||||||
|
|
||||||
@@ -38,6 +43,9 @@ public final class IpSecConfig implements Parcelable {
|
|||||||
// for outbound packets. It may also be used to select packets.
|
// for outbound packets. It may also be used to select packets.
|
||||||
private Network mNetwork;
|
private Network mNetwork;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This class captures the parameters that specifically apply to inbound or outbound traffic.
|
||||||
|
*/
|
||||||
public static class Flow {
|
public static class Flow {
|
||||||
// Minimum requirements for identifying a transform
|
// Minimum requirements for identifying a transform
|
||||||
// SPI identifying the IPsec flow in packet processing
|
// SPI identifying the IPsec flow in packet processing
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ import static com.android.internal.util.Preconditions.checkNotNull;
|
|||||||
|
|
||||||
import android.annotation.NonNull;
|
import android.annotation.NonNull;
|
||||||
import android.annotation.SystemService;
|
import android.annotation.SystemService;
|
||||||
|
import android.annotation.TestApi;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.os.Binder;
|
import android.os.Binder;
|
||||||
import android.os.ParcelFileDescriptor;
|
import android.os.ParcelFileDescriptor;
|
||||||
@@ -37,22 +38,28 @@ import java.net.InetAddress;
|
|||||||
import java.net.Socket;
|
import java.net.Socket;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This class contains methods for managing IPsec sessions, which will perform kernel-space
|
* This class contains methods for managing IPsec sessions. Once configured, the kernel will apply
|
||||||
* encryption and decryption of socket or Network traffic.
|
* confidentiality (encryption) and integrity (authentication) to IP traffic.
|
||||||
*
|
*
|
||||||
* <p>An IpSecManager may be obtained by calling {@link
|
* <p>Note that not all aspects of IPsec are permitted by this API. Applications may create
|
||||||
* android.content.Context#getSystemService(String) Context#getSystemService(String)} with {@link
|
* transport mode security associations and apply them to individual sockets. Applications looking
|
||||||
* android.content.Context#IPSEC_SERVICE Context#IPSEC_SERVICE}
|
* to create a VPN should use {@link VpnService}.
|
||||||
|
*
|
||||||
|
* @see <a href="https://tools.ietf.org/html/rfc4301">RFC 4301, Security Architecture for the
|
||||||
|
* Internet Protocol</a>
|
||||||
*/
|
*/
|
||||||
@SystemService(Context.IPSEC_SERVICE)
|
@SystemService(Context.IPSEC_SERVICE)
|
||||||
public final class IpSecManager {
|
public final class IpSecManager {
|
||||||
private static final String TAG = "IpSecManager";
|
private static final String TAG = "IpSecManager";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The Security Parameter Index, SPI, 0 indicates an unknown or invalid index.
|
* The Security Parameter Index (SPI) 0 indicates an unknown or invalid index.
|
||||||
*
|
*
|
||||||
* <p>No IPsec packet may contain an SPI of 0.
|
* <p>No IPsec packet may contain an SPI of 0.
|
||||||
|
*
|
||||||
|
* @hide
|
||||||
*/
|
*/
|
||||||
|
@TestApi
|
||||||
public static final int INVALID_SECURITY_PARAMETER_INDEX = 0;
|
public static final int INVALID_SECURITY_PARAMETER_INDEX = 0;
|
||||||
|
|
||||||
/** @hide */
|
/** @hide */
|
||||||
@@ -66,10 +73,12 @@ public final class IpSecManager {
|
|||||||
public static final int INVALID_RESOURCE_ID = 0;
|
public static final int INVALID_RESOURCE_ID = 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Indicates that the combination of remote InetAddress and SPI was non-unique for a given
|
* Thrown to indicate that a requested SPI is in use.
|
||||||
* request. If encountered, selection of a new SPI is required before a transform may be
|
*
|
||||||
* created. Note, this should happen very rarely if the SPI is chosen to be sufficiently random
|
* <p>The combination of remote {@code InetAddress} and SPI must be unique across all apps on
|
||||||
* or reserved using reserveSecurityParameterIndex.
|
* one device. If this error is encountered, a new SPI is required before a transform may be
|
||||||
|
* created. This error can be avoided by calling {@link
|
||||||
|
* IpSecManager#reserveSecurityParameterIndex}.
|
||||||
*/
|
*/
|
||||||
public static final class SpiUnavailableException extends AndroidException {
|
public static final class SpiUnavailableException extends AndroidException {
|
||||||
private final int mSpi;
|
private final int mSpi;
|
||||||
@@ -78,24 +87,26 @@ public final class IpSecManager {
|
|||||||
* Construct an exception indicating that a transform with the given SPI is already in use
|
* Construct an exception indicating that a transform with the given SPI is already in use
|
||||||
* or otherwise unavailable.
|
* or otherwise unavailable.
|
||||||
*
|
*
|
||||||
* @param msg Description indicating the colliding SPI
|
* @param msg description indicating the colliding SPI
|
||||||
* @param spi the SPI that could not be used due to a collision
|
* @param spi the SPI that could not be used due to a collision
|
||||||
*/
|
*/
|
||||||
SpiUnavailableException(String msg, int spi) {
|
SpiUnavailableException(String msg, int spi) {
|
||||||
super(msg + "(spi: " + spi + ")");
|
super(msg + " (spi: " + spi + ")");
|
||||||
mSpi = spi;
|
mSpi = spi;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Retrieve the SPI that caused a collision */
|
/** Get the SPI that caused a collision. */
|
||||||
public int getSpi() {
|
public int getSpi() {
|
||||||
return mSpi;
|
return mSpi;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Indicates that the requested system resource for IPsec, such as a socket or other system
|
* Thrown to indicate that an IPsec resource is unavailable.
|
||||||
* resource is unavailable. If this exception is thrown, try releasing allocated objects of the
|
*
|
||||||
* type requested.
|
* <p>This could apply to resources such as sockets, {@link SecurityParameterIndex}, {@link
|
||||||
|
* IpSecTransform}, or other system resources. If this exception is thrown, users should release
|
||||||
|
* allocated objects of the type requested.
|
||||||
*/
|
*/
|
||||||
public static final class ResourceUnavailableException extends AndroidException {
|
public static final class ResourceUnavailableException extends AndroidException {
|
||||||
|
|
||||||
@@ -106,6 +117,13 @@ public final class IpSecManager {
|
|||||||
|
|
||||||
private final IIpSecService mService;
|
private final IIpSecService mService;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This class represents a reserved SPI.
|
||||||
|
*
|
||||||
|
* <p>Objects of this type are used to track reserved security parameter indices. They can be
|
||||||
|
* obtained by calling {@link IpSecManager#reserveSecurityParameterIndex} and must be released
|
||||||
|
* by calling {@link #close()} when they are no longer needed.
|
||||||
|
*/
|
||||||
public static final class SecurityParameterIndex implements AutoCloseable {
|
public static final class SecurityParameterIndex implements AutoCloseable {
|
||||||
private final IIpSecService mService;
|
private final IIpSecService mService;
|
||||||
private final InetAddress mRemoteAddress;
|
private final InetAddress mRemoteAddress;
|
||||||
@@ -113,7 +131,7 @@ public final class IpSecManager {
|
|||||||
private int mSpi = INVALID_SECURITY_PARAMETER_INDEX;
|
private int mSpi = INVALID_SECURITY_PARAMETER_INDEX;
|
||||||
private int mResourceId;
|
private int mResourceId;
|
||||||
|
|
||||||
/** Return the underlying SPI held by this object */
|
/** Get the underlying SPI held by this object. */
|
||||||
public int getSpi() {
|
public int getSpi() {
|
||||||
return mSpi;
|
return mSpi;
|
||||||
}
|
}
|
||||||
@@ -135,6 +153,7 @@ public final class IpSecManager {
|
|||||||
mCloseGuard.close();
|
mCloseGuard.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Check that the SPI was closed properly. */
|
||||||
@Override
|
@Override
|
||||||
protected void finalize() throws Throwable {
|
protected void finalize() throws Throwable {
|
||||||
if (mCloseGuard != null) {
|
if (mCloseGuard != null) {
|
||||||
@@ -197,13 +216,13 @@ public final class IpSecManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Reserve an SPI for traffic bound towards the specified remote address.
|
* Reserve a random SPI for traffic bound to or from the specified remote address.
|
||||||
*
|
*
|
||||||
* <p>If successful, this SPI is guaranteed available until released by a call to {@link
|
* <p>If successful, this SPI is guaranteed available until released by a call to {@link
|
||||||
* SecurityParameterIndex#close()}.
|
* SecurityParameterIndex#close()}.
|
||||||
*
|
*
|
||||||
* @param direction {@link IpSecTransform#DIRECTION_IN} or {@link IpSecTransform#DIRECTION_OUT}
|
* @param direction {@link IpSecTransform#DIRECTION_IN} or {@link IpSecTransform#DIRECTION_OUT}
|
||||||
* @param remoteAddress address of the remote. SPIs must be unique for each remoteAddress.
|
* @param remoteAddress address of the remote. SPIs must be unique for each remoteAddress
|
||||||
* @return the reserved SecurityParameterIndex
|
* @return the reserved SecurityParameterIndex
|
||||||
* @throws ResourceUnavailableException indicating that too many SPIs are currently allocated
|
* @throws ResourceUnavailableException indicating that too many SPIs are currently allocated
|
||||||
* for this user
|
* for this user
|
||||||
@@ -223,17 +242,18 @@ public final class IpSecManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Reserve an SPI for traffic bound towards the specified remote address.
|
* Reserve the requested SPI for traffic bound to or from the specified remote address.
|
||||||
*
|
*
|
||||||
* <p>If successful, this SPI is guaranteed available until released by a call to {@link
|
* <p>If successful, this SPI is guaranteed available until released by a call to {@link
|
||||||
* SecurityParameterIndex#close()}.
|
* SecurityParameterIndex#close()}.
|
||||||
*
|
*
|
||||||
* @param direction {@link IpSecTransform#DIRECTION_IN} or {@link IpSecTransform#DIRECTION_OUT}
|
* @param direction {@link IpSecTransform#DIRECTION_IN} or {@link IpSecTransform#DIRECTION_OUT}
|
||||||
* @param remoteAddress address of the remote. SPIs must be unique for each remoteAddress.
|
* @param remoteAddress address of the remote. SPIs must be unique for each remoteAddress
|
||||||
* @param requestedSpi the requested SPI, or '0' to allocate a random SPI.
|
* @param requestedSpi the requested SPI, or '0' to allocate a random SPI
|
||||||
* @return the reserved SecurityParameterIndex
|
* @return the reserved SecurityParameterIndex
|
||||||
* @throws ResourceUnavailableException indicating that too many SPIs are currently allocated
|
* @throws ResourceUnavailableException indicating that too many SPIs are currently allocated
|
||||||
* for this user
|
* for this user
|
||||||
|
* @throws SpiUnavailableException indicating that the requested SPI could not be reserved
|
||||||
*/
|
*/
|
||||||
public SecurityParameterIndex reserveSecurityParameterIndex(
|
public SecurityParameterIndex reserveSecurityParameterIndex(
|
||||||
int direction, InetAddress remoteAddress, int requestedSpi)
|
int direction, InetAddress remoteAddress, int requestedSpi)
|
||||||
@@ -245,16 +265,28 @@ public final class IpSecManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Apply an active Transport Mode IPsec Transform to a stream socket to perform IPsec
|
* Apply an IPsec transform to a stream socket.
|
||||||
* encapsulation of the traffic flowing between the socket and the remote InetAddress of that
|
*
|
||||||
* transform. For security reasons, attempts to send traffic to any IP address other than the
|
* <p>This applies transport mode encapsulation to the given socket. Once applied, I/O on the
|
||||||
* address associated with that transform will throw an IOException. In addition, if the
|
* socket will be encapsulated according to the parameters of the {@code IpSecTransform}. When
|
||||||
* IpSecTransform is later deactivated, the socket will throw an IOException on any calls to
|
* the transform is removed from the socket by calling {@link #removeTransportModeTransform},
|
||||||
* send() or receive() until the transform is removed from the socket by calling {@link
|
* unprotected traffic can resume on that socket.
|
||||||
* #removeTransportModeTransform(Socket, IpSecTransform)};
|
*
|
||||||
|
* <p>For security reasons, the destination address of any traffic on the socket must match the
|
||||||
|
* remote {@code InetAddress} of the {@code IpSecTransform}. Attempts to send traffic to any
|
||||||
|
* other IP address will result in an IOException. In addition, reads and writes on the socket
|
||||||
|
* will throw IOException if the user deactivates the transform (by calling {@link
|
||||||
|
* IpSecTransform#close()}) without calling {@link #removeTransportModeTransform}.
|
||||||
|
*
|
||||||
|
* <h4>Rekey Procedure</h4> <p>When applying a new tranform to a socket, the previous transform
|
||||||
|
* will be removed. However, inbound traffic on the old transform will continue to be decrypted
|
||||||
|
* until that transform is deallocated by calling {@link IpSecTransform#close()}. This overlap
|
||||||
|
* allows rekey procedures where both transforms are valid until both endpoints are using the
|
||||||
|
* new transform and all in-flight packets have been received.
|
||||||
*
|
*
|
||||||
* @param socket a stream socket
|
* @param socket a stream socket
|
||||||
* @param transform an {@link IpSecTransform}, which must be an active Transport Mode transform.
|
* @param transform a transport mode {@code IpSecTransform}
|
||||||
|
* @throws IOException indicating that the transform could not be applied
|
||||||
* @hide
|
* @hide
|
||||||
*/
|
*/
|
||||||
public void applyTransportModeTransform(Socket socket, IpSecTransform transform)
|
public void applyTransportModeTransform(Socket socket, IpSecTransform transform)
|
||||||
@@ -265,16 +297,28 @@ public final class IpSecManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Apply an active Transport Mode IPsec Transform to a datagram socket to perform IPsec
|
* Apply an IPsec transform to a datagram socket.
|
||||||
* encapsulation of the traffic flowing between the socket and the remote InetAddress of that
|
*
|
||||||
* transform. For security reasons, attempts to send traffic to any IP address other than the
|
* <p>This applies transport mode encapsulation to the given socket. Once applied, I/O on the
|
||||||
* address associated with that transform will throw an IOException. In addition, if the
|
* socket will be encapsulated according to the parameters of the {@code IpSecTransform}. When
|
||||||
* IpSecTransform is later deactivated, the socket will throw an IOException on any calls to
|
* the transform is removed from the socket by calling {@link #removeTransportModeTransform},
|
||||||
* send() or receive() until the transform is removed from the socket by calling {@link
|
* unprotected traffic can resume on that socket.
|
||||||
* #removeTransportModeTransform(DatagramSocket, IpSecTransform)};
|
*
|
||||||
|
* <p>For security reasons, the destination address of any traffic on the socket must match the
|
||||||
|
* remote {@code InetAddress} of the {@code IpSecTransform}. Attempts to send traffic to any
|
||||||
|
* other IP address will result in an IOException. In addition, reads and writes on the socket
|
||||||
|
* will throw IOException if the user deactivates the transform (by calling {@link
|
||||||
|
* IpSecTransform#close()}) without calling {@link #removeTransportModeTransform}.
|
||||||
|
*
|
||||||
|
* <h4>Rekey Procedure</h4> <p>When applying a new tranform to a socket, the previous transform
|
||||||
|
* will be removed. However, inbound traffic on the old transform will continue to be decrypted
|
||||||
|
* until that transform is deallocated by calling {@link IpSecTransform#close()}. This overlap
|
||||||
|
* allows rekey procedures where both transforms are valid until both endpoints are using the
|
||||||
|
* new transform and all in-flight packets have been received.
|
||||||
*
|
*
|
||||||
* @param socket a datagram socket
|
* @param socket a datagram socket
|
||||||
* @param transform an {@link IpSecTransform}, which must be an active Transport Mode transform.
|
* @param transform a transport mode {@code IpSecTransform}
|
||||||
|
* @throws IOException indicating that the transform could not be applied
|
||||||
* @hide
|
* @hide
|
||||||
*/
|
*/
|
||||||
public void applyTransportModeTransform(DatagramSocket socket, IpSecTransform transform)
|
public void applyTransportModeTransform(DatagramSocket socket, IpSecTransform transform)
|
||||||
@@ -285,16 +329,28 @@ public final class IpSecManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Apply an active Transport Mode IPsec Transform to a stream socket to perform IPsec
|
* Apply an IPsec transform to a socket.
|
||||||
* encapsulation of the traffic flowing between the socket and the remote InetAddress of that
|
*
|
||||||
* transform. For security reasons, attempts to send traffic to any IP address other than the
|
* <p>This applies transport mode encapsulation to the given socket. Once applied, I/O on the
|
||||||
* address associated with that transform will throw an IOException. In addition, if the
|
* socket will be encapsulated according to the parameters of the {@code IpSecTransform}. When
|
||||||
* IpSecTransform is later deactivated, the socket will throw an IOException on any calls to
|
* the transform is removed from the socket by calling {@link #removeTransportModeTransform},
|
||||||
* send() or receive() until the transform is removed from the socket by calling {@link
|
* unprotected traffic can resume on that socket.
|
||||||
* #removeTransportModeTransform(FileDescriptor, IpSecTransform)};
|
*
|
||||||
|
* <p>For security reasons, the destination address of any traffic on the socket must match the
|
||||||
|
* remote {@code InetAddress} of the {@code IpSecTransform}. Attempts to send traffic to any
|
||||||
|
* other IP address will result in an IOException. In addition, reads and writes on the socket
|
||||||
|
* will throw IOException if the user deactivates the transform (by calling {@link
|
||||||
|
* IpSecTransform#close()}) without calling {@link #removeTransportModeTransform}.
|
||||||
|
*
|
||||||
|
* <h4>Rekey Procedure</h4> <p>When applying a new tranform to a socket, the previous transform
|
||||||
|
* will be removed. However, inbound traffic on the old transform will continue to be decrypted
|
||||||
|
* until that transform is deallocated by calling {@link IpSecTransform#close()}. This overlap
|
||||||
|
* allows rekey procedures where both transforms are valid until both endpoints are using the
|
||||||
|
* new transform and all in-flight packets have been received.
|
||||||
*
|
*
|
||||||
* @param socket a socket file descriptor
|
* @param socket a socket file descriptor
|
||||||
* @param transform an {@link IpSecTransform}, which must be an active Transport Mode transform.
|
* @param transform a transport mode {@code IpSecTransform}
|
||||||
|
* @throws IOException indicating that the transform could not be applied
|
||||||
*/
|
*/
|
||||||
public void applyTransportModeTransform(FileDescriptor socket, IpSecTransform transform)
|
public void applyTransportModeTransform(FileDescriptor socket, IpSecTransform transform)
|
||||||
throws IOException {
|
throws IOException {
|
||||||
@@ -323,6 +379,7 @@ public final class IpSecManager {
|
|||||||
* Applications should probably not use this API directly. Instead, they should use {@link
|
* Applications should probably not use this API directly. Instead, they should use {@link
|
||||||
* VpnService} to provide VPN capability in a more generic fashion.
|
* VpnService} to provide VPN capability in a more generic fashion.
|
||||||
*
|
*
|
||||||
|
* TODO: Update javadoc for tunnel mode APIs at the same time the APIs are re-worked.
|
||||||
* @param net a {@link Network} that will be tunneled via IP Sec.
|
* @param net a {@link Network} that will be tunneled via IP Sec.
|
||||||
* @param transform an {@link IpSecTransform}, which must be an active Tunnel Mode transform.
|
* @param transform an {@link IpSecTransform}, which must be an active Tunnel Mode transform.
|
||||||
* @hide
|
* @hide
|
||||||
@@ -330,14 +387,19 @@ public final class IpSecManager {
|
|||||||
public void applyTunnelModeTransform(Network net, IpSecTransform transform) {}
|
public void applyTunnelModeTransform(Network net, IpSecTransform transform) {}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Remove a transform from a given stream socket. Once removed, traffic on the socket will not
|
* Remove an IPsec transform from a stream socket.
|
||||||
* be encypted. This allows sockets that have been used for IPsec to be reclaimed for
|
|
||||||
* communication in the clear in the event socket reuse is desired. This operation will succeed
|
|
||||||
* regardless of the underlying state of a transform. If a transform is removed, communication
|
|
||||||
* on all sockets to which that transform was applied will fail until this method is called.
|
|
||||||
*
|
*
|
||||||
* @param socket a socket that previously had a transform applied to it.
|
* <p>Once removed, traffic on the socket will not be encrypted. This operation will succeed
|
||||||
|
* regardless of the state of the transform. Removing a transform from a socket allows the
|
||||||
|
* socket to be reused for communication in the clear.
|
||||||
|
*
|
||||||
|
* <p>If an {@code IpSecTransform} object applied to this socket was deallocated by calling
|
||||||
|
* {@link IpSecTransform#close()}, then communication on the socket will fail until this method
|
||||||
|
* is called.
|
||||||
|
*
|
||||||
|
* @param socket a socket that previously had a transform applied to it
|
||||||
* @param transform the IPsec Transform that was previously applied to the given socket
|
* @param transform the IPsec Transform that was previously applied to the given socket
|
||||||
|
* @throws IOException indicating that the transform could not be removed from the socket
|
||||||
* @hide
|
* @hide
|
||||||
*/
|
*/
|
||||||
public void removeTransportModeTransform(Socket socket, IpSecTransform transform)
|
public void removeTransportModeTransform(Socket socket, IpSecTransform transform)
|
||||||
@@ -348,14 +410,19 @@ public final class IpSecManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Remove a transform from a given datagram socket. Once removed, traffic on the socket will not
|
* Remove an IPsec transform from a datagram socket.
|
||||||
* be encypted. This allows sockets that have been used for IPsec to be reclaimed for
|
|
||||||
* communication in the clear in the event socket reuse is desired. This operation will succeed
|
|
||||||
* regardless of the underlying state of a transform. If a transform is removed, communication
|
|
||||||
* on all sockets to which that transform was applied will fail until this method is called.
|
|
||||||
*
|
*
|
||||||
* @param socket a socket that previously had a transform applied to it.
|
* <p>Once removed, traffic on the socket will not be encrypted. This operation will succeed
|
||||||
|
* regardless of the state of the transform. Removing a transform from a socket allows the
|
||||||
|
* socket to be reused for communication in the clear.
|
||||||
|
*
|
||||||
|
* <p>If an {@code IpSecTransform} object applied to this socket was deallocated by calling
|
||||||
|
* {@link IpSecTransform#close()}, then communication on the socket will fail until this method
|
||||||
|
* is called.
|
||||||
|
*
|
||||||
|
* @param socket a socket that previously had a transform applied to it
|
||||||
* @param transform the IPsec Transform that was previously applied to the given socket
|
* @param transform the IPsec Transform that was previously applied to the given socket
|
||||||
|
* @throws IOException indicating that the transform could not be removed from the socket
|
||||||
* @hide
|
* @hide
|
||||||
*/
|
*/
|
||||||
public void removeTransportModeTransform(DatagramSocket socket, IpSecTransform transform)
|
public void removeTransportModeTransform(DatagramSocket socket, IpSecTransform transform)
|
||||||
@@ -366,14 +433,19 @@ public final class IpSecManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Remove a transform from a given stream socket. Once removed, traffic on the socket will not
|
* Remove an IPsec transform from a socket.
|
||||||
* be encypted. This allows sockets that have been used for IPsec to be reclaimed for
|
|
||||||
* communication in the clear in the event socket reuse is desired. This operation will succeed
|
|
||||||
* regardless of the underlying state of a transform. If a transform is removed, communication
|
|
||||||
* on all sockets to which that transform was applied will fail until this method is called.
|
|
||||||
*
|
*
|
||||||
* @param socket a socket file descriptor that previously had a transform applied to it.
|
* <p>Once removed, traffic on the socket will not be encrypted. This operation will succeed
|
||||||
|
* regardless of the state of the transform. Removing a transform from a socket allows the
|
||||||
|
* socket to be reused for communication in the clear.
|
||||||
|
*
|
||||||
|
* <p>If an {@code IpSecTransform} object applied to this socket was deallocated by calling
|
||||||
|
* {@link IpSecTransform#close()}, then communication on the socket will fail until this method
|
||||||
|
* is called.
|
||||||
|
*
|
||||||
|
* @param socket a socket that previously had a transform applied to it
|
||||||
* @param transform the IPsec Transform that was previously applied to the given socket
|
* @param transform the IPsec Transform that was previously applied to the given socket
|
||||||
|
* @throws IOException indicating that the transform could not be removed from the socket
|
||||||
*/
|
*/
|
||||||
public void removeTransportModeTransform(FileDescriptor socket, IpSecTransform transform)
|
public void removeTransportModeTransform(FileDescriptor socket, IpSecTransform transform)
|
||||||
throws IOException {
|
throws IOException {
|
||||||
@@ -382,7 +454,7 @@ public final class IpSecManager {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Call down to activate a transform */
|
/* Call down to remove a transform */
|
||||||
private void removeTransportModeTransform(ParcelFileDescriptor pfd, IpSecTransform transform) {
|
private void removeTransportModeTransform(ParcelFileDescriptor pfd, IpSecTransform transform) {
|
||||||
try {
|
try {
|
||||||
mService.removeTransportModeTransform(pfd, transform.getResourceId());
|
mService.removeTransportModeTransform(pfd, transform.getResourceId());
|
||||||
@@ -397,6 +469,7 @@ public final class IpSecManager {
|
|||||||
* all traffic that cannot be routed to the Tunnel's outbound interface. If that interface is
|
* all traffic that cannot be routed to the Tunnel's outbound interface. If that interface is
|
||||||
* lost, all traffic will drop.
|
* lost, all traffic will drop.
|
||||||
*
|
*
|
||||||
|
* TODO: Update javadoc for tunnel mode APIs at the same time the APIs are re-worked.
|
||||||
* @param net a network that currently has transform applied to it.
|
* @param net a network that currently has transform applied to it.
|
||||||
* @param transform a Tunnel Mode IPsec Transform that has been previously applied to the given
|
* @param transform a Tunnel Mode IPsec Transform that has been previously applied to the given
|
||||||
* network
|
* network
|
||||||
@@ -405,11 +478,18 @@ public final class IpSecManager {
|
|||||||
public void removeTunnelModeTransform(Network net, IpSecTransform transform) {}
|
public void removeTunnelModeTransform(Network net, IpSecTransform transform) {}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class providing access to a system-provided UDP Encapsulation Socket, which may be used for
|
* This class provides access to a UDP encapsulation Socket.
|
||||||
* IKE signalling as well as for inbound and outbound UDP encapsulated IPsec traffic.
|
|
||||||
*
|
*
|
||||||
* <p>The socket provided by this class cannot be re-bound or closed via the inner
|
* <p>{@code UdpEncapsulationSocket} wraps a system-provided datagram socket intended for IKEv2
|
||||||
* FileDescriptor. Instead, disposing of this socket requires a call to close().
|
* signalling and UDP encapsulated IPsec traffic. Instances can be obtained by calling {@link
|
||||||
|
* IpSecManager#openUdpEncapsulationSocket}. The provided socket cannot be re-bound by the
|
||||||
|
* caller. The caller should not close the {@code FileDescriptor} returned by {@link
|
||||||
|
* #getSocket}, but should use {@link #close} instead.
|
||||||
|
*
|
||||||
|
* <p>Allowing the user to close or unbind a UDP encapsulation socket could impact the traffic
|
||||||
|
* of the next user who binds to that port. To prevent this scenario, these sockets are held
|
||||||
|
* open by the system so that they may only be closed by calling {@link #close} or when the user
|
||||||
|
* process exits.
|
||||||
*/
|
*/
|
||||||
public static final class UdpEncapsulationSocket implements AutoCloseable {
|
public static final class UdpEncapsulationSocket implements AutoCloseable {
|
||||||
private final ParcelFileDescriptor mPfd;
|
private final ParcelFileDescriptor mPfd;
|
||||||
@@ -443,7 +523,7 @@ public final class IpSecManager {
|
|||||||
mCloseGuard.open("constructor");
|
mCloseGuard.open("constructor");
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Access the inner UDP Encapsulation Socket */
|
/** Get the wrapped socket. */
|
||||||
public FileDescriptor getSocket() {
|
public FileDescriptor getSocket() {
|
||||||
if (mPfd == null) {
|
if (mPfd == null) {
|
||||||
return null;
|
return null;
|
||||||
@@ -451,22 +531,19 @@ public final class IpSecManager {
|
|||||||
return mPfd.getFileDescriptor();
|
return mPfd.getFileDescriptor();
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Retrieve the port number of the inner encapsulation socket */
|
/** Get the bound port of the wrapped socket. */
|
||||||
public int getPort() {
|
public int getPort() {
|
||||||
return mPort;
|
return mPort;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
/**
|
/**
|
||||||
* Release the resources that have been reserved for this Socket.
|
* Close this socket.
|
||||||
*
|
*
|
||||||
* <p>This method closes the underlying socket, reducing a user's allocated sockets in the
|
* <p>This closes the wrapped socket. Open encapsulation sockets count against a user's
|
||||||
* system. This must be done as part of cleanup following use of a socket. Failure to do so
|
* resource limits, and forgetting to close them eventually will result in {@link
|
||||||
* will cause the socket to count against a total allocation limit for IpSec and eventually
|
* ResourceUnavailableException} being thrown.
|
||||||
* fail due to resource limits.
|
|
||||||
*
|
|
||||||
* @param fd a file descriptor previously returned as a UDP Encapsulation socket.
|
|
||||||
*/
|
*/
|
||||||
|
@Override
|
||||||
public void close() throws IOException {
|
public void close() throws IOException {
|
||||||
try {
|
try {
|
||||||
mService.closeUdpEncapsulationSocket(mResourceId);
|
mService.closeUdpEncapsulationSocket(mResourceId);
|
||||||
@@ -483,6 +560,7 @@ public final class IpSecManager {
|
|||||||
mCloseGuard.close();
|
mCloseGuard.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Check that the socket was closed properly. */
|
||||||
@Override
|
@Override
|
||||||
protected void finalize() throws Throwable {
|
protected void finalize() throws Throwable {
|
||||||
if (mCloseGuard != null) {
|
if (mCloseGuard != null) {
|
||||||
@@ -499,21 +577,14 @@ public final class IpSecManager {
|
|||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Open a socket that is bound to a free UDP port on the system.
|
* Open a socket for UDP encapsulation and bind to the given port.
|
||||||
*
|
*
|
||||||
* <p>By binding in this manner and holding the FileDescriptor, the socket cannot be un-bound by
|
* <p>See {@link UdpEncapsulationSocket} for the proper way to close the returned socket.
|
||||||
* the caller. This provides safe access to a socket on a port that can later be used as a UDP
|
|
||||||
* Encapsulation port.
|
|
||||||
*
|
*
|
||||||
* <p>This socket reservation works in conjunction with IpSecTransforms, which may re-use the
|
* @param port a local UDP port
|
||||||
* socket port. Explicitly opening this port is only necessary if communication is desired on
|
* @return a socket that is bound to the given port
|
||||||
* that port.
|
* @throws IOException indicating that the socket could not be opened or bound
|
||||||
*
|
* @throws ResourceUnavailableException indicating that too many encapsulation sockets are open
|
||||||
* @param port a local UDP port to be reserved for UDP Encapsulation. is provided, then this
|
|
||||||
* method will bind to the specified port or fail. To retrieve the port number, call {@link
|
|
||||||
* android.system.Os#getsockname(FileDescriptor)}.
|
|
||||||
* @return a {@link UdpEncapsulationSocket} that is bound to the requested port for the lifetime
|
|
||||||
* of the object.
|
|
||||||
*/
|
*/
|
||||||
// Returning a socket in this fashion that has been created and bound by the system
|
// Returning a socket in this fashion that has been created and bound by the system
|
||||||
// is the only safe way to ensure that a socket is both accessible to the user and
|
// is the only safe way to ensure that a socket is both accessible to the user and
|
||||||
@@ -533,17 +604,16 @@ public final class IpSecManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Open a socket that is bound to a port selected by the system.
|
* Open a socket for UDP encapsulation.
|
||||||
*
|
*
|
||||||
* <p>By binding in this manner and holding the FileDescriptor, the socket cannot be un-bound by
|
* <p>See {@link UdpEncapsulationSocket} for the proper way to close the returned socket.
|
||||||
* the caller. This provides safe access to a socket on a port that can later be used as a UDP
|
|
||||||
* Encapsulation port.
|
|
||||||
*
|
*
|
||||||
* <p>This socket reservation works in conjunction with IpSecTransforms, which may re-use the
|
* <p>The local port of the returned socket can be obtained by calling {@link
|
||||||
* socket port. Explicitly opening this port is only necessary if communication is desired on
|
* UdpEncapsulationSocket#getPort()}.
|
||||||
* that port.
|
|
||||||
*
|
*
|
||||||
* @return a {@link UdpEncapsulationSocket} that is bound to an arbitrarily selected port
|
* @return a socket that is bound to a local port
|
||||||
|
* @throws IOException indicating that the socket could not be opened or bound
|
||||||
|
* @throws ResourceUnavailableException indicating that too many encapsulation sockets are open
|
||||||
*/
|
*/
|
||||||
// Returning a socket in this fashion that has been created and bound by the system
|
// Returning a socket in this fashion that has been created and bound by the system
|
||||||
// is the only safe way to ensure that a socket is both accessible to the user and
|
// is the only safe way to ensure that a socket is both accessible to the user and
|
||||||
@@ -556,7 +626,7 @@ public final class IpSecManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Retrieve an instance of an IpSecManager within you application context
|
* Construct an instance of IpSecManager within an application context.
|
||||||
*
|
*
|
||||||
* @param context the application context for this manager
|
* @param context the application context for this manager
|
||||||
* @hide
|
* @hide
|
||||||
|
|||||||
@@ -38,27 +38,29 @@ import java.lang.annotation.RetentionPolicy;
|
|||||||
import java.net.InetAddress;
|
import java.net.InetAddress;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This class represents an IpSecTransform, which encapsulates both properties and state of IPsec.
|
* This class represents an IPsec transform, which comprises security associations in one or both
|
||||||
|
* directions.
|
||||||
*
|
*
|
||||||
* <p>IpSecTransforms must be built from an IpSecTransform.Builder, and they must persist throughout
|
* <p>Transforms are created using {@link IpSecTransform.Builder}. Each {@code IpSecTransform}
|
||||||
* the lifetime of the underlying transform. If a transform object leaves scope, the underlying
|
* object encapsulates the properties and state of an inbound and outbound IPsec security
|
||||||
* transform may be disabled automatically, with likely undesirable results.
|
* association. That includes, but is not limited to, algorithm choice, key material, and allocated
|
||||||
|
* system resources.
|
||||||
*
|
*
|
||||||
* <p>An IpSecTransform may either represent a tunnel mode transform that operates on a wide array
|
* @see <a href="https://tools.ietf.org/html/rfc4301">RFC 4301, Security Architecture for the
|
||||||
* of traffic or may represent a transport mode transform operating on a Socket or Sockets.
|
* Internet Protocol</a>
|
||||||
*/
|
*/
|
||||||
public final class IpSecTransform implements AutoCloseable {
|
public final class IpSecTransform implements AutoCloseable {
|
||||||
private static final String TAG = "IpSecTransform";
|
private static final String TAG = "IpSecTransform";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* For direction-specific attributes of an IpSecTransform, indicates that an attribute applies
|
* For direction-specific attributes of an {@link IpSecTransform}, indicates that an attribute
|
||||||
* to traffic towards the host.
|
* applies to traffic towards the host.
|
||||||
*/
|
*/
|
||||||
public static final int DIRECTION_IN = 0;
|
public static final int DIRECTION_IN = 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* For direction-specific attributes of an IpSecTransform, indicates that an attribute applies
|
* For direction-specific attributes of an {@link IpSecTransform}, indicates that an attribute
|
||||||
* to traffic from the host.
|
* applies to traffic from the host.
|
||||||
*/
|
*/
|
||||||
public static final int DIRECTION_OUT = 1;
|
public static final int DIRECTION_OUT = 1;
|
||||||
|
|
||||||
@@ -77,16 +79,16 @@ public final class IpSecTransform implements AutoCloseable {
|
|||||||
public static final int ENCAP_NONE = 0;
|
public static final int ENCAP_NONE = 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* IpSec traffic will be encapsulated within a UDP header with an additional 8-byte header pad
|
* IPsec traffic will be encapsulated within UDP, but with 8 zero-value bytes between the UDP
|
||||||
* (of '0'-value bytes) that prevents traffic from being interpreted as IKE or as ESP over UDP.
|
* header and payload. This prevents traffic from being interpreted as ESP or IKEv2.
|
||||||
*
|
*
|
||||||
* @hide
|
* @hide
|
||||||
*/
|
*/
|
||||||
public static final int ENCAP_ESPINUDP_NON_IKE = 1;
|
public static final int ENCAP_ESPINUDP_NON_IKE = 1;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* IpSec traffic will be encapsulated within UDP as per <a
|
* IPsec traffic will be encapsulated within UDP as per
|
||||||
* href="https://tools.ietf.org/html/rfc3948">RFC3498</a>.
|
* <a href="https://tools.ietf.org/html/rfc3948">RFC 3498</a>.
|
||||||
*
|
*
|
||||||
* @hide
|
* @hide
|
||||||
*/
|
*/
|
||||||
@@ -165,13 +167,14 @@ public final class IpSecTransform implements AutoCloseable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Deactivate an IpSecTransform and free all resources for that transform that are managed by
|
* Deactivate this {@code IpSecTransform} and free allocated resources.
|
||||||
* the system for this Transform.
|
|
||||||
*
|
*
|
||||||
* <p>Deactivating a transform while it is still applied to any Socket will result in sockets
|
* <p>Deactivating a transform while it is still applied to a socket will result in errors on
|
||||||
* refusing to send or receive data. This method will silently succeed if the specified
|
* that socket. Make sure to remove transforms by calling {@link
|
||||||
* transform has already been removed; thus, it is always safe to attempt cleanup when a
|
* IpSecManager#removeTransportModeTransform}. Note, removing an {@code IpSecTransform} from a
|
||||||
* transform is no longer needed.
|
* 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() {
|
public void close() {
|
||||||
Log.d(TAG, "Removing Transform with Id " + mResourceId);
|
Log.d(TAG, "Removing Transform with Id " + mResourceId);
|
||||||
@@ -197,6 +200,7 @@ public final class IpSecTransform implements AutoCloseable {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Check that the transform was closed properly. */
|
||||||
@Override
|
@Override
|
||||||
protected void finalize() throws Throwable {
|
protected void finalize() throws Throwable {
|
||||||
if (mCloseGuard != null) {
|
if (mCloseGuard != null) {
|
||||||
@@ -264,65 +268,63 @@ public final class IpSecTransform implements AutoCloseable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Builder object to facilitate the creation of IpSecTransform objects.
|
* This class is used to build {@link IpSecTransform} objects.
|
||||||
*
|
|
||||||
* <p>Apply additional properties to the transform and then call a build() method to return an
|
|
||||||
* IpSecTransform object.
|
|
||||||
*
|
|
||||||
* @see Builder#buildTransportModeTransform(InetAddress)
|
|
||||||
*/
|
*/
|
||||||
public static class Builder {
|
public static class Builder {
|
||||||
private Context mContext;
|
private Context mContext;
|
||||||
private IpSecConfig mConfig;
|
private IpSecConfig mConfig;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add an encryption algorithm to the transform for the given direction.
|
* Set the encryption algorithm for the given direction.
|
||||||
*
|
*
|
||||||
* <p>If encryption is set for a given direction without also providing an SPI for that
|
* <p>If encryption is set for a direction without also providing an SPI for that direction,
|
||||||
* direction, creation of an IpSecTransform will fail upon calling a build() method.
|
* creation of an {@code IpSecTransform} will fail when attempting to build the transform.
|
||||||
*
|
*
|
||||||
* <p>Authenticated encryption is mutually exclusive with encryption and authentication.
|
* <p>Encryption is mutually exclusive with authenticated encryption.
|
||||||
*
|
*
|
||||||
* @param direction either {@link #DIRECTION_IN or #DIRECTION_OUT}
|
* @param direction either {@link #DIRECTION_IN} or {@link #DIRECTION_OUT}
|
||||||
* @param algo {@link IpSecAlgorithm} specifying the encryption to be applied.
|
* @param algo {@link IpSecAlgorithm} specifying the encryption to be applied.
|
||||||
*/
|
*/
|
||||||
public IpSecTransform.Builder setEncryption(
|
public IpSecTransform.Builder setEncryption(
|
||||||
@TransformDirection int direction, IpSecAlgorithm algo) {
|
@TransformDirection int direction, IpSecAlgorithm algo) {
|
||||||
|
// TODO: throw IllegalArgumentException if algo is not an encryption algorithm.
|
||||||
mConfig.setEncryption(direction, algo);
|
mConfig.setEncryption(direction, algo);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add an authentication/integrity algorithm to the transform.
|
* Set the authentication (integrity) algorithm for the given direction.
|
||||||
*
|
*
|
||||||
* <p>If authentication is set for a given direction without also providing an SPI for that
|
* <p>If authentication is set for a direction without also providing an SPI for that
|
||||||
* direction, creation of an IpSecTransform will fail upon calling a build() method.
|
* direction, creation of an {@code IpSecTransform} will fail when attempting to build the
|
||||||
|
* transform.
|
||||||
*
|
*
|
||||||
* <p>Authenticated encryption is mutually exclusive with encryption and authentication.
|
* <p>Authentication is mutually exclusive with authenticated encryption.
|
||||||
*
|
*
|
||||||
* @param direction either {@link #DIRECTION_IN or #DIRECTION_OUT}
|
* @param direction either {@link #DIRECTION_IN} or {@link #DIRECTION_OUT}
|
||||||
* @param algo {@link IpSecAlgorithm} specifying the authentication to be applied.
|
* @param algo {@link IpSecAlgorithm} specifying the authentication to be applied.
|
||||||
*/
|
*/
|
||||||
public IpSecTransform.Builder setAuthentication(
|
public IpSecTransform.Builder setAuthentication(
|
||||||
@TransformDirection int direction, IpSecAlgorithm algo) {
|
@TransformDirection int direction, IpSecAlgorithm algo) {
|
||||||
|
// TODO: throw IllegalArgumentException if algo is not an authentication algorithm.
|
||||||
mConfig.setAuthentication(direction, algo);
|
mConfig.setAuthentication(direction, algo);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add an authenticated encryption algorithm to the transform for the given direction.
|
* Set the authenticated encryption algorithm for the given direction.
|
||||||
*
|
*
|
||||||
* <p>If an authenticated encryption algorithm is set for a given direction without also
|
* <p>If an authenticated encryption algorithm is set for a given direction without also
|
||||||
* providing an SPI for that direction, creation of an IpSecTransform will fail upon calling
|
* providing an SPI for that direction, creation of an {@code IpSecTransform} will fail when
|
||||||
* a build() method.
|
* attempting to build the transform.
|
||||||
*
|
*
|
||||||
* <p>The Authenticated Encryption (AE) class of algorithms are also known as Authenticated
|
* <p>The Authenticated Encryption (AE) class of algorithms are also known as Authenticated
|
||||||
* Encryption with Associated Data (AEAD) algorithms, or Combined mode algorithms (as
|
* Encryption with Associated Data (AEAD) algorithms, or Combined mode algorithms (as
|
||||||
* referred to in RFC 4301)
|
* referred to in <a href="https://tools.ietf.org/html/rfc4301">RFC 4301</a>).
|
||||||
*
|
*
|
||||||
* <p>Authenticated encryption is mutually exclusive with encryption and authentication.
|
* <p>Authenticated encryption is mutually exclusive with encryption and authentication.
|
||||||
*
|
*
|
||||||
* @param direction either {@link #DIRECTION_IN or #DIRECTION_OUT}
|
* @param direction either {@link #DIRECTION_IN} or {@link #DIRECTION_OUT}
|
||||||
* @param algo {@link IpSecAlgorithm} specifying the authenticated encryption algorithm to
|
* @param algo {@link IpSecAlgorithm} specifying the authenticated encryption algorithm to
|
||||||
* be applied.
|
* be applied.
|
||||||
*/
|
*/
|
||||||
@@ -333,19 +335,16 @@ public final class IpSecTransform implements AutoCloseable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set the SPI, which uniquely identifies a particular IPsec session from others. Because
|
* Set the SPI for the given direction.
|
||||||
* IPsec operates at the IP layer, this 32-bit identifier uniquely identifies packets to a
|
|
||||||
* given destination address.
|
|
||||||
*
|
*
|
||||||
* <p>Care should be chosen when selecting an SPI to ensure that is is as unique as
|
* <p>Because IPsec operates at the IP layer, this 32-bit identifier uniquely identifies
|
||||||
* possible. To reserve a value call {@link IpSecManager#reserveSecurityParameterIndex(int,
|
* packets to a given destination address. To prevent SPI collisions, values should be
|
||||||
* InetAddress, int)}. Otherwise, SPI collisions would prevent a transform from being
|
* reserved by calling {@link IpSecManager#reserveSecurityParameterIndex}.
|
||||||
* activated. IpSecManager#reserveSecurityParameterIndex(int, InetAddres$s, int)}.
|
|
||||||
*
|
*
|
||||||
* <p>Unless an SPI is set for a given direction, traffic in that direction will be
|
* <p>If the SPI and algorithms are omitted for one direction, traffic in that direction
|
||||||
* sent/received without any IPsec applied.
|
* will not be encrypted or authenticated.
|
||||||
*
|
*
|
||||||
* @param direction either {@link #DIRECTION_IN or #DIRECTION_OUT}
|
* @param direction either {@link #DIRECTION_IN} or {@link #DIRECTION_OUT}
|
||||||
* @param spi a unique {@link IpSecManager.SecurityParameterIndex} to identify transformed
|
* @param spi a unique {@link IpSecManager.SecurityParameterIndex} to identify transformed
|
||||||
* traffic
|
* traffic
|
||||||
*/
|
*/
|
||||||
@@ -356,11 +355,10 @@ public final class IpSecTransform implements AutoCloseable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Specify the network on which this transform will emit its traffic; (otherwise it will
|
* Set the {@link Network} which will carry tunneled traffic.
|
||||||
* emit on the default network).
|
|
||||||
*
|
*
|
||||||
* <p>Restricts the transformed traffic to a particular {@link Network}. This is required in
|
* <p>Restricts the transformed traffic to a particular {@link Network}. This is required
|
||||||
* tunnel mode.
|
* for tunnel mode, otherwise tunneled traffic would be sent on the default network.
|
||||||
*
|
*
|
||||||
* @hide
|
* @hide
|
||||||
*/
|
*/
|
||||||
@@ -371,15 +369,18 @@ public final class IpSecTransform implements AutoCloseable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add UDP encapsulation to an IPv4 transform
|
* Add UDP encapsulation to an IPv4 transform.
|
||||||
*
|
*
|
||||||
* <p>This option allows IPsec traffic to pass through NAT. Refer to RFC 3947 and 3948 for
|
* <p>This allows IPsec traffic to pass through a NAT.
|
||||||
* details on how UDP should be applied to IPsec.
|
|
||||||
*
|
*
|
||||||
* @param localSocket a {@link IpSecManager.UdpEncapsulationSocket} for sending and
|
* @see <a href="https://tools.ietf.org/html/rfc3948">RFC 3948, UDP Encapsulation of IPsec
|
||||||
* receiving encapsulating traffic.
|
* ESP Packets</a>
|
||||||
* @param remotePort the UDP port number of the remote that will send and receive
|
* @see <a href="https://tools.ietf.org/html/rfc7296#section-2.23">RFC 7296 section 2.23,
|
||||||
* encapsulated traffic. In the case of IKE, this is likely port 4500.
|
* 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.
|
||||||
*/
|
*/
|
||||||
public IpSecTransform.Builder setIpv4Encapsulation(
|
public IpSecTransform.Builder setIpv4Encapsulation(
|
||||||
IpSecManager.UdpEncapsulationSocket localSocket, int remotePort) {
|
IpSecManager.UdpEncapsulationSocket localSocket, int remotePort) {
|
||||||
@@ -393,12 +394,15 @@ public final class IpSecTransform implements AutoCloseable {
|
|||||||
// TODO: Probably a better exception to throw for NATTKeepalive failure
|
// TODO: Probably a better exception to throw for NATTKeepalive failure
|
||||||
// TODO: Specify the needed NATT keepalive permission.
|
// TODO: Specify the needed NATT keepalive permission.
|
||||||
/**
|
/**
|
||||||
* Send a NATT Keepalive packet with a given maximum interval. This will create an offloaded
|
* Set NAT-T keepalives to be sent with a given interval.
|
||||||
* request to do power-efficient NATT Keepalive. If NATT keepalive is requested but cannot
|
*
|
||||||
* be activated, then the transform will fail to activate and throw an IOException.
|
* <p>This will set power-efficient keepalive packets to be sent by the system. If NAT-T
|
||||||
|
* keepalive is requested but cannot be activated, then creation of an {@link
|
||||||
|
* IpSecTransform} will fail when calling the build method.
|
||||||
|
*
|
||||||
|
* @param intervalSeconds the maximum number of seconds between keepalive packets. Must be
|
||||||
|
* between 20s and 3600s.
|
||||||
*
|
*
|
||||||
* @param intervalSeconds the maximum number of seconds between keepalive packets, no less
|
|
||||||
* than 20s and no more than 3600s.
|
|
||||||
* @hide
|
* @hide
|
||||||
*/
|
*/
|
||||||
@SystemApi
|
@SystemApi
|
||||||
@@ -408,36 +412,29 @@ public final class IpSecTransform implements AutoCloseable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Build and return an active {@link IpSecTransform} object as a Transport Mode Transform.
|
* Build a transport mode {@link IpSecTransform}.
|
||||||
* Some parameters have interdependencies that are checked at build time. If a well-formed
|
|
||||||
* transform cannot be created from the supplied parameters, this method will throw an
|
|
||||||
* Exception.
|
|
||||||
*
|
*
|
||||||
* <p>Upon a successful return from this call, the provided IpSecTransform will be active
|
* <p>This builds and activates a transport mode transform. Note that an active transform
|
||||||
* and may be applied to sockets. If too many IpSecTransform objects are active for a given
|
* will not affect any network traffic until it has been applied to one or more sockets.
|
||||||
* user this operation will fail and throw ResourceUnavailableException. To avoid these
|
|
||||||
* exceptions, unused Transform objects must be cleaned up by calling {@link
|
|
||||||
* IpSecTransform#close()} when they are no longer needed.
|
|
||||||
*
|
*
|
||||||
* @param remoteAddress the {@link InetAddress} that, when matched on traffic to/from this
|
* @see IpSecManager#applyTransportModeTransform
|
||||||
* socket will cause the transform to be applied.
|
*
|
||||||
* <p>Note that an active transform will not impact any network traffic until it has
|
* @param remoteAddress the remote {@code InetAddress} of traffic on sockets that will use
|
||||||
* been applied to one or more Sockets. Calling this method is a necessary precondition
|
* this transform
|
||||||
* for applying it to a socket, but is not sufficient to actually apply IPsec.
|
|
||||||
* @throws IllegalArgumentException indicating that a particular combination of transform
|
* @throws IllegalArgumentException indicating that a particular combination of transform
|
||||||
* properties is invalid.
|
* properties is invalid
|
||||||
* @throws IpSecManager.ResourceUnavailableException in the event that no more Transforms
|
* @throws IpSecManager.ResourceUnavailableException indicating that too many transforms are
|
||||||
* may be allocated
|
* active
|
||||||
* @throws SpiUnavailableException if the SPI collides with an existing transform
|
* @throws IpSecManager.SpiUnavailableException indicating the rare case where an SPI
|
||||||
* (unlikely).
|
* collides with an existing transform
|
||||||
* @throws ResourceUnavailableException if the current user currently has exceeded the
|
* @throws IOException indicating other errors
|
||||||
* number of allowed active transforms.
|
|
||||||
*/
|
*/
|
||||||
public IpSecTransform buildTransportModeTransform(InetAddress remoteAddress)
|
public IpSecTransform buildTransportModeTransform(InetAddress remoteAddress)
|
||||||
throws IpSecManager.ResourceUnavailableException,
|
throws IpSecManager.ResourceUnavailableException,
|
||||||
IpSecManager.SpiUnavailableException, IOException {
|
IpSecManager.SpiUnavailableException, IOException {
|
||||||
mConfig.setMode(MODE_TRANSPORT);
|
mConfig.setMode(MODE_TRANSPORT);
|
||||||
mConfig.setRemoteAddress(remoteAddress.getHostAddress());
|
mConfig.setRemoteAddress(remoteAddress.getHostAddress());
|
||||||
|
// FIXME: modifying a builder after calling build can change the built transform.
|
||||||
return new IpSecTransform(mContext, mConfig).activate();
|
return new IpSecTransform(mContext, mConfig).activate();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -465,9 +462,9 @@ public final class IpSecTransform implements AutoCloseable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a new IpSecTransform.Builder to construct an IpSecTransform
|
* Create a new IpSecTransform.Builder.
|
||||||
*
|
*
|
||||||
* @param context current Context
|
* @param context current context
|
||||||
*/
|
*/
|
||||||
public Builder(@NonNull Context context) {
|
public Builder(@NonNull Context context) {
|
||||||
Preconditions.checkNotNull(context);
|
Preconditions.checkNotNull(context);
|
||||||
|
|||||||
Reference in New Issue
Block a user