blob: 7b9b4830929d33492a0f2e940e803932b1453fb1 [file] [log] [blame]
Nathan Harold330e1082017-01-12 18:38:57 -08001/*
2 * Copyright (C) 2017 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16package android.net;
17
Nathan Harold93962f32017-03-07 13:23:36 -080018import static android.net.IpSecManager.INVALID_RESOURCE_ID;
Nathan Harold93962f32017-03-07 13:23:36 -080019
Nathan Harold330e1082017-01-12 18:38:57 -080020import android.annotation.IntDef;
Nathan Harold93962f32017-03-07 13:23:36 -080021import android.annotation.NonNull;
Nathan Harold330e1082017-01-12 18:38:57 -080022import android.annotation.SystemApi;
23import android.content.Context;
Nathan Harold93962f32017-03-07 13:23:36 -080024import android.os.Binder;
Nathan Harold93962f32017-03-07 13:23:36 -080025import android.os.IBinder;
26import android.os.RemoteException;
27import android.os.ServiceManager;
Nathan Harold330e1082017-01-12 18:38:57 -080028import android.util.Log;
Nathan Haroldd999d222017-09-11 19:53:33 -070029
ludi1a06aa72017-05-12 09:15:00 -070030import com.android.internal.annotations.VisibleForTesting;
Nathan Harold93962f32017-03-07 13:23:36 -080031import com.android.internal.util.Preconditions;
Nathan Haroldd999d222017-09-11 19:53:33 -070032
Nathan Harold330e1082017-01-12 18:38:57 -080033import dalvik.system.CloseGuard;
Nathan Haroldd999d222017-09-11 19:53:33 -070034
Nathan Harold330e1082017-01-12 18:38:57 -080035import java.io.IOException;
36import java.lang.annotation.Retention;
37import java.lang.annotation.RetentionPolicy;
38import java.net.InetAddress;
39
40/**
Nathan Harolda2523312018-01-05 19:25:13 -080041 * This class represents a transform, which roughly corresponds to an IPsec Security Association.
Nathan Harold330e1082017-01-12 18:38:57 -080042 *
Jonathan Basseric61b70d2017-04-21 15:53:51 -070043 * <p>Transforms are created using {@link IpSecTransform.Builder}. Each {@code IpSecTransform}
Nathan Harolda2523312018-01-05 19:25:13 -080044 * object encapsulates the properties and state of an IPsec security association. That includes,
45 * but is not limited to, algorithm choice, key material, and allocated system resources.
Nathan Harold330e1082017-01-12 18:38:57 -080046 *
Jonathan Basseric61b70d2017-04-21 15:53:51 -070047 * @see <a href="https://tools.ietf.org/html/rfc4301">RFC 4301, Security Architecture for the
Jonathan Basseri5fb92902017-11-16 10:58:01 -080048 * Internet Protocol</a>
Nathan Harold330e1082017-01-12 18:38:57 -080049 */
50public final class IpSecTransform implements AutoCloseable {
51 private static final String TAG = "IpSecTransform";
52
Nathan Harold330e1082017-01-12 18:38:57 -080053 /** @hide */
Nathan Harolda10003d2017-08-23 13:46:33 -070054 public static final int MODE_TRANSPORT = 0;
Nathan Harold330e1082017-01-12 18:38:57 -080055
56 /** @hide */
Nathan Harolda10003d2017-08-23 13:46:33 -070057 public static final int MODE_TUNNEL = 1;
Nathan Harold330e1082017-01-12 18:38:57 -080058
59 /** @hide */
60 public static final int ENCAP_NONE = 0;
61
62 /**
Jonathan Basseric61b70d2017-04-21 15:53:51 -070063 * IPsec traffic will be encapsulated within UDP, but with 8 zero-value bytes between the UDP
64 * header and payload. This prevents traffic from being interpreted as ESP or IKEv2.
Nathan Harold330e1082017-01-12 18:38:57 -080065 *
66 * @hide
67 */
Nathan Harold8dc1fd02017-04-04 19:37:48 -070068 public static final int ENCAP_ESPINUDP_NON_IKE = 1;
69
70 /**
Jonathan Basseric61b70d2017-04-21 15:53:51 -070071 * IPsec traffic will be encapsulated within UDP as per
72 * <a href="https://tools.ietf.org/html/rfc3948">RFC 3498</a>.
Nathan Harold8dc1fd02017-04-04 19:37:48 -070073 *
74 * @hide
75 */
76 public static final int ENCAP_ESPINUDP = 2;
Nathan Harold330e1082017-01-12 18:38:57 -080077
78 /** @hide */
Nathan Harold8dc1fd02017-04-04 19:37:48 -070079 @IntDef(value = {ENCAP_NONE, ENCAP_ESPINUDP, ENCAP_ESPINUDP_NON_IKE})
Nathan Harold330e1082017-01-12 18:38:57 -080080 @Retention(RetentionPolicy.SOURCE)
81 public @interface EncapType {}
82
Nathan Harold330e1082017-01-12 18:38:57 -080083 private IpSecTransform(Context context, IpSecConfig config) {
84 mContext = context;
85 mConfig = config;
Nathan Harold93962f32017-03-07 13:23:36 -080086 mResourceId = INVALID_RESOURCE_ID;
87 }
88
89 private IIpSecService getIpSecService() {
90 IBinder b = ServiceManager.getService(android.content.Context.IPSEC_SERVICE);
91 if (b == null) {
92 throw new RemoteException("Failed to connect to IpSecService")
93 .rethrowAsRuntimeException();
94 }
95
96 return IIpSecService.Stub.asInterface(b);
97 }
98
Nathan Harolda10003d2017-08-23 13:46:33 -070099 /**
Jonathan Basseri5fb92902017-11-16 10:58:01 -0800100 * Checks the result status and throws an appropriate exception if the status is not Status.OK.
Nathan Harolda10003d2017-08-23 13:46:33 -0700101 */
102 private void checkResultStatus(int status)
Nathan Harold93962f32017-03-07 13:23:36 -0800103 throws IOException, IpSecManager.ResourceUnavailableException,
104 IpSecManager.SpiUnavailableException {
105 switch (status) {
106 case IpSecManager.Status.OK:
107 return;
108 // TODO: Pass Error string back from bundle so that errors can be more specific
109 case IpSecManager.Status.RESOURCE_UNAVAILABLE:
110 throw new IpSecManager.ResourceUnavailableException(
111 "Failed to allocate a new IpSecTransform");
112 case IpSecManager.Status.SPI_UNAVAILABLE:
113 Log.wtf(TAG, "Attempting to use an SPI that was somehow not reserved");
114 // Fall through
115 default:
116 throw new IllegalStateException(
117 "Failed to Create a Transform with status code " + status);
118 }
Nathan Harold330e1082017-01-12 18:38:57 -0800119 }
120
121 private IpSecTransform activate()
122 throws IOException, IpSecManager.ResourceUnavailableException,
123 IpSecManager.SpiUnavailableException {
Nathan Harold330e1082017-01-12 18:38:57 -0800124 synchronized (this) {
Nathan Harold93962f32017-03-07 13:23:36 -0800125 try {
126 IIpSecService svc = getIpSecService();
Nathan Harold8dc1fd02017-04-04 19:37:48 -0700127 IpSecTransformResponse result =
128 svc.createTransportModeTransform(mConfig, new Binder());
129 int status = result.status;
Nathan Harolda10003d2017-08-23 13:46:33 -0700130 checkResultStatus(status);
Nathan Harold8dc1fd02017-04-04 19:37:48 -0700131 mResourceId = result.resourceId;
Nathan Harold330e1082017-01-12 18:38:57 -0800132
Nathan Harold93962f32017-03-07 13:23:36 -0800133 /* Keepalive will silently fail if not needed by the config; but, if needed and
134 * it fails to start, we need to bail because a transform will not be reliable
135 * to use if keepalive is expected to offload and fails.
136 */
137 // FIXME: if keepalive fails, we need to fail spectacularly
138 startKeepalive(mContext);
139 Log.d(TAG, "Added Transform with Id " + mResourceId);
140 mCloseGuard.open("build");
141 } catch (RemoteException e) {
142 throw e.rethrowAsRuntimeException();
Nathan Harold330e1082017-01-12 18:38:57 -0800143 }
Nathan Harold330e1082017-01-12 18:38:57 -0800144 }
Nathan Harold330e1082017-01-12 18:38:57 -0800145
146 return this;
147 }
148
149 /**
Jonathan Basseric61b70d2017-04-21 15:53:51 -0700150 * Deactivate this {@code IpSecTransform} and free allocated resources.
Nathan Harold330e1082017-01-12 18:38:57 -0800151 *
Jonathan Basseric61b70d2017-04-21 15:53:51 -0700152 * <p>Deactivating a transform while it is still applied to a socket will result in errors on
153 * that socket. Make sure to remove transforms by calling {@link
Nathan Harolda2523312018-01-05 19:25:13 -0800154 * IpSecManager#removeTransportModeTransforms}. Note, removing an {@code IpSecTransform} from a
Jonathan Basseric61b70d2017-04-21 15:53:51 -0700155 * socket will not deactivate it (because one transform may be applied to multiple sockets).
156 *
157 * <p>It is safe to call this method on a transform that has already been deactivated.
Nathan Harold330e1082017-01-12 18:38:57 -0800158 */
159 public void close() {
Nathan Harold93962f32017-03-07 13:23:36 -0800160 Log.d(TAG, "Removing Transform with Id " + mResourceId);
Nathan Harold330e1082017-01-12 18:38:57 -0800161
162 // Always safe to attempt cleanup
Nathan Harold93962f32017-03-07 13:23:36 -0800163 if (mResourceId == INVALID_RESOURCE_ID) {
164 mCloseGuard.close();
Nathan Harold330e1082017-01-12 18:38:57 -0800165 return;
166 }
Nathan Harold93962f32017-03-07 13:23:36 -0800167 try {
168 /* Order matters here because the keepalive is best-effort but could fail in some
169 * horrible way to be removed if the wifi (or cell) subsystem has crashed, and we
170 * still want to clear out the transform.
171 */
172 IIpSecService svc = getIpSecService();
173 svc.deleteTransportModeTransform(mResourceId);
174 stopKeepalive();
175 } catch (RemoteException e) {
176 throw e.rethrowAsRuntimeException();
177 } finally {
178 mResourceId = INVALID_RESOURCE_ID;
179 mCloseGuard.close();
180 }
Nathan Harold330e1082017-01-12 18:38:57 -0800181 }
182
Jonathan Basseric61b70d2017-04-21 15:53:51 -0700183 /** Check that the transform was closed properly. */
Nathan Harold330e1082017-01-12 18:38:57 -0800184 @Override
185 protected void finalize() throws Throwable {
186 if (mCloseGuard != null) {
187 mCloseGuard.warnIfOpen();
188 }
189 close();
190 }
191
192 /* Package */
193 IpSecConfig getConfig() {
194 return mConfig;
195 }
196
197 private final IpSecConfig mConfig;
Nathan Harold93962f32017-03-07 13:23:36 -0800198 private int mResourceId;
Nathan Harold330e1082017-01-12 18:38:57 -0800199 private final Context mContext;
200 private final CloseGuard mCloseGuard = CloseGuard.get();
201 private ConnectivityManager.PacketKeepalive mKeepalive;
202 private int mKeepaliveStatus = ConnectivityManager.PacketKeepalive.NO_KEEPALIVE;
203 private Object mKeepaliveSyncLock = new Object();
204 private ConnectivityManager.PacketKeepaliveCallback mKeepaliveCallback =
205 new ConnectivityManager.PacketKeepaliveCallback() {
206
207 @Override
208 public void onStarted() {
209 synchronized (mKeepaliveSyncLock) {
210 mKeepaliveStatus = ConnectivityManager.PacketKeepalive.SUCCESS;
211 mKeepaliveSyncLock.notifyAll();
212 }
213 }
214
215 @Override
216 public void onStopped() {
217 synchronized (mKeepaliveSyncLock) {
218 mKeepaliveStatus = ConnectivityManager.PacketKeepalive.NO_KEEPALIVE;
219 mKeepaliveSyncLock.notifyAll();
220 }
221 }
222
223 @Override
224 public void onError(int error) {
225 synchronized (mKeepaliveSyncLock) {
226 mKeepaliveStatus = error;
227 mKeepaliveSyncLock.notifyAll();
228 }
229 }
230 };
231
232 /* Package */
233 void startKeepalive(Context c) {
Nathan Harolda10003d2017-08-23 13:46:33 -0700234 if (mConfig.getNattKeepaliveInterval() != 0) {
235 Log.wtf(TAG, "Keepalive not yet supported.");
Nathan Harold330e1082017-01-12 18:38:57 -0800236 }
237 }
238
Nathan Harolda10003d2017-08-23 13:46:33 -0700239 /** @hide */
240 @VisibleForTesting
241 public int getResourceId() {
Nathan Harold93962f32017-03-07 13:23:36 -0800242 return mResourceId;
243 }
244
245 /* Package */
Nathan Harold330e1082017-01-12 18:38:57 -0800246 void stopKeepalive() {
Nathan Harolda10003d2017-08-23 13:46:33 -0700247 return;
Nathan Harold330e1082017-01-12 18:38:57 -0800248 }
249
Jonathan Basseri5fb92902017-11-16 10:58:01 -0800250 /** This class is used to build {@link IpSecTransform} objects. */
Nathan Harold330e1082017-01-12 18:38:57 -0800251 public static class Builder {
252 private Context mContext;
253 private IpSecConfig mConfig;
254
255 /**
Nathan Harolda2523312018-01-05 19:25:13 -0800256 * Set the encryption algorithm.
Nathan Harold330e1082017-01-12 18:38:57 -0800257 *
Jonathan Basseric61b70d2017-04-21 15:53:51 -0700258 * <p>Encryption is mutually exclusive with authenticated encryption.
Benedict Wong0febe5e2017-08-22 21:42:33 -0700259 *
Nathan Harold330e1082017-01-12 18:38:57 -0800260 * @param algo {@link IpSecAlgorithm} specifying the encryption to be applied.
261 */
Nathan Harolda2523312018-01-05 19:25:13 -0800262 public IpSecTransform.Builder setEncryption(@NonNull IpSecAlgorithm algo) {
Jonathan Basseric61b70d2017-04-21 15:53:51 -0700263 // TODO: throw IllegalArgumentException if algo is not an encryption algorithm.
Nathan Harolda2523312018-01-05 19:25:13 -0800264 Preconditions.checkNotNull(algo);
265 mConfig.setEncryption(algo);
Nathan Harold330e1082017-01-12 18:38:57 -0800266 return this;
267 }
268
269 /**
Nathan Harolda2523312018-01-05 19:25:13 -0800270 * Set the authentication (integrity) algorithm.
Nathan Harold330e1082017-01-12 18:38:57 -0800271 *
Jonathan Basseric61b70d2017-04-21 15:53:51 -0700272 * <p>Authentication is mutually exclusive with authenticated encryption.
Benedict Wong0febe5e2017-08-22 21:42:33 -0700273 *
Nathan Harold330e1082017-01-12 18:38:57 -0800274 * @param algo {@link IpSecAlgorithm} specifying the authentication to be applied.
275 */
Nathan Harolda2523312018-01-05 19:25:13 -0800276 public IpSecTransform.Builder setAuthentication(@NonNull IpSecAlgorithm algo) {
Jonathan Basseric61b70d2017-04-21 15:53:51 -0700277 // TODO: throw IllegalArgumentException if algo is not an authentication algorithm.
Nathan Harolda2523312018-01-05 19:25:13 -0800278 Preconditions.checkNotNull(algo);
279 mConfig.setAuthentication(algo);
Nathan Harold330e1082017-01-12 18:38:57 -0800280 return this;
281 }
282
283 /**
Nathan Harolda2523312018-01-05 19:25:13 -0800284 * Set the authenticated encryption algorithm.
Benedict Wong0febe5e2017-08-22 21:42:33 -0700285 *
Nathan Harolda2523312018-01-05 19:25:13 -0800286 * <p>The Authenticated Encryption (AE) class of algorithms are also known as
287 * Authenticated Encryption with Associated Data (AEAD) algorithms, or Combined mode
288 * algorithms (as referred to in
289 * <a href="https://tools.ietf.org/html/rfc4301">RFC 4301</a>).
Benedict Wong0febe5e2017-08-22 21:42:33 -0700290 *
291 * <p>Authenticated encryption is mutually exclusive with encryption and authentication.
292 *
Benedict Wong0febe5e2017-08-22 21:42:33 -0700293 * @param algo {@link IpSecAlgorithm} specifying the authenticated encryption algorithm to
294 * be applied.
295 */
Nathan Harolda2523312018-01-05 19:25:13 -0800296 public IpSecTransform.Builder setAuthenticatedEncryption(@NonNull IpSecAlgorithm algo) {
297 Preconditions.checkNotNull(algo);
298 mConfig.setAuthenticatedEncryption(algo);
Nathan Harold330e1082017-01-12 18:38:57 -0800299 return this;
300 }
301
302 /**
Jonathan Basseric61b70d2017-04-21 15:53:51 -0700303 * Set the {@link Network} which will carry tunneled traffic.
Nathan Harold330e1082017-01-12 18:38:57 -0800304 *
Jonathan Basseric61b70d2017-04-21 15:53:51 -0700305 * <p>Restricts the transformed traffic to a particular {@link Network}. This is required
306 * for tunnel mode, otherwise tunneled traffic would be sent on the default network.
Nathan Harold330e1082017-01-12 18:38:57 -0800307 *
308 * @hide
309 */
310 @SystemApi
Nathan Harolda2523312018-01-05 19:25:13 -0800311 public IpSecTransform.Builder setUnderlyingNetwork(@NonNull Network net) {
312 Preconditions.checkNotNull(net);
Nathan Harolda10003d2017-08-23 13:46:33 -0700313 mConfig.setNetwork(net);
Nathan Harold330e1082017-01-12 18:38:57 -0800314 return this;
315 }
316
317 /**
Jonathan Basseric61b70d2017-04-21 15:53:51 -0700318 * Add UDP encapsulation to an IPv4 transform.
Nathan Harold330e1082017-01-12 18:38:57 -0800319 *
Jonathan Basseric61b70d2017-04-21 15:53:51 -0700320 * <p>This allows IPsec traffic to pass through a NAT.
Nathan Harold330e1082017-01-12 18:38:57 -0800321 *
Jonathan Basseric61b70d2017-04-21 15:53:51 -0700322 * @see <a href="https://tools.ietf.org/html/rfc3948">RFC 3948, UDP Encapsulation of IPsec
Jonathan Basseri5fb92902017-11-16 10:58:01 -0800323 * ESP Packets</a>
Jonathan Basseric61b70d2017-04-21 15:53:51 -0700324 * @see <a href="https://tools.ietf.org/html/rfc7296#section-2.23">RFC 7296 section 2.23,
Jonathan Basseri5fb92902017-11-16 10:58:01 -0800325 * NAT Traversal of IKEv2</a>
Jonathan Basseric61b70d2017-04-21 15:53:51 -0700326 * @param localSocket a socket for sending and receiving encapsulated traffic
327 * @param remotePort the UDP port number of the remote host that will send and receive
328 * encapsulated traffic. In the case of IKEv2, this should be port 4500.
Nathan Harold330e1082017-01-12 18:38:57 -0800329 */
330 public IpSecTransform.Builder setIpv4Encapsulation(
Nathan Harolda2523312018-01-05 19:25:13 -0800331 @NonNull IpSecManager.UdpEncapsulationSocket localSocket, int remotePort) {
332 Preconditions.checkNotNull(localSocket);
Nathan Harolda10003d2017-08-23 13:46:33 -0700333 mConfig.setEncapType(ENCAP_ESPINUDP);
Nathan Harold6119d8d2017-12-13 18:51:35 -0800334 if (localSocket.getResourceId() == INVALID_RESOURCE_ID) {
335 throw new IllegalArgumentException("Invalid UdpEncapsulationSocket");
336 }
Nathan Harolda10003d2017-08-23 13:46:33 -0700337 mConfig.setEncapSocketResourceId(localSocket.getResourceId());
338 mConfig.setEncapRemotePort(remotePort);
Nathan Harold330e1082017-01-12 18:38:57 -0800339 return this;
340 }
341
342 // TODO: Decrease the minimum keepalive to maybe 10?
343 // TODO: Probably a better exception to throw for NATTKeepalive failure
344 // TODO: Specify the needed NATT keepalive permission.
345 /**
Jonathan Basseric61b70d2017-04-21 15:53:51 -0700346 * Set NAT-T keepalives to be sent with a given interval.
Nathan Harold330e1082017-01-12 18:38:57 -0800347 *
Jonathan Basseric61b70d2017-04-21 15:53:51 -0700348 * <p>This will set power-efficient keepalive packets to be sent by the system. If NAT-T
349 * keepalive is requested but cannot be activated, then creation of an {@link
350 * IpSecTransform} will fail when calling the build method.
351 *
352 * @param intervalSeconds the maximum number of seconds between keepalive packets. Must be
353 * between 20s and 3600s.
Nathan Harold330e1082017-01-12 18:38:57 -0800354 * @hide
355 */
356 @SystemApi
357 public IpSecTransform.Builder setNattKeepalive(int intervalSeconds) {
Nathan Harolda10003d2017-08-23 13:46:33 -0700358 mConfig.setNattKeepaliveInterval(intervalSeconds);
Nathan Harold330e1082017-01-12 18:38:57 -0800359 return this;
360 }
361
362 /**
Jonathan Basseric61b70d2017-04-21 15:53:51 -0700363 * Build a transport mode {@link IpSecTransform}.
Nathan Harold330e1082017-01-12 18:38:57 -0800364 *
Jonathan Basseric61b70d2017-04-21 15:53:51 -0700365 * <p>This builds and activates a transport mode transform. Note that an active transform
366 * will not affect any network traffic until it has been applied to one or more sockets.
Nathan Harold330e1082017-01-12 18:38:57 -0800367 *
Jonathan Basseric61b70d2017-04-21 15:53:51 -0700368 * @see IpSecManager#applyTransportModeTransform
Nathan Harolda2523312018-01-05 19:25:13 -0800369 * @param sourceAddress the source {@code InetAddress} of traffic on sockets that will use
370 * this transform; this address must belong to the Network used by all sockets that
371 * utilize this transform; if provided, then only traffic originating from the
372 * specified source address will be processed.
373 * @param spi a unique {@link IpSecManager.SecurityParameterIndex} to identify transformed
374 * traffic
Nathan Harold330e1082017-01-12 18:38:57 -0800375 * @throws IllegalArgumentException indicating that a particular combination of transform
Jonathan Basseric61b70d2017-04-21 15:53:51 -0700376 * properties is invalid
Nathan Harolda2523312018-01-05 19:25:13 -0800377 * @throws IpSecManager.ResourceUnavailableException indicating that too many transforms
378 * are active
Jonathan Basseric61b70d2017-04-21 15:53:51 -0700379 * @throws IpSecManager.SpiUnavailableException indicating the rare case where an SPI
380 * collides with an existing transform
381 * @throws IOException indicating other errors
Nathan Harold330e1082017-01-12 18:38:57 -0800382 */
Nathan Harolda2523312018-01-05 19:25:13 -0800383 public IpSecTransform buildTransportModeTransform(
384 @NonNull InetAddress sourceAddress,
385 @NonNull IpSecManager.SecurityParameterIndex spi)
Nathan Harold330e1082017-01-12 18:38:57 -0800386 throws IpSecManager.ResourceUnavailableException,
387 IpSecManager.SpiUnavailableException, IOException {
Nathan Harolda2523312018-01-05 19:25:13 -0800388 Preconditions.checkNotNull(sourceAddress);
389 Preconditions.checkNotNull(spi);
390 if (spi.getResourceId() == INVALID_RESOURCE_ID) {
391 throw new IllegalArgumentException("Invalid SecurityParameterIndex");
Nathan Harold6119d8d2017-12-13 18:51:35 -0800392 }
Nathan Harolda10003d2017-08-23 13:46:33 -0700393 mConfig.setMode(MODE_TRANSPORT);
Nathan Harolda2523312018-01-05 19:25:13 -0800394 mConfig.setSourceAddress(sourceAddress.getHostAddress());
395 mConfig.setSpiResourceId(spi.getResourceId());
Jonathan Basseric61b70d2017-04-21 15:53:51 -0700396 // FIXME: modifying a builder after calling build can change the built transform.
Nathan Harold330e1082017-01-12 18:38:57 -0800397 return new IpSecTransform(mContext, mConfig).activate();
398 }
399
400 /**
401 * Build and return an {@link IpSecTransform} object as a Tunnel Mode Transform. Some
402 * parameters have interdependencies that are checked at build time.
403 *
Nathan Harolda2523312018-01-05 19:25:13 -0800404 * @param sourceAddress the {@link InetAddress} that provides the source address for this
Nathan Harold330e1082017-01-12 18:38:57 -0800405 * IPsec tunnel. This is almost certainly an address belonging to the {@link Network}
406 * that will originate the traffic, which is set as the {@link #setUnderlyingNetwork}.
Nathan Harolda2523312018-01-05 19:25:13 -0800407 * @param spi a unique {@link IpSecManager.SecurityParameterIndex} to identify transformed
408 * traffic
Nathan Harold330e1082017-01-12 18:38:57 -0800409 * @throws IllegalArgumentException indicating that a particular combination of transform
410 * properties is invalid.
Nathan Harolda2523312018-01-05 19:25:13 -0800411 * @throws IpSecManager.ResourceUnavailableException indicating that too many transforms
412 * are active
413 * @throws IpSecManager.SpiUnavailableException indicating the rare case where an SPI
414 * collides with an existing transform
415 * @throws IOException indicating other errors
Nathan Harold330e1082017-01-12 18:38:57 -0800416 * @hide
417 */
Nathan Harold330e1082017-01-12 18:38:57 -0800418 public IpSecTransform buildTunnelModeTransform(
Nathan Harolda2523312018-01-05 19:25:13 -0800419 @NonNull InetAddress sourceAddress,
420 @NonNull IpSecManager.SecurityParameterIndex spi)
421 throws IpSecManager.ResourceUnavailableException,
422 IpSecManager.SpiUnavailableException, IOException {
423 Preconditions.checkNotNull(sourceAddress);
424 Preconditions.checkNotNull(spi);
425 if (spi.getResourceId() == INVALID_RESOURCE_ID) {
426 throw new IllegalArgumentException("Invalid SecurityParameterIndex");
Nathan Harold6119d8d2017-12-13 18:51:35 -0800427 }
Nathan Harolda10003d2017-08-23 13:46:33 -0700428 mConfig.setMode(MODE_TUNNEL);
Nathan Harolda2523312018-01-05 19:25:13 -0800429 mConfig.setSourceAddress(sourceAddress.getHostAddress());
430 mConfig.setSpiResourceId(spi.getResourceId());
Nathan Harold330e1082017-01-12 18:38:57 -0800431 return new IpSecTransform(mContext, mConfig);
432 }
433
434 /**
Jonathan Basseric61b70d2017-04-21 15:53:51 -0700435 * Create a new IpSecTransform.Builder.
Nathan Harold330e1082017-01-12 18:38:57 -0800436 *
Jonathan Basseric61b70d2017-04-21 15:53:51 -0700437 * @param context current context
Nathan Harold330e1082017-01-12 18:38:57 -0800438 */
Nathan Harold93962f32017-03-07 13:23:36 -0800439 public Builder(@NonNull Context context) {
440 Preconditions.checkNotNull(context);
Nathan Harold330e1082017-01-12 18:38:57 -0800441 mContext = context;
442 mConfig = new IpSecConfig();
443 }
Nathan Harold330e1082017-01-12 18:38:57 -0800444 }
445}