Add XFRM-I support to IpSecService

This change adds support for XFRM-I to all IpSecService netd calls.
Fallback logic is in netd, and thus both VTI and XFRM-I parameters are
always passed down to IpSecService.

Bug: 78589502
Test: All java, CTS tests passing
Change-Id: Ie4186f0ad7e50763b21831f6fa411b5ee436de78
This commit is contained in:
Benedict Wong
2018-09-06 11:31:25 -07:00
parent 683441d87a
commit 5d74984c24
2 changed files with 70 additions and 28 deletions

View File

@@ -69,6 +69,9 @@ public final class IpSecConfig implements Parcelable {
private int mMarkValue;
private int mMarkMask;
// XFRM interface id
private int mXfrmInterfaceId;
/** Set the mode for this IPsec transform */
public void setMode(int mode) {
mMode = mode;
@@ -145,6 +148,10 @@ public final class IpSecConfig implements Parcelable {
mMarkMask = mask;
}
public void setXfrmInterfaceId(int xfrmInterfaceId) {
mXfrmInterfaceId = xfrmInterfaceId;
}
// Transport or Tunnel
public int getMode() {
return mMode;
@@ -202,6 +209,10 @@ public final class IpSecConfig implements Parcelable {
return mMarkMask;
}
public int getXfrmInterfaceId() {
return mXfrmInterfaceId;
}
// Parcelable Methods
@Override
@@ -225,6 +236,7 @@ public final class IpSecConfig implements Parcelable {
out.writeInt(mNattKeepaliveInterval);
out.writeInt(mMarkValue);
out.writeInt(mMarkMask);
out.writeInt(mXfrmInterfaceId);
}
@VisibleForTesting
@@ -247,6 +259,7 @@ public final class IpSecConfig implements Parcelable {
mNattKeepaliveInterval = c.mNattKeepaliveInterval;
mMarkValue = c.mMarkValue;
mMarkMask = c.mMarkMask;
mXfrmInterfaceId = c.mXfrmInterfaceId;
}
private IpSecConfig(Parcel in) {
@@ -267,6 +280,7 @@ public final class IpSecConfig implements Parcelable {
mNattKeepaliveInterval = in.readInt();
mMarkValue = in.readInt();
mMarkMask = in.readInt();
mXfrmInterfaceId = in.readInt();
}
@Override
@@ -301,6 +315,8 @@ public final class IpSecConfig implements Parcelable {
.append(mMarkValue)
.append(", mMarkMask=")
.append(mMarkMask)
.append(", mXfrmInterfaceId=")
.append(mXfrmInterfaceId)
.append("}");
return strBuilder.toString();
@@ -332,10 +348,10 @@ public final class IpSecConfig implements Parcelable {
&& lhs.mNattKeepaliveInterval == rhs.mNattKeepaliveInterval
&& lhs.mSpiResourceId == rhs.mSpiResourceId
&& IpSecAlgorithm.equals(lhs.mEncryption, rhs.mEncryption)
&& IpSecAlgorithm.equals(
lhs.mAuthenticatedEncryption, rhs.mAuthenticatedEncryption)
&& IpSecAlgorithm.equals(lhs.mAuthenticatedEncryption, rhs.mAuthenticatedEncryption)
&& IpSecAlgorithm.equals(lhs.mAuthentication, rhs.mAuthentication)
&& lhs.mMarkValue == rhs.mMarkValue
&& lhs.mMarkMask == rhs.mMarkMask);
&& lhs.mMarkMask == rhs.mMarkMask
&& lhs.mXfrmInterfaceId == rhs.mXfrmInterfaceId);
}
}

View File

@@ -622,7 +622,8 @@ public class IpSecService extends IIpSecService.Stub {
mConfig.getDestinationAddress(),
spi,
mConfig.getMarkValue(),
mConfig.getMarkMask());
mConfig.getMarkMask(),
mConfig.getXfrmInterfaceId());
} catch (RemoteException | ServiceSpecificException e) {
Log.e(TAG, "Failed to delete SA with ID: " + mResourceId, e);
}
@@ -684,7 +685,8 @@ public class IpSecService extends IIpSecService.Stub {
mSrvConfig
.getNetdInstance()
.ipSecDeleteSecurityAssociation(
uid, mSourceAddress, mDestinationAddress, mSpi, 0, 0);
uid, mSourceAddress, mDestinationAddress, mSpi, 0 /* mark */,
0 /* mask */, 0 /* if_id */);
}
} catch (ServiceSpecificException | RemoteException e) {
Log.e(TAG, "Failed to delete SPI reservation with ID: " + mResourceId, e);
@@ -796,6 +798,8 @@ public class IpSecService extends IIpSecService.Stub {
private final int mIkey;
private final int mOkey;
private final int mIfId;
TunnelInterfaceRecord(
int resourceId,
String interfaceName,
@@ -803,7 +807,8 @@ public class IpSecService extends IIpSecService.Stub {
String localAddr,
String remoteAddr,
int ikey,
int okey) {
int okey,
int intfId) {
super(resourceId);
mInterfaceName = interfaceName;
@@ -812,6 +817,7 @@ public class IpSecService extends IIpSecService.Stub {
mRemoteAddress = remoteAddr;
mIkey = ikey;
mOkey = okey;
mIfId = intfId;
}
/** always guarded by IpSecService#this */
@@ -822,7 +828,7 @@ public class IpSecService extends IIpSecService.Stub {
// Delete global policies
try {
final INetd netd = mSrvConfig.getNetdInstance();
netd.removeVirtualTunnelInterface(mInterfaceName);
netd.ipSecRemoveTunnelInterface(mInterfaceName);
for (int selAddrFamily : ADDRESS_FAMILIES) {
netd.ipSecDeleteSecurityPolicy(
@@ -830,13 +836,15 @@ public class IpSecService extends IIpSecService.Stub {
selAddrFamily,
IpSecManager.DIRECTION_OUT,
mOkey,
0xffffffff);
0xffffffff,
mIfId);
netd.ipSecDeleteSecurityPolicy(
uid,
selAddrFamily,
IpSecManager.DIRECTION_IN,
mIkey,
0xffffffff);
0xffffffff,
mIfId);
}
} catch (ServiceSpecificException | RemoteException e) {
Log.e(
@@ -878,6 +886,10 @@ public class IpSecService extends IIpSecService.Stub {
return mOkey;
}
public int getIfId() {
return mIfId;
}
@Override
protected ResourceTracker getResourceTracker() {
return getUserRecord().mTunnelQuotaTracker;
@@ -1287,7 +1299,7 @@ public class IpSecService extends IIpSecService.Stub {
// Add inbound/outbound global policies
// (use reqid = 0)
final INetd netd = mSrvConfig.getNetdInstance();
netd.addVirtualTunnelInterface(intfName, localAddr, remoteAddr, ikey, okey);
netd.ipSecAddTunnelInterface(intfName, localAddr, remoteAddr, ikey, okey, resourceId);
for (int selAddrFamily : ADDRESS_FAMILIES) {
// Always send down correct local/remote addresses for template.
@@ -1299,7 +1311,8 @@ public class IpSecService extends IIpSecService.Stub {
remoteAddr,
0,
okey,
0xffffffff);
0xffffffff,
resourceId);
netd.ipSecAddSecurityPolicy(
callerUid,
selAddrFamily,
@@ -1308,7 +1321,8 @@ public class IpSecService extends IIpSecService.Stub {
localAddr,
0,
ikey,
0xffffffff);
0xffffffff,
resourceId);
}
userRecord.mTunnelInterfaceRecords.put(
@@ -1321,7 +1335,8 @@ public class IpSecService extends IIpSecService.Stub {
localAddr,
remoteAddr,
ikey,
okey),
okey,
resourceId),
binder));
return new IpSecTunnelInterfaceResponse(IpSecManager.Status.OK, resourceId, intfName);
} catch (RemoteException e) {
@@ -1588,7 +1603,8 @@ public class IpSecService extends IIpSecService.Stub {
(authCrypt != null) ? authCrypt.getTruncationLengthBits() : 0,
encapType,
encapLocalPort,
encapRemotePort);
encapRemotePort,
c.getXfrmInterfaceId());
}
/**
@@ -1744,6 +1760,11 @@ public class IpSecService extends IIpSecService.Stub {
: tunnelInterfaceInfo.getIkey();
try {
// Default to using the invalid SPI of 0 for inbound SAs. This allows policies to skip
// SPI matching as part of the template resolution.
int spi = IpSecManager.INVALID_SECURITY_PARAMETER_INDEX;
c.setXfrmInterfaceId(tunnelInterfaceInfo.getIfId());
// TODO: enable this when UPDSA supports updating marks. Adding kernel support upstream
// (and backporting) would allow us to narrow the mark space, and ensure that the SA
// and SPs have matching marks (as VTI are meant to be built).
@@ -1757,20 +1778,25 @@ public class IpSecService extends IIpSecService.Stub {
// Set output mark via underlying network (output only)
c.setNetwork(tunnelInterfaceInfo.getUnderlyingNetwork());
// If outbound, also add SPI to the policy.
for (int selAddrFamily : ADDRESS_FAMILIES) {
mSrvConfig
.getNetdInstance()
.ipSecUpdateSecurityPolicy(
callingUid,
selAddrFamily,
direction,
tunnelInterfaceInfo.getLocalAddress(),
tunnelInterfaceInfo.getRemoteAddress(),
transformInfo.getSpiRecord().getSpi(),
mark, // Must always set policy mark; ikey/okey for VTIs
0xffffffff);
}
// Set outbound SPI only. We want inbound to use any valid SA (old, new) on rekeys,
// but want to guarantee outbound packets are sent over the new SA.
spi = transformInfo.getSpiRecord().getSpi();
}
// Always update the policy with the relevant XFRM_IF_ID
for (int selAddrFamily : ADDRESS_FAMILIES) {
mSrvConfig
.getNetdInstance()
.ipSecUpdateSecurityPolicy(
callingUid,
selAddrFamily,
direction,
transformInfo.getConfig().getSourceAddress(),
transformInfo.getConfig().getDestinationAddress(),
spi, // If outbound, also add SPI to the policy.
mark, // Must always set policy mark; ikey/okey for VTIs
0xffffffff,
c.getXfrmInterfaceId());
}
// Update SA with tunnel mark (ikey or okey based on direction)