Merge "Javadoc cleanup of IpSecManager API."

am: d09d106ec0

Change-Id: Iaf206b0980d3bed14fe6b8318d2073577212b460
This commit is contained in:
Jonathan Basseri
2017-11-22 01:51:46 +00:00
committed by android-build-merger
4 changed files with 299 additions and 222 deletions

View File

@@ -15,6 +15,7 @@
*/
package android.net;
import android.annotation.NonNull;
import android.annotation.StringDef;
import android.os.Build;
import android.os.Parcel;
@@ -27,8 +28,10 @@ import java.lang.annotation.RetentionPolicy;
import java.util.Arrays;
/**
* IpSecAlgorithm specifies a single algorithm that can be applied to an IpSec Transform. Refer to
* RFC 4301.
* 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 {
/**
@@ -39,16 +42,16 @@ public final class IpSecAlgorithm implements Parcelable {
public static final String CRYPT_AES_CBC = "cbc(aes)";
/**
* MD5 HMAC Authentication/Integrity Algorithm. This algorithm is not recommended for use in new
* applications and is provided for legacy compatibility with 3gpp infrastructure.
* 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>Valid truncation lengths are multiples of 8 bits from 96 to (default) 128.
*/
public static final String AUTH_HMAC_MD5 = "hmac(md5)";
/**
* SHA1 HMAC Authentication/Integrity Algorithm. This algorithm is not recommended for use in
* new applications and is provided for legacy compatibility with 3gpp infrastructure.
* 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>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)";
/**
* SHA512 HMAC Authentication/Integrity Algorithm
* SHA512 HMAC Authentication/Integrity Algorithm.
*
* <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>As per RFC4106 (Section 8.1), 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>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}.
*/
@@ -105,48 +108,47 @@ public final class IpSecAlgorithm implements Parcelable {
private final int mTruncLenBits;
/**
* Specify a IpSecAlgorithm of one of the supported types including the truncation length of the
* algorithm
* Creates an IpSecAlgorithm of one of the supported types. Supported algorithm names are
* defined as constants in this class.
*
* @param algorithm type for IpSec.
* @param key non-null Key padded to a multiple of 8 bits.
* @param algorithm name of the algorithm.
* @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);
}
/**
* Specify a IpSecAlgorithm of one of the supported types including the truncation length of the
* algorithm
* Creates an IpSecAlgorithm of one of the supported types. Supported algorithm names are
* defined as constants in this class.
*
* @param algoName precise name of the algorithm to be used.
* @param key non-null Key padded to a multiple of 8 bits.
* @param truncLenBits the number of bits of output hash to use; only meaningful for
* Authentication or Authenticated Encryption (equivalent to ICV length).
* <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.
*/
public IpSecAlgorithm(@AlgorithmName String algoName, byte[] key, int truncLenBits) {
if (!isTruncationLengthValid(algoName, truncLenBits)) {
public IpSecAlgorithm(@AlgorithmName String algorithm, @NonNull byte[] key, int truncLenBits) {
if (!isTruncationLengthValid(algorithm, truncLenBits)) {
throw new IllegalArgumentException("Unknown algorithm or invalid length");
}
mName = algoName;
mName = algorithm;
mKey = key.clone();
mTruncLenBits = Math.min(truncLenBits, key.length * 8);
}
/** Retrieve the algorithm name */
/** Get the algorithm name */
public String getName() {
return mName;
}
/** Retrieve the key for this algorithm */
/** Get the key for this algorithm */
public byte[] getKey() {
return mKey.clone();
}
/**
* Retrieve the truncation length, in bits, for the key in this algo. By default this will be
* the length in bits of the key.
*/
/** Get the truncation length of this algorithm, in bits */
public int getTruncationLengthBits() {
return mTruncLenBits;
}

View File

@@ -20,7 +20,12 @@ import android.os.Parcelable;
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 {
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.
private Network mNetwork;
/**
* This class captures the parameters that specifically apply to inbound or outbound traffic.
*/
public static class Flow {
// Minimum requirements for identifying a transform
// SPI identifying the IPsec flow in packet processing

View File

@@ -19,6 +19,7 @@ import static com.android.internal.util.Preconditions.checkNotNull;
import android.annotation.NonNull;
import android.annotation.SystemService;
import android.annotation.TestApi;
import android.content.Context;
import android.os.Binder;
import android.os.ParcelFileDescriptor;
@@ -37,22 +38,28 @@ import java.net.InetAddress;
import java.net.Socket;
/**
* This class contains methods for managing IPsec sessions, which will perform kernel-space
* encryption and decryption of socket or Network traffic.
* This class contains methods for managing IPsec sessions. Once configured, the kernel will apply
* confidentiality (encryption) and integrity (authentication) to IP traffic.
*
* <p>An IpSecManager may be obtained by calling {@link
* android.content.Context#getSystemService(String) Context#getSystemService(String)} with {@link
* android.content.Context#IPSEC_SERVICE Context#IPSEC_SERVICE}
* <p>Note that not all aspects of IPsec are permitted by this API. Applications may create
* transport mode security associations and apply them to individual sockets. Applications looking
* 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)
public final class 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.
*
* @hide
*/
@TestApi
public static final int INVALID_SECURITY_PARAMETER_INDEX = 0;
/** @hide */
@@ -66,10 +73,12 @@ public final class IpSecManager {
public static final int INVALID_RESOURCE_ID = 0;
/**
* Indicates that the combination of remote InetAddress and SPI was non-unique for a given
* 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
* or reserved using reserveSecurityParameterIndex.
* Thrown to indicate that a requested SPI is in use.
*
* <p>The combination of remote {@code InetAddress} and SPI must be unique across all apps on
* 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 {
private final int mSpi;
@@ -78,7 +87,7 @@ public final class IpSecManager {
* Construct an exception indicating that a transform with the given SPI is already in use
* 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
*/
SpiUnavailableException(String msg, int spi) {
@@ -86,16 +95,18 @@ public final class IpSecManager {
mSpi = spi;
}
/** Retrieve the SPI that caused a collision */
/** Get the SPI that caused a collision. */
public int getSpi() {
return mSpi;
}
}
/**
* Indicates that the requested system resource for IPsec, such as a socket or other system
* resource is unavailable. If this exception is thrown, try releasing allocated objects of the
* type requested.
* Thrown to indicate that an IPsec resource is unavailable.
*
* <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 {
@@ -106,6 +117,13 @@ public final class IpSecManager {
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 {
private final IIpSecService mService;
private final InetAddress mRemoteAddress;
@@ -113,7 +131,7 @@ public final class IpSecManager {
private int mSpi = INVALID_SECURITY_PARAMETER_INDEX;
private int mResourceId;
/** Return the underlying SPI held by this object */
/** Get the underlying SPI held by this object. */
public int getSpi() {
return mSpi;
}
@@ -135,6 +153,7 @@ public final class IpSecManager {
mCloseGuard.close();
}
/** Check that the SPI was closed properly. */
@Override
protected void finalize() throws Throwable {
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
* SecurityParameterIndex#close()}.
*
* @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
* @throws ResourceUnavailableException indicating that too many SPIs are currently allocated
* 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
* SecurityParameterIndex#close()}.
*
* @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 requestedSpi the requested SPI, or '0' to allocate a random SPI.
* @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
* @return the reserved SecurityParameterIndex
* @throws ResourceUnavailableException indicating that too many SPIs are currently allocated
* for this user
* @throws SpiUnavailableException indicating that the requested SPI could not be reserved
*/
public SecurityParameterIndex reserveSecurityParameterIndex(
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
* 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
* address associated with that transform will throw an IOException. In addition, if the
* IpSecTransform is later deactivated, the socket will throw an IOException on any calls to
* send() or receive() until the transform is removed from the socket by calling {@link
* #removeTransportModeTransform(Socket, IpSecTransform)};
* Apply an IPsec transform to a stream socket.
*
* <p>This applies transport mode encapsulation to the given socket. Once applied, I/O on the
* socket will be encapsulated according to the parameters of the {@code IpSecTransform}. When
* the transform is removed from the socket by calling {@link #removeTransportModeTransform},
* unprotected traffic can resume on that socket.
*
* <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 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
*/
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
* 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
* address associated with that transform will throw an IOException. In addition, if the
* IpSecTransform is later deactivated, the socket will throw an IOException on any calls to
* send() or receive() until the transform is removed from the socket by calling {@link
* #removeTransportModeTransform(DatagramSocket, IpSecTransform)};
* Apply an IPsec transform to a datagram socket.
*
* <p>This applies transport mode encapsulation to the given socket. Once applied, I/O on the
* socket will be encapsulated according to the parameters of the {@code IpSecTransform}. When
* the transform is removed from the socket by calling {@link #removeTransportModeTransform},
* unprotected traffic can resume on that socket.
*
* <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 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
*/
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
* 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
* address associated with that transform will throw an IOException. In addition, if the
* IpSecTransform is later deactivated, the socket will throw an IOException on any calls to
* send() or receive() until the transform is removed from the socket by calling {@link
* #removeTransportModeTransform(FileDescriptor, IpSecTransform)};
* Apply an IPsec transform to a socket.
*
* <p>This applies transport mode encapsulation to the given socket. Once applied, I/O on the
* socket will be encapsulated according to the parameters of the {@code IpSecTransform}. When
* the transform is removed from the socket by calling {@link #removeTransportModeTransform},
* unprotected traffic can resume on that socket.
*
* <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 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)
throws IOException {
@@ -323,6 +379,7 @@ public final class IpSecManager {
* Applications should probably not use this API directly. Instead, they should use {@link
* 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 transform an {@link IpSecTransform}, which must be an active Tunnel Mode transform.
* @hide
@@ -330,14 +387,19 @@ public final class IpSecManager {
public void applyTunnelModeTransform(Network net, IpSecTransform transform) {}
/**
* Remove a transform from a given stream socket. Once removed, traffic on the socket will not
* 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.
* Remove an IPsec transform from a stream socket.
*
* @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
* @throws IOException indicating that the transform could not be removed from the socket
* @hide
*/
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
* 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.
* Remove an IPsec transform from a datagram socket.
*
* @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
* @throws IOException indicating that the transform could not be removed from the socket
* @hide
*/
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
* 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.
* Remove an IPsec transform from a socket.
*
* @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
* @throws IOException indicating that the transform could not be removed from the socket
*/
public void removeTransportModeTransform(FileDescriptor socket, IpSecTransform transform)
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) {
try {
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
* 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 transform a Tunnel Mode IPsec Transform that has been previously applied to the given
* network
@@ -405,11 +478,18 @@ public final class IpSecManager {
public void removeTunnelModeTransform(Network net, IpSecTransform transform) {}
/**
* Class providing access to a system-provided UDP Encapsulation Socket, which may be used for
* IKE signalling as well as for inbound and outbound UDP encapsulated IPsec traffic.
* This class provides access to a UDP encapsulation Socket.
*
* <p>The socket provided by this class cannot be re-bound or closed via the inner
* FileDescriptor. Instead, disposing of this socket requires a call to close().
* <p>{@code UdpEncapsulationSocket} wraps a system-provided datagram socket intended for IKEv2
* 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 {
private final ParcelFileDescriptor mPfd;
@@ -443,7 +523,7 @@ public final class IpSecManager {
mCloseGuard.open("constructor");
}
/** Access the inner UDP Encapsulation Socket */
/** Get the wrapped socket. */
public FileDescriptor getSocket() {
if (mPfd == null) {
return null;
@@ -451,22 +531,19 @@ public final class IpSecManager {
return mPfd.getFileDescriptor();
}
/** Retrieve the port number of the inner encapsulation socket */
/** Get the bound port of the wrapped socket. */
public int getPort() {
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
* system. This must be done as part of cleanup following use of a socket. Failure to do so
* will cause the socket to count against a total allocation limit for IpSec and eventually
* fail due to resource limits.
*
* @param fd a file descriptor previously returned as a UDP Encapsulation socket.
* <p>This closes the wrapped socket. Open encapsulation sockets count against a user's
* resource limits, and forgetting to close them eventually will result in {@link
* ResourceUnavailableException} being thrown.
*/
@Override
public void close() throws IOException {
try {
mService.closeUdpEncapsulationSocket(mResourceId);
@@ -483,6 +560,7 @@ public final class IpSecManager {
mCloseGuard.close();
}
/** Check that the socket was closed properly. */
@Override
protected void finalize() throws Throwable {
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
* the caller. This provides safe access to a socket on a port that can later be used as a UDP
* Encapsulation port.
* <p>See {@link UdpEncapsulationSocket} for the proper way to close the returned socket.
*
* <p>This socket reservation works in conjunction with IpSecTransforms, which may re-use the
* socket port. Explicitly opening this port is only necessary if communication is desired on
* that port.
*
* @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.
* @param port a local UDP port
* @return a socket that is bound to the given 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
// 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
* the caller. This provides safe access to a socket on a port that can later be used as a UDP
* Encapsulation port.
* <p>See {@link UdpEncapsulationSocket} for the proper way to close the returned socket.
*
* <p>This socket reservation works in conjunction with IpSecTransforms, which may re-use the
* socket port. Explicitly opening this port is only necessary if communication is desired on
* that port.
* <p>The local port of the returned socket can be obtained by calling {@link
* UdpEncapsulationSocket#getPort()}.
*
* @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
// 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
* @hide

View File

@@ -38,27 +38,29 @@ import java.lang.annotation.RetentionPolicy;
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
* the lifetime of the underlying transform. If a transform object leaves scope, the underlying
* transform may be disabled automatically, with likely undesirable results.
* <p>Transforms are created using {@link IpSecTransform.Builder}. Each {@code IpSecTransform}
* object encapsulates the properties and state of an inbound and outbound IPsec security
* 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
* of traffic or may represent a transport mode transform operating on a Socket or Sockets.
* @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";
/**
* For direction-specific attributes of an IpSecTransform, indicates that an attribute applies
* to traffic towards the host.
* For direction-specific attributes of an {@link IpSecTransform}, indicates that an attribute
* applies to traffic towards the host.
*/
public static final int DIRECTION_IN = 0;
/**
* For direction-specific attributes of an IpSecTransform, indicates that an attribute applies
* to traffic from the host.
* For direction-specific attributes of an {@link IpSecTransform}, indicates that an attribute
* applies to traffic from the host.
*/
public static final int DIRECTION_OUT = 1;
@@ -77,16 +79,16 @@ public final class IpSecTransform implements AutoCloseable {
public static final int ENCAP_NONE = 0;
/**
* IpSec traffic will be encapsulated within a UDP header with an additional 8-byte header pad
* (of '0'-value bytes) that prevents traffic from being interpreted as IKE or as ESP over UDP.
* 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">RFC3498</a>.
* IPsec traffic will be encapsulated within UDP as per
* <a href="https://tools.ietf.org/html/rfc3948">RFC 3498</a>.
*
* @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
* the system for this Transform.
* Deactivate this {@code IpSecTransform} and free allocated resources.
*
* <p>Deactivating a transform while it is still applied to any Socket will result in sockets
* refusing to send or receive data. This method will silently succeed if the specified
* transform has already been removed; thus, it is always safe to attempt cleanup when a
* transform is no longer needed.
* <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#removeTransportModeTransform}. 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);
@@ -197,6 +200,7 @@ public final class IpSecTransform implements AutoCloseable {
}
}
/** Check that the transform was closed properly. */
@Override
protected void finalize() throws Throwable {
if (mCloseGuard != null) {
@@ -264,65 +268,63 @@ public final class IpSecTransform implements AutoCloseable {
}
/**
* Builder object to facilitate the creation of IpSecTransform objects.
*
* <p>Apply additional properties to the transform and then call a build() method to return an
* IpSecTransform object.
*
* @see Builder#buildTransportModeTransform(InetAddress)
* This class is used to build {@link IpSecTransform} objects.
*/
public static class Builder {
private Context mContext;
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
* direction, creation of an IpSecTransform will fail upon calling a build() method.
* <p>If encryption is set for a direction without also providing an SPI for that 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>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.
*/
public IpSecTransform.Builder setEncryption(
@TransformDirection int direction, IpSecAlgorithm algo) {
// TODO: throw IllegalArgumentException if algo is not an encryption algorithm.
mConfig.setEncryption(direction, algo);
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
* direction, creation of an IpSecTransform will fail upon calling a build() method.
* <p>If authentication is set for a direction without also providing an SPI for that
* 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.
*/
public IpSecTransform.Builder setAuthentication(
@TransformDirection int direction, IpSecAlgorithm algo) {
// TODO: throw IllegalArgumentException if algo is not an authentication algorithm.
mConfig.setAuthentication(direction, algo);
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
* providing an SPI for that direction, creation of an IpSecTransform will fail upon calling
* a build() method.
* providing an SPI for that direction, creation of an {@code IpSecTransform} will fail when
* attempting to build the transform.
*
* <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 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.
*
* @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
* 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
* IPsec operates at the IP layer, this 32-bit identifier uniquely identifies packets to a
* given destination address.
* Set the SPI for the given direction.
*
* <p>Care should be chosen when selecting an SPI to ensure that is is as unique as
* possible. To reserve a value call {@link IpSecManager#reserveSecurityParameterIndex(int,
* InetAddress, int)}. Otherwise, SPI collisions would prevent a transform from being
* activated. IpSecManager#reserveSecurityParameterIndex(int, InetAddres$s, int)}.
* <p>Because IPsec operates at the IP layer, this 32-bit identifier uniquely identifies
* packets to a given destination address. To prevent SPI collisions, values should be
* reserved by calling {@link IpSecManager#reserveSecurityParameterIndex}.
*
* <p>Unless an SPI is set for a given direction, traffic in that direction will be
* sent/received without any IPsec applied.
* <p>If the SPI and algorithms are omitted for one direction, traffic in that direction
* 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
* 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
* emit on the default network).
* Set the {@link Network} which will carry tunneled traffic.
*
* <p>Restricts the transformed traffic to a particular {@link Network}. This is required in
* tunnel mode.
* <p>Restricts the transformed traffic to a particular {@link Network}. This is required
* for tunnel mode, otherwise tunneled traffic would be sent on the default network.
*
* @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
* details on how UDP should be applied to IPsec.
* <p>This allows IPsec traffic to pass through a NAT.
*
* @param localSocket a {@link IpSecManager.UdpEncapsulationSocket} for sending and
* receiving encapsulating traffic.
* @param remotePort the UDP port number of the remote that will send and receive
* encapsulated traffic. In the case of IKE, this is likely port 4500.
* @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.
*/
public IpSecTransform.Builder setIpv4Encapsulation(
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: Specify the needed NATT keepalive permission.
/**
* Send a NATT Keepalive packet with a given maximum interval. This will create an offloaded
* 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.
* Set NAT-T keepalives to be sent with a given interval.
*
* <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
*/
@SystemApi
@@ -408,36 +412,29 @@ public final class IpSecTransform implements AutoCloseable {
}
/**
* Build and return an active {@link IpSecTransform} object as a Transport Mode Transform.
* 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.
* Build a transport mode {@link IpSecTransform}.
*
* <p>Upon a successful return from this call, the provided IpSecTransform will be active
* and may be applied to sockets. If too many IpSecTransform objects are active for a given
* 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.
* <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.
*
* @param remoteAddress the {@link InetAddress} that, when matched on traffic to/from this
* socket will cause the transform to be applied.
* <p>Note that an active transform will not impact any network traffic until it has
* been applied to one or more Sockets. Calling this method is a necessary precondition
* for applying it to a socket, but is not sufficient to actually apply IPsec.
* @see IpSecManager#applyTransportModeTransform
*
* @param remoteAddress the remote {@code InetAddress} of traffic on sockets that will use
* this transform
* @throws IllegalArgumentException indicating that a particular combination of transform
* properties is invalid.
* @throws IpSecManager.ResourceUnavailableException in the event that no more Transforms
* may be allocated
* @throws SpiUnavailableException if the SPI collides with an existing transform
* (unlikely).
* @throws ResourceUnavailableException if the current user currently has exceeded the
* number of allowed active transforms.
* 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
*/
public IpSecTransform buildTransportModeTransform(InetAddress remoteAddress)
throws IpSecManager.ResourceUnavailableException,
IpSecManager.SpiUnavailableException, IOException {
mConfig.setMode(MODE_TRANSPORT);
mConfig.setRemoteAddress(remoteAddress.getHostAddress());
// FIXME: modifying a builder after calling build can change the built transform.
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) {
Preconditions.checkNotNull(context);