summaryrefslogtreecommitdiff
path: root/core/java/android
diff options
context:
space:
mode:
authorNathan Harold <nharold@google.com>2018-01-05 19:25:13 -0800
committerNathan Harold <nharold@google.com>2018-01-16 11:08:31 -0800
commita25233123b2d29fde83dd686f6313f0a232c5b2a (patch)
tree71eeaa238dffb8f13772ee22e6da239ac997aa5a /core/java/android
parente1bdd513d0014ae969188c20a8fd1c2e3acb74a7 (diff)
Make Transforms Unidirectional
Convert the IpSecTransform from being a bi-directional pair of SAs to a unidirectional single SA. This CL also removes the concept of "direction from SAs meaning that a IpSecTransform may now be applied to a socket in either direction. -Make transforms unidirectional -Add Convert allocateSpi() to use destination rather than direction and remote address -Remove directionality from builders for IpSecTransform -Change applyTransportModeTransform() to take a direction in which to apply the transform object. -Additional minor naming updates -Restrict IpSecConfig to only print keys on eng builds -Move DIRECTION constants to IpSecManager -Add sourceAddress parameter to IpSecTransform to provide additional guarantees about the source address of data; (explicit failure rather than implicit failure). -Move SPI to the build() method of IpSecTransform Bug: 71717213 Test: runtest frameworks-net, CTS - IpSecManagerTest Change-Id: I0824b37f443f4b8c62536d9801238c63ed8f2a1c
Diffstat (limited to 'core/java/android')
-rw-r--r--core/java/android/net/IIpSecService.aidl6
-rw-r--r--core/java/android/net/IpSecAlgorithm.java8
-rw-r--r--core/java/android/net/IpSecConfig.java187
-rw-r--r--core/java/android/net/IpSecManager.java119
-rw-r--r--core/java/android/net/IpSecTransform.java155
5 files changed, 215 insertions, 260 deletions
diff --git a/core/java/android/net/IIpSecService.aidl b/core/java/android/net/IIpSecService.aidl
index d9b57db18071..3fe531fd7960 100644
--- a/core/java/android/net/IIpSecService.aidl
+++ b/core/java/android/net/IIpSecService.aidl
@@ -31,7 +31,7 @@ import android.os.ParcelFileDescriptor;
interface IIpSecService
{
IpSecSpiResponse allocateSecurityParameterIndex(
- int direction, in String remoteAddress, int requestedSpi, in IBinder binder);
+ in String destinationAddress, int requestedSpi, in IBinder binder);
void releaseSecurityParameterIndex(int resourceId);
@@ -43,7 +43,7 @@ interface IIpSecService
void deleteTransportModeTransform(int transformId);
- void applyTransportModeTransform(in ParcelFileDescriptor socket, int transformId);
+ void applyTransportModeTransform(in ParcelFileDescriptor socket, int direction, int transformId);
- void removeTransportModeTransform(in ParcelFileDescriptor socket, int transformId);
+ void removeTransportModeTransforms(in ParcelFileDescriptor socket, int transformId);
}
diff --git a/core/java/android/net/IpSecAlgorithm.java b/core/java/android/net/IpSecAlgorithm.java
index 7d752e89e6f6..c69a4d4c0bee 100644
--- a/core/java/android/net/IpSecAlgorithm.java
+++ b/core/java/android/net/IpSecAlgorithm.java
@@ -256,13 +256,19 @@ public final class IpSecAlgorithm implements Parcelable {
return getName().equals(AUTH_CRYPT_AES_GCM);
}
+ // Because encryption keys are sensitive and userdebug builds are used by large user pools
+ // such as beta testers, we only allow sensitive info such as keys on eng builds.
+ private static boolean isUnsafeBuild() {
+ return Build.IS_DEBUGGABLE && Build.IS_ENG;
+ }
+
@Override
public String toString() {
return new StringBuilder()
.append("{mName=")
.append(mName)
.append(", mKey=")
- .append(Build.IS_DEBUGGABLE ? HexDump.toHexString(mKey) : "<hidden>")
+ .append(isUnsafeBuild() ? HexDump.toHexString(mKey) : "<hidden>")
.append(", mTruncLenBits=")
.append(mTruncLenBits)
.append("}")
diff --git a/core/java/android/net/IpSecConfig.java b/core/java/android/net/IpSecConfig.java
index f54ceb5c142a..80b0af33735b 100644
--- a/core/java/android/net/IpSecConfig.java
+++ b/core/java/android/net/IpSecConfig.java
@@ -32,59 +32,29 @@ public final class IpSecConfig implements Parcelable {
// MODE_TRANSPORT or MODE_TUNNEL
private int mMode = IpSecTransform.MODE_TRANSPORT;
- // Needs to be valid only for tunnel mode
// Preventing this from being null simplifies Java->Native binder
- private String mLocalAddress = "";
+ private String mSourceAddress = "";
// Preventing this from being null simplifies Java->Native binder
- private String mRemoteAddress = "";
+ private String mDestinationAddress = "";
// The underlying Network that represents the "gateway" Network
// for outbound packets. It may also be used to select packets.
private Network mNetwork;
- /**
- * 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
- // and a remote IP address
- private int mSpiResourceId = IpSecManager.INVALID_RESOURCE_ID;
-
- // Encryption Algorithm
- private IpSecAlgorithm mEncryption;
-
- // Authentication Algorithm
- private IpSecAlgorithm mAuthentication;
-
- // Authenticated Encryption Algorithm
- private IpSecAlgorithm mAuthenticatedEncryption;
-
- @Override
- public String toString() {
- return new StringBuilder()
- .append("{mSpiResourceId=")
- .append(mSpiResourceId)
- .append(", mEncryption=")
- .append(mEncryption)
- .append(", mAuthentication=")
- .append(mAuthentication)
- .append(", mAuthenticatedEncryption=")
- .append(mAuthenticatedEncryption)
- .append("}")
- .toString();
- }
-
- static boolean equals(IpSecConfig.Flow lhs, IpSecConfig.Flow rhs) {
- if (lhs == null || rhs == null) return (lhs == rhs);
- return (lhs.mSpiResourceId == rhs.mSpiResourceId
- && IpSecAlgorithm.equals(lhs.mEncryption, rhs.mEncryption)
- && IpSecAlgorithm.equals(lhs.mAuthentication, rhs.mAuthentication));
- }
- }
+ // Minimum requirements for identifying a transform
+ // SPI identifying the IPsec SA in packet processing
+ // and a destination IP address
+ private int mSpiResourceId = IpSecManager.INVALID_RESOURCE_ID;
+
+ // Encryption Algorithm
+ private IpSecAlgorithm mEncryption;
+
+ // Authentication Algorithm
+ private IpSecAlgorithm mAuthentication;
- private final Flow[] mFlow = new Flow[] {new Flow(), new Flow()};
+ // Authenticated Encryption Algorithm
+ private IpSecAlgorithm mAuthenticatedEncryption;
// For tunnel mode IPv4 UDP Encapsulation
// IpSecTransform#ENCAP_ESP_*, such as ENCAP_ESP_OVER_UDP_IKE
@@ -100,36 +70,37 @@ public final class IpSecConfig implements Parcelable {
mMode = mode;
}
- /** Set the local IP address for Tunnel mode */
- public void setLocalAddress(String localAddress) {
- mLocalAddress = localAddress;
+ /** Set the source IP addres for this IPsec transform */
+ public void setSourceAddress(String sourceAddress) {
+ mSourceAddress = sourceAddress;
}
- /** Set the remote IP address for this IPsec transform */
- public void setRemoteAddress(String remoteAddress) {
- mRemoteAddress = remoteAddress;
+ /** Set the destination IP address for this IPsec transform */
+ public void setDestinationAddress(String destinationAddress) {
+ mDestinationAddress = destinationAddress;
}
- /** Set the SPI for a given direction by resource ID */
- public void setSpiResourceId(int direction, int resourceId) {
- mFlow[direction].mSpiResourceId = resourceId;
+ /** Set the SPI by resource ID */
+ public void setSpiResourceId(int resourceId) {
+ mSpiResourceId = resourceId;
}
- /** Set the encryption algorithm for a given direction */
- public void setEncryption(int direction, IpSecAlgorithm encryption) {
- mFlow[direction].mEncryption = encryption;
+ /** Set the encryption algorithm */
+ public void setEncryption(IpSecAlgorithm encryption) {
+ mEncryption = encryption;
}
- /** Set the authentication algorithm for a given direction */
- public void setAuthentication(int direction, IpSecAlgorithm authentication) {
- mFlow[direction].mAuthentication = authentication;
+ /** Set the authentication algorithm */
+ public void setAuthentication(IpSecAlgorithm authentication) {
+ mAuthentication = authentication;
}
- /** Set the authenticated encryption algorithm for a given direction */
- public void setAuthenticatedEncryption(int direction, IpSecAlgorithm authenticatedEncryption) {
- mFlow[direction].mAuthenticatedEncryption = authenticatedEncryption;
+ /** Set the authenticated encryption algorithm */
+ public void setAuthenticatedEncryption(IpSecAlgorithm authenticatedEncryption) {
+ mAuthenticatedEncryption = authenticatedEncryption;
}
+ /** Set the underlying network that will carry traffic for this transform */
public void setNetwork(Network network) {
mNetwork = network;
}
@@ -155,28 +126,28 @@ public final class IpSecConfig implements Parcelable {
return mMode;
}
- public String getLocalAddress() {
- return mLocalAddress;
+ public String getSourceAddress() {
+ return mSourceAddress;
}
- public int getSpiResourceId(int direction) {
- return mFlow[direction].mSpiResourceId;
+ public int getSpiResourceId() {
+ return mSpiResourceId;
}
- public String getRemoteAddress() {
- return mRemoteAddress;
+ public String getDestinationAddress() {
+ return mDestinationAddress;
}
- public IpSecAlgorithm getEncryption(int direction) {
- return mFlow[direction].mEncryption;
+ public IpSecAlgorithm getEncryption() {
+ return mEncryption;
}
- public IpSecAlgorithm getAuthentication(int direction) {
- return mFlow[direction].mAuthentication;
+ public IpSecAlgorithm getAuthentication() {
+ return mAuthentication;
}
- public IpSecAlgorithm getAuthenticatedEncryption(int direction) {
- return mFlow[direction].mAuthenticatedEncryption;
+ public IpSecAlgorithm getAuthenticatedEncryption() {
+ return mAuthenticatedEncryption;
}
public Network getNetwork() {
@@ -209,17 +180,13 @@ public final class IpSecConfig implements Parcelable {
@Override
public void writeToParcel(Parcel out, int flags) {
out.writeInt(mMode);
- out.writeString(mLocalAddress);
- out.writeString(mRemoteAddress);
+ out.writeString(mSourceAddress);
+ out.writeString(mDestinationAddress);
out.writeParcelable(mNetwork, flags);
- out.writeInt(mFlow[IpSecTransform.DIRECTION_IN].mSpiResourceId);
- out.writeParcelable(mFlow[IpSecTransform.DIRECTION_IN].mEncryption, flags);
- out.writeParcelable(mFlow[IpSecTransform.DIRECTION_IN].mAuthentication, flags);
- out.writeParcelable(mFlow[IpSecTransform.DIRECTION_IN].mAuthenticatedEncryption, flags);
- out.writeInt(mFlow[IpSecTransform.DIRECTION_OUT].mSpiResourceId);
- out.writeParcelable(mFlow[IpSecTransform.DIRECTION_OUT].mEncryption, flags);
- out.writeParcelable(mFlow[IpSecTransform.DIRECTION_OUT].mAuthentication, flags);
- out.writeParcelable(mFlow[IpSecTransform.DIRECTION_OUT].mAuthenticatedEncryption, flags);
+ out.writeInt(mSpiResourceId);
+ out.writeParcelable(mEncryption, flags);
+ out.writeParcelable(mAuthentication, flags);
+ out.writeParcelable(mAuthenticatedEncryption, flags);
out.writeInt(mEncapType);
out.writeInt(mEncapSocketResourceId);
out.writeInt(mEncapRemotePort);
@@ -231,22 +198,15 @@ public final class IpSecConfig implements Parcelable {
private IpSecConfig(Parcel in) {
mMode = in.readInt();
- mLocalAddress = in.readString();
- mRemoteAddress = in.readString();
+ mSourceAddress = in.readString();
+ mDestinationAddress = in.readString();
mNetwork = (Network) in.readParcelable(Network.class.getClassLoader());
- mFlow[IpSecTransform.DIRECTION_IN].mSpiResourceId = in.readInt();
- mFlow[IpSecTransform.DIRECTION_IN].mEncryption =
- (IpSecAlgorithm) in.readParcelable(IpSecAlgorithm.class.getClassLoader());
- mFlow[IpSecTransform.DIRECTION_IN].mAuthentication =
- (IpSecAlgorithm) in.readParcelable(IpSecAlgorithm.class.getClassLoader());
- mFlow[IpSecTransform.DIRECTION_IN].mAuthenticatedEncryption =
- (IpSecAlgorithm) in.readParcelable(IpSecAlgorithm.class.getClassLoader());
- mFlow[IpSecTransform.DIRECTION_OUT].mSpiResourceId = in.readInt();
- mFlow[IpSecTransform.DIRECTION_OUT].mEncryption =
+ mSpiResourceId = in.readInt();
+ mEncryption =
(IpSecAlgorithm) in.readParcelable(IpSecAlgorithm.class.getClassLoader());
- mFlow[IpSecTransform.DIRECTION_OUT].mAuthentication =
+ mAuthentication =
(IpSecAlgorithm) in.readParcelable(IpSecAlgorithm.class.getClassLoader());
- mFlow[IpSecTransform.DIRECTION_OUT].mAuthenticatedEncryption =
+ mAuthenticatedEncryption =
(IpSecAlgorithm) in.readParcelable(IpSecAlgorithm.class.getClassLoader());
mEncapType = in.readInt();
mEncapSocketResourceId = in.readInt();
@@ -260,10 +220,10 @@ public final class IpSecConfig implements Parcelable {
strBuilder
.append("{mMode=")
.append(mMode == IpSecTransform.MODE_TUNNEL ? "TUNNEL" : "TRANSPORT")
- .append(", mLocalAddress=")
- .append(mLocalAddress)
- .append(", mRemoteAddress=")
- .append(mRemoteAddress)
+ .append(", mSourceAddress=")
+ .append(mSourceAddress)
+ .append(", mDestinationAddress=")
+ .append(mDestinationAddress)
.append(", mNetwork=")
.append(mNetwork)
.append(", mEncapType=")
@@ -274,10 +234,14 @@ public final class IpSecConfig implements Parcelable {
.append(mEncapRemotePort)
.append(", mNattKeepaliveInterval=")
.append(mNattKeepaliveInterval)
- .append(", mFlow[OUT]=")
- .append(mFlow[IpSecTransform.DIRECTION_OUT])
- .append(", mFlow[IN]=")
- .append(mFlow[IpSecTransform.DIRECTION_IN])
+ .append("{mSpiResourceId=")
+ .append(mSpiResourceId)
+ .append(", mEncryption=")
+ .append(mEncryption)
+ .append(", mAuthentication=")
+ .append(mAuthentication)
+ .append(", mAuthenticatedEncryption=")
+ .append(mAuthenticatedEncryption)
.append("}");
return strBuilder.toString();
@@ -299,17 +263,18 @@ public final class IpSecConfig implements Parcelable {
public static boolean equals(IpSecConfig lhs, IpSecConfig rhs) {
if (lhs == null || rhs == null) return (lhs == rhs);
return (lhs.mMode == rhs.mMode
- && lhs.mLocalAddress.equals(rhs.mLocalAddress)
- && lhs.mRemoteAddress.equals(rhs.mRemoteAddress)
+ && lhs.mSourceAddress.equals(rhs.mSourceAddress)
+ && lhs.mDestinationAddress.equals(rhs.mDestinationAddress)
&& ((lhs.mNetwork != null && lhs.mNetwork.equals(rhs.mNetwork))
|| (lhs.mNetwork == rhs.mNetwork))
&& lhs.mEncapType == rhs.mEncapType
&& lhs.mEncapSocketResourceId == rhs.mEncapSocketResourceId
&& lhs.mEncapRemotePort == rhs.mEncapRemotePort
&& lhs.mNattKeepaliveInterval == rhs.mNattKeepaliveInterval
- && IpSecConfig.Flow.equals(lhs.mFlow[IpSecTransform.DIRECTION_OUT],
- rhs.mFlow[IpSecTransform.DIRECTION_OUT])
- && IpSecConfig.Flow.equals(lhs.mFlow[IpSecTransform.DIRECTION_IN],
- rhs.mFlow[IpSecTransform.DIRECTION_IN]));
+ && lhs.mSpiResourceId == rhs.mSpiResourceId
+ && IpSecAlgorithm.equals(lhs.mEncryption, rhs.mEncryption)
+ && IpSecAlgorithm.equals(
+ lhs.mAuthenticatedEncryption, rhs.mAuthenticatedEncryption)
+ && IpSecAlgorithm.equals(lhs.mAuthentication, rhs.mAuthentication));
}
}
diff --git a/core/java/android/net/IpSecManager.java b/core/java/android/net/IpSecManager.java
index 34cfa9b2153d..67d4fcac97d6 100644
--- a/core/java/android/net/IpSecManager.java
+++ b/core/java/android/net/IpSecManager.java
@@ -17,6 +17,7 @@ package android.net;
import static com.android.internal.util.Preconditions.checkNotNull;
+import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.SystemService;
import android.annotation.TestApi;
@@ -33,6 +34,8 @@ import dalvik.system.CloseGuard;
import java.io.FileDescriptor;
import java.io.IOException;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.Socket;
@@ -53,6 +56,23 @@ public final class IpSecManager {
private static final String TAG = "IpSecManager";
/**
+ * 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 {@link IpSecTransform}, indicates that an attribute
+ * applies to traffic from the host.
+ */
+ public static final int DIRECTION_OUT = 1;
+
+ /** @hide */
+ @IntDef(value = {DIRECTION_IN, DIRECTION_OUT})
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface PolicyDirection {}
+
+ /**
* The Security Parameter Index (SPI) 0 indicates an unknown or invalid index.
*
* <p>No IPsec packet may contain an SPI of 0.
@@ -125,7 +145,7 @@ public final class IpSecManager {
*/
public static final class SecurityParameterIndex implements AutoCloseable {
private final IIpSecService mService;
- private final InetAddress mRemoteAddress;
+ private final InetAddress mDestinationAddress;
private final CloseGuard mCloseGuard = CloseGuard.get();
private int mSpi = INVALID_SECURITY_PARAMETER_INDEX;
private int mResourceId = INVALID_RESOURCE_ID;
@@ -164,14 +184,14 @@ public final class IpSecManager {
}
private SecurityParameterIndex(
- @NonNull IIpSecService service, int direction, InetAddress remoteAddress, int spi)
+ @NonNull IIpSecService service, InetAddress destinationAddress, int spi)
throws ResourceUnavailableException, SpiUnavailableException {
mService = service;
- mRemoteAddress = remoteAddress;
+ mDestinationAddress = destinationAddress;
try {
IpSecSpiResponse result =
mService.allocateSecurityParameterIndex(
- direction, remoteAddress.getHostAddress(), spi, new Binder());
+ destinationAddress.getHostAddress(), spi, new Binder());
if (result == null) {
throw new NullPointerException("Received null response from IpSecService");
@@ -216,25 +236,23 @@ public final class IpSecManager {
}
/**
- * Reserve a random SPI for traffic bound to or from the specified remote address.
+ * Reserve a random SPI for traffic bound to or from the specified destination 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 destinationAddress the destination address for traffic bearing the requested SPI.
+ * For inbound traffic, the destination should be an address currently assigned on-device.
* @return the reserved SecurityParameterIndex
- * @throws ResourceUnavailableException indicating that too many SPIs are currently allocated
- * for this user
- * @throws SpiUnavailableException indicating that a particular SPI cannot be reserved
+ * @throws {@link #ResourceUnavailableException} indicating that too many SPIs are
+ * currently allocated for this user
*/
- public SecurityParameterIndex allocateSecurityParameterIndex(
- int direction, InetAddress remoteAddress) throws ResourceUnavailableException {
+ public SecurityParameterIndex allocateSecurityParameterIndex(InetAddress destinationAddress)
+ throws ResourceUnavailableException {
try {
return new SecurityParameterIndex(
mService,
- direction,
- remoteAddress,
+ destinationAddress,
IpSecManager.INVALID_SECURITY_PARAMETER_INDEX);
} catch (SpiUnavailableException unlikely) {
throw new ResourceUnavailableException("No SPIs available");
@@ -242,26 +260,27 @@ public final class IpSecManager {
}
/**
- * Reserve the requested SPI for traffic bound to or from the specified remote address.
+ * Reserve the requested SPI for traffic bound to or from the specified destination 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 destinationAddress the destination address for traffic bearing the requested SPI.
+ * For inbound traffic, the destination should be an address currently assigned on-device.
* @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
+ * @throws {@link #ResourceUnavailableException} indicating that too many SPIs are
+ * currently allocated for this user
+ * @throws {@link #SpiUnavailableException} indicating that the requested SPI could not be
+ * reserved
*/
public SecurityParameterIndex allocateSecurityParameterIndex(
- int direction, InetAddress remoteAddress, int requestedSpi)
+ InetAddress destinationAddress, int requestedSpi)
throws SpiUnavailableException, ResourceUnavailableException {
if (requestedSpi == IpSecManager.INVALID_SECURITY_PARAMETER_INDEX) {
throw new IllegalArgumentException("Requested SPI must be a valid (non-zero) SPI");
}
- return new SecurityParameterIndex(mService, direction, remoteAddress, requestedSpi);
+ return new SecurityParameterIndex(mService, destinationAddress, requestedSpi);
}
/**
@@ -269,14 +288,14 @@ public final class IpSecManager {
*
* <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},
+ * the transform is removed from the socket by calling {@link #removeTransportModeTransforms},
* 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}.
+ * IpSecTransform#close()}) without calling {@link #removeTransportModeTransforms}.
*
* <h4>Rekey Procedure</h4>
*
@@ -287,14 +306,15 @@ public final class IpSecManager {
* in-flight packets have been received.
*
* @param socket a stream socket
+ * @param direction the policy direction either {@link #DIRECTION_IN} or {@link #DIRECTION_OUT}
* @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)
+ public void applyTransportModeTransform(
+ Socket socket, int direction, IpSecTransform transform)
throws IOException {
try (ParcelFileDescriptor pfd = ParcelFileDescriptor.fromSocket(socket)) {
- applyTransportModeTransform(pfd, transform);
+ applyTransportModeTransform(pfd, direction, transform);
}
}
@@ -303,14 +323,14 @@ public final class IpSecManager {
*
* <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},
+ * the transform is removed from the socket by calling {@link #removeTransportModeTransforms},
* 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}.
+ * IpSecTransform#close()}) without calling {@link #removeTransportModeTransforms}.
*
* <h4>Rekey Procedure</h4>
*
@@ -321,14 +341,14 @@ public final class IpSecManager {
* in-flight packets have been received.
*
* @param socket a datagram socket
+ * @param direction the policy direction either DIRECTION_IN or DIRECTION_OUT
* @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)
- throws IOException {
+ public void applyTransportModeTransform(
+ DatagramSocket socket, int direction, IpSecTransform transform) throws IOException {
try (ParcelFileDescriptor pfd = ParcelFileDescriptor.fromDatagramSocket(socket)) {
- applyTransportModeTransform(pfd, transform);
+ applyTransportModeTransform(pfd, direction, transform);
}
}
@@ -337,14 +357,14 @@ public final class IpSecManager {
*
* <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},
+ * the transform is removed from the socket by calling {@link #removeTransportModeTransforms},
* 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}.
+ * IpSecTransform#close()}) without calling {@link #removeTransportModeTransforms}.
*
* <h4>Rekey Procedure</h4>
*
@@ -355,24 +375,27 @@ public final class IpSecManager {
* in-flight packets have been received.
*
* @param socket a socket file descriptor
+ * @param direction the policy direction either DIRECTION_IN or DIRECTION_OUT
* @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, int direction, IpSecTransform transform)
throws IOException {
// We dup() the FileDescriptor here because if we don't, then the ParcelFileDescriptor()
// constructor takes control and closes the user's FD when we exit the method
// This is behaviorally the same as the other versions, but the PFD constructor does not
// dup() automatically, whereas PFD.fromSocket() and PDF.fromDatagramSocket() do dup().
try (ParcelFileDescriptor pfd = ParcelFileDescriptor.dup(socket)) {
- applyTransportModeTransform(pfd, transform);
+ applyTransportModeTransform(pfd, direction, transform);
}
}
/* Call down to activate a transform */
- private void applyTransportModeTransform(ParcelFileDescriptor pfd, IpSecTransform transform) {
+ private void applyTransportModeTransform(
+ ParcelFileDescriptor pfd, int direction, IpSecTransform transform) throws IOException {
try {
- mService.applyTransportModeTransform(pfd, transform.getResourceId());
+ mService.applyTransportModeTransform(pfd, direction, transform.getResourceId());
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
@@ -407,12 +430,11 @@ public final class IpSecManager {
* @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)
+ public void removeTransportModeTransforms(Socket socket, IpSecTransform transform)
throws IOException {
try (ParcelFileDescriptor pfd = ParcelFileDescriptor.fromSocket(socket)) {
- removeTransportModeTransform(pfd, transform);
+ removeTransportModeTransforms(pfd, transform);
}
}
@@ -430,12 +452,11 @@ public final class IpSecManager {
* @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)
+ public void removeTransportModeTransforms(DatagramSocket socket, IpSecTransform transform)
throws IOException {
try (ParcelFileDescriptor pfd = ParcelFileDescriptor.fromDatagramSocket(socket)) {
- removeTransportModeTransform(pfd, transform);
+ removeTransportModeTransforms(pfd, transform);
}
}
@@ -454,17 +475,17 @@ public final class IpSecManager {
* @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 removeTransportModeTransforms(FileDescriptor socket, IpSecTransform transform)
throws IOException {
try (ParcelFileDescriptor pfd = ParcelFileDescriptor.dup(socket)) {
- removeTransportModeTransform(pfd, transform);
+ removeTransportModeTransforms(pfd, transform);
}
}
/* Call down to remove a transform */
- private void removeTransportModeTransform(ParcelFileDescriptor pfd, IpSecTransform transform) {
+ private void removeTransportModeTransforms(ParcelFileDescriptor pfd, IpSecTransform transform) {
try {
- mService.removeTransportModeTransform(pfd, transform.getResourceId());
+ mService.removeTransportModeTransforms(pfd, transform.getResourceId());
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
diff --git a/core/java/android/net/IpSecTransform.java b/core/java/android/net/IpSecTransform.java
index 102ba6d94faa..7b9b4830929d 100644
--- a/core/java/android/net/IpSecTransform.java
+++ b/core/java/android/net/IpSecTransform.java
@@ -38,13 +38,11 @@ import java.lang.annotation.RetentionPolicy;
import java.net.InetAddress;
/**
- * This class represents an IPsec transform, which comprises security associations in one or both
- * directions.
+ * This class represents a transform, which roughly corresponds to an IPsec Security Association.
*
* <p>Transforms are created using {@link IpSecTransform.Builder}. Each {@code IpSecTransform}
- * object encapsulates the properties and state of an inbound and outbound IPsec security
- * association. That includes, but is not limited to, algorithm choice, key material, and allocated
- * system resources.
+ * object encapsulates the properties and state of an IPsec security association. That includes,
+ * but is not limited to, algorithm choice, key material, and allocated system resources.
*
* @see <a href="https://tools.ietf.org/html/rfc4301">RFC 4301, Security Architecture for the
* Internet Protocol</a>
@@ -52,23 +50,6 @@ import java.net.InetAddress;
public final class IpSecTransform implements AutoCloseable {
private static final String TAG = "IpSecTransform";
- /**
- * 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 {@link IpSecTransform}, indicates that an attribute
- * applies to traffic from the host.
- */
- public static final int DIRECTION_OUT = 1;
-
- /** @hide */
- @IntDef(value = {DIRECTION_IN, DIRECTION_OUT})
- @Retention(RetentionPolicy.SOURCE)
- public @interface TransformDirection {}
-
/** @hide */
public static final int MODE_TRANSPORT = 0;
@@ -170,7 +151,7 @@ public final class IpSecTransform implements AutoCloseable {
*
* <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
+ * IpSecManager#removeTransportModeTransforms}. Note, removing an {@code IpSecTransform} from a
* socket will not deactivate it (because one transform may be applied to multiple sockets).
*
* <p>It is safe to call this method on a transform that has already been deactivated.
@@ -272,85 +253,49 @@ public final class IpSecTransform implements AutoCloseable {
private IpSecConfig mConfig;
/**
- * Set the encryption algorithm for the given direction.
- *
- * <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.
+ * Set the encryption algorithm.
*
* <p>Encryption is mutually exclusive with authenticated encryption.
*
- * @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) {
+ public IpSecTransform.Builder setEncryption(@NonNull IpSecAlgorithm algo) {
// TODO: throw IllegalArgumentException if algo is not an encryption algorithm.
- mConfig.setEncryption(direction, algo);
+ Preconditions.checkNotNull(algo);
+ mConfig.setEncryption(algo);
return this;
}
/**
- * Set the authentication (integrity) algorithm for the given direction.
- *
- * <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.
+ * Set the authentication (integrity) algorithm.
*
* <p>Authentication is mutually exclusive with authenticated encryption.
*
- * @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) {
+ public IpSecTransform.Builder setAuthentication(@NonNull IpSecAlgorithm algo) {
// TODO: throw IllegalArgumentException if algo is not an authentication algorithm.
- mConfig.setAuthentication(direction, algo);
+ Preconditions.checkNotNull(algo);
+ mConfig.setAuthentication(algo);
return this;
}
/**
- * 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 {@code IpSecTransform} will fail when
- * attempting to build the transform.
+ * Set the authenticated encryption algorithm.
*
- * <p>The Authenticated Encryption (AE) class of algorithms are also known as Authenticated
- * Encryption with Associated Data (AEAD) algorithms, or Combined mode algorithms (as
- * referred to in <a href="https://tools.ietf.org/html/rfc4301">RFC 4301</a>).
+ * <p>The Authenticated Encryption (AE) class of algorithms are also known as
+ * Authenticated Encryption with Associated Data (AEAD) algorithms, or Combined mode
+ * algorithms (as referred to in
+ * <a href="https://tools.ietf.org/html/rfc4301">RFC 4301</a>).
*
* <p>Authenticated encryption is mutually exclusive with encryption and authentication.
*
- * @param direction either {@link #DIRECTION_IN} or {@link #DIRECTION_OUT}
* @param algo {@link IpSecAlgorithm} specifying the authenticated encryption algorithm to
* be applied.
*/
- public IpSecTransform.Builder setAuthenticatedEncryption(
- @TransformDirection int direction, IpSecAlgorithm algo) {
- mConfig.setAuthenticatedEncryption(direction, algo);
- return this;
- }
-
- /**
- * Set the SPI for the given direction.
- *
- * <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#allocateSecurityParameterIndex}.
- *
- * <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 {@link #DIRECTION_OUT}
- * @param spi a unique {@link IpSecManager.SecurityParameterIndex} to identify transformed
- * traffic
- */
- public IpSecTransform.Builder setSpi(
- @TransformDirection int direction, IpSecManager.SecurityParameterIndex spi) {
- if (spi.getResourceId() == INVALID_RESOURCE_ID) {
- throw new IllegalArgumentException("Invalid SecurityParameterIndex");
- }
- mConfig.setSpiResourceId(direction, spi.getResourceId());
+ public IpSecTransform.Builder setAuthenticatedEncryption(@NonNull IpSecAlgorithm algo) {
+ Preconditions.checkNotNull(algo);
+ mConfig.setAuthenticatedEncryption(algo);
return this;
}
@@ -363,7 +308,8 @@ public final class IpSecTransform implements AutoCloseable {
* @hide
*/
@SystemApi
- public IpSecTransform.Builder setUnderlyingNetwork(Network net) {
+ public IpSecTransform.Builder setUnderlyingNetwork(@NonNull Network net) {
+ Preconditions.checkNotNull(net);
mConfig.setNetwork(net);
return this;
}
@@ -382,7 +328,8 @@ public final class IpSecTransform implements AutoCloseable {
* encapsulated traffic. In the case of IKEv2, this should be port 4500.
*/
public IpSecTransform.Builder setIpv4Encapsulation(
- IpSecManager.UdpEncapsulationSocket localSocket, int remotePort) {
+ @NonNull IpSecManager.UdpEncapsulationSocket localSocket, int remotePort) {
+ Preconditions.checkNotNull(localSocket);
mConfig.setEncapType(ENCAP_ESPINUDP);
if (localSocket.getResourceId() == INVALID_RESOURCE_ID) {
throw new IllegalArgumentException("Invalid UdpEncapsulationSocket");
@@ -419,24 +366,33 @@ public final class IpSecTransform implements AutoCloseable {
* will not affect any network traffic until it has been applied to one or more sockets.
*
* @see IpSecManager#applyTransportModeTransform
- * @param remoteAddress the remote {@code InetAddress} of traffic on sockets that will use
- * this transform
+ * @param sourceAddress the source {@code InetAddress} of traffic on sockets that will use
+ * this transform; this address must belong to the Network used by all sockets that
+ * utilize this transform; if provided, then only traffic originating from the
+ * specified source address will be processed.
+ * @param spi a unique {@link IpSecManager.SecurityParameterIndex} to identify transformed
+ * traffic
* @throws IllegalArgumentException indicating that a particular combination of transform
* properties is invalid
- * @throws IpSecManager.ResourceUnavailableException indicating that too many transforms are
- * active
+ * @throws IpSecManager.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)
+ public IpSecTransform buildTransportModeTransform(
+ @NonNull InetAddress sourceAddress,
+ @NonNull IpSecManager.SecurityParameterIndex spi)
throws IpSecManager.ResourceUnavailableException,
IpSecManager.SpiUnavailableException, IOException {
- if (remoteAddress == null) {
- throw new IllegalArgumentException("Remote address may not be null or empty!");
+ Preconditions.checkNotNull(sourceAddress);
+ Preconditions.checkNotNull(spi);
+ if (spi.getResourceId() == INVALID_RESOURCE_ID) {
+ throw new IllegalArgumentException("Invalid SecurityParameterIndex");
}
mConfig.setMode(MODE_TRANSPORT);
- mConfig.setRemoteAddress(remoteAddress.getHostAddress());
+ mConfig.setSourceAddress(sourceAddress.getHostAddress());
+ mConfig.setSpiResourceId(spi.getResourceId());
// FIXME: modifying a builder after calling build can change the built transform.
return new IpSecTransform(mContext, mConfig).activate();
}
@@ -445,26 +401,33 @@ public final class IpSecTransform implements AutoCloseable {
* Build and return an {@link IpSecTransform} object as a Tunnel Mode Transform. Some
* parameters have interdependencies that are checked at build time.
*
- * @param localAddress the {@link InetAddress} that provides the local endpoint for this
+ * @param sourceAddress the {@link InetAddress} that provides the source address for this
* IPsec tunnel. This is almost certainly an address belonging to the {@link Network}
* that will originate the traffic, which is set as the {@link #setUnderlyingNetwork}.
- * @param remoteAddress the {@link InetAddress} representing the remote endpoint of this
- * IPsec tunnel.
+ * @param spi a unique {@link IpSecManager.SecurityParameterIndex} to identify transformed
+ * traffic
* @throws IllegalArgumentException indicating that a particular combination of transform
* properties is invalid.
+ * @throws IpSecManager.ResourceUnavailableException indicating that too many transforms
+ * are active
+ * @throws IpSecManager.SpiUnavailableException indicating the rare case where an SPI
+ * collides with an existing transform
+ * @throws IOException indicating other errors
* @hide
*/
public IpSecTransform buildTunnelModeTransform(
- InetAddress localAddress, InetAddress remoteAddress) {
- if (localAddress == null) {
- throw new IllegalArgumentException("Local address may not be null or empty!");
- }
- if (remoteAddress == null) {
- throw new IllegalArgumentException("Remote address may not be null or empty!");
+ @NonNull InetAddress sourceAddress,
+ @NonNull IpSecManager.SecurityParameterIndex spi)
+ throws IpSecManager.ResourceUnavailableException,
+ IpSecManager.SpiUnavailableException, IOException {
+ Preconditions.checkNotNull(sourceAddress);
+ Preconditions.checkNotNull(spi);
+ if (spi.getResourceId() == INVALID_RESOURCE_ID) {
+ throw new IllegalArgumentException("Invalid SecurityParameterIndex");
}
- mConfig.setLocalAddress(localAddress.getHostAddress());
- mConfig.setRemoteAddress(remoteAddress.getHostAddress());
mConfig.setMode(MODE_TUNNEL);
+ mConfig.setSourceAddress(sourceAddress.getHostAddress());
+ mConfig.setSpiResourceId(spi.getResourceId());
return new IpSecTransform(mContext, mConfig);
}