blob: 37e2c4fbf04a1b5119f49f295d5591331ef82a1b [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();
Benedict Wongf33f03132018-01-18 14:38:16 -0800127 IpSecTransformResponse result = svc.createTransform(mConfig, new Binder());
Nathan Harold8dc1fd02017-04-04 19:37:48 -0700128 int status = result.status;
Nathan Harolda10003d2017-08-23 13:46:33 -0700129 checkResultStatus(status);
Nathan Harold8dc1fd02017-04-04 19:37:48 -0700130 mResourceId = result.resourceId;
Nathan Harold330e1082017-01-12 18:38:57 -0800131
Nathan Harold93962f32017-03-07 13:23:36 -0800132 /* Keepalive will silently fail if not needed by the config; but, if needed and
133 * it fails to start, we need to bail because a transform will not be reliable
134 * to use if keepalive is expected to offload and fails.
135 */
136 // FIXME: if keepalive fails, we need to fail spectacularly
137 startKeepalive(mContext);
138 Log.d(TAG, "Added Transform with Id " + mResourceId);
139 mCloseGuard.open("build");
140 } catch (RemoteException e) {
141 throw e.rethrowAsRuntimeException();
Nathan Harold330e1082017-01-12 18:38:57 -0800142 }
Nathan Harold330e1082017-01-12 18:38:57 -0800143 }
Nathan Harold330e1082017-01-12 18:38:57 -0800144
145 return this;
146 }
147
148 /**
Jonathan Basseric61b70d2017-04-21 15:53:51 -0700149 * Deactivate this {@code IpSecTransform} and free allocated resources.
Nathan Harold330e1082017-01-12 18:38:57 -0800150 *
Jonathan Basseric61b70d2017-04-21 15:53:51 -0700151 * <p>Deactivating a transform while it is still applied to a socket will result in errors on
152 * that socket. Make sure to remove transforms by calling {@link
Nathan Harolda2523312018-01-05 19:25:13 -0800153 * IpSecManager#removeTransportModeTransforms}. Note, removing an {@code IpSecTransform} from a
Jonathan Basseric61b70d2017-04-21 15:53:51 -0700154 * socket will not deactivate it (because one transform may be applied to multiple sockets).
155 *
156 * <p>It is safe to call this method on a transform that has already been deactivated.
Nathan Harold330e1082017-01-12 18:38:57 -0800157 */
158 public void close() {
Nathan Harold93962f32017-03-07 13:23:36 -0800159 Log.d(TAG, "Removing Transform with Id " + mResourceId);
Nathan Harold330e1082017-01-12 18:38:57 -0800160
161 // Always safe to attempt cleanup
Nathan Harold93962f32017-03-07 13:23:36 -0800162 if (mResourceId == INVALID_RESOURCE_ID) {
163 mCloseGuard.close();
Nathan Harold330e1082017-01-12 18:38:57 -0800164 return;
165 }
Nathan Harold93962f32017-03-07 13:23:36 -0800166 try {
167 /* Order matters here because the keepalive is best-effort but could fail in some
168 * horrible way to be removed if the wifi (or cell) subsystem has crashed, and we
169 * still want to clear out the transform.
170 */
171 IIpSecService svc = getIpSecService();
Benedict Wongf33f03132018-01-18 14:38:16 -0800172 svc.deleteTransform(mResourceId);
Nathan Harold93962f32017-03-07 13:23:36 -0800173 stopKeepalive();
174 } catch (RemoteException e) {
175 throw e.rethrowAsRuntimeException();
176 } finally {
177 mResourceId = INVALID_RESOURCE_ID;
178 mCloseGuard.close();
179 }
Nathan Harold330e1082017-01-12 18:38:57 -0800180 }
181
Jonathan Basseric61b70d2017-04-21 15:53:51 -0700182 /** Check that the transform was closed properly. */
Nathan Harold330e1082017-01-12 18:38:57 -0800183 @Override
184 protected void finalize() throws Throwable {
185 if (mCloseGuard != null) {
186 mCloseGuard.warnIfOpen();
187 }
188 close();
189 }
190
191 /* Package */
192 IpSecConfig getConfig() {
193 return mConfig;
194 }
195
196 private final IpSecConfig mConfig;
Nathan Harold93962f32017-03-07 13:23:36 -0800197 private int mResourceId;
Nathan Harold330e1082017-01-12 18:38:57 -0800198 private final Context mContext;
199 private final CloseGuard mCloseGuard = CloseGuard.get();
200 private ConnectivityManager.PacketKeepalive mKeepalive;
201 private int mKeepaliveStatus = ConnectivityManager.PacketKeepalive.NO_KEEPALIVE;
202 private Object mKeepaliveSyncLock = new Object();
203 private ConnectivityManager.PacketKeepaliveCallback mKeepaliveCallback =
204 new ConnectivityManager.PacketKeepaliveCallback() {
205
206 @Override
207 public void onStarted() {
208 synchronized (mKeepaliveSyncLock) {
209 mKeepaliveStatus = ConnectivityManager.PacketKeepalive.SUCCESS;
210 mKeepaliveSyncLock.notifyAll();
211 }
212 }
213
214 @Override
215 public void onStopped() {
216 synchronized (mKeepaliveSyncLock) {
217 mKeepaliveStatus = ConnectivityManager.PacketKeepalive.NO_KEEPALIVE;
218 mKeepaliveSyncLock.notifyAll();
219 }
220 }
221
222 @Override
223 public void onError(int error) {
224 synchronized (mKeepaliveSyncLock) {
225 mKeepaliveStatus = error;
226 mKeepaliveSyncLock.notifyAll();
227 }
228 }
229 };
230
231 /* Package */
232 void startKeepalive(Context c) {
Nathan Harolda10003d2017-08-23 13:46:33 -0700233 if (mConfig.getNattKeepaliveInterval() != 0) {
234 Log.wtf(TAG, "Keepalive not yet supported.");
Nathan Harold330e1082017-01-12 18:38:57 -0800235 }
236 }
237
Nathan Harolda10003d2017-08-23 13:46:33 -0700238 /** @hide */
239 @VisibleForTesting
240 public int getResourceId() {
Nathan Harold93962f32017-03-07 13:23:36 -0800241 return mResourceId;
242 }
243
244 /* Package */
Nathan Harold330e1082017-01-12 18:38:57 -0800245 void stopKeepalive() {
Nathan Harolda10003d2017-08-23 13:46:33 -0700246 return;
Nathan Harold330e1082017-01-12 18:38:57 -0800247 }
248
Jonathan Basseri5fb92902017-11-16 10:58:01 -0800249 /** This class is used to build {@link IpSecTransform} objects. */
Nathan Harold330e1082017-01-12 18:38:57 -0800250 public static class Builder {
251 private Context mContext;
252 private IpSecConfig mConfig;
253
254 /**
Nathan Harolda2523312018-01-05 19:25:13 -0800255 * Set the encryption algorithm.
Nathan Harold330e1082017-01-12 18:38:57 -0800256 *
Jonathan Basseric61b70d2017-04-21 15:53:51 -0700257 * <p>Encryption is mutually exclusive with authenticated encryption.
Benedict Wong0febe5e2017-08-22 21:42:33 -0700258 *
Nathan Harold330e1082017-01-12 18:38:57 -0800259 * @param algo {@link IpSecAlgorithm} specifying the encryption to be applied.
260 */
Nathan Harolda2523312018-01-05 19:25:13 -0800261 public IpSecTransform.Builder setEncryption(@NonNull IpSecAlgorithm algo) {
Jonathan Basseric61b70d2017-04-21 15:53:51 -0700262 // TODO: throw IllegalArgumentException if algo is not an encryption algorithm.
Nathan Harolda2523312018-01-05 19:25:13 -0800263 Preconditions.checkNotNull(algo);
264 mConfig.setEncryption(algo);
Nathan Harold330e1082017-01-12 18:38:57 -0800265 return this;
266 }
267
268 /**
Nathan Harolda2523312018-01-05 19:25:13 -0800269 * Set the authentication (integrity) algorithm.
Nathan Harold330e1082017-01-12 18:38:57 -0800270 *
Jonathan Basseric61b70d2017-04-21 15:53:51 -0700271 * <p>Authentication is mutually exclusive with authenticated encryption.
Benedict Wong0febe5e2017-08-22 21:42:33 -0700272 *
Nathan Harold330e1082017-01-12 18:38:57 -0800273 * @param algo {@link IpSecAlgorithm} specifying the authentication to be applied.
274 */
Nathan Harolda2523312018-01-05 19:25:13 -0800275 public IpSecTransform.Builder setAuthentication(@NonNull IpSecAlgorithm algo) {
Jonathan Basseric61b70d2017-04-21 15:53:51 -0700276 // TODO: throw IllegalArgumentException if algo is not an authentication algorithm.
Nathan Harolda2523312018-01-05 19:25:13 -0800277 Preconditions.checkNotNull(algo);
278 mConfig.setAuthentication(algo);
Nathan Harold330e1082017-01-12 18:38:57 -0800279 return this;
280 }
281
282 /**
Nathan Harolda2523312018-01-05 19:25:13 -0800283 * Set the authenticated encryption algorithm.
Benedict Wong0febe5e2017-08-22 21:42:33 -0700284 *
Nathan Harolda2523312018-01-05 19:25:13 -0800285 * <p>The Authenticated Encryption (AE) class of algorithms are also known as
286 * Authenticated Encryption with Associated Data (AEAD) algorithms, or Combined mode
287 * algorithms (as referred to in
288 * <a href="https://tools.ietf.org/html/rfc4301">RFC 4301</a>).
Benedict Wong0febe5e2017-08-22 21:42:33 -0700289 *
290 * <p>Authenticated encryption is mutually exclusive with encryption and authentication.
291 *
Benedict Wong0febe5e2017-08-22 21:42:33 -0700292 * @param algo {@link IpSecAlgorithm} specifying the authenticated encryption algorithm to
293 * be applied.
294 */
Nathan Harolda2523312018-01-05 19:25:13 -0800295 public IpSecTransform.Builder setAuthenticatedEncryption(@NonNull IpSecAlgorithm algo) {
296 Preconditions.checkNotNull(algo);
297 mConfig.setAuthenticatedEncryption(algo);
Nathan Harold330e1082017-01-12 18:38:57 -0800298 return this;
299 }
300
301 /**
Jonathan Basseric61b70d2017-04-21 15:53:51 -0700302 * Add UDP encapsulation to an IPv4 transform.
Nathan Harold330e1082017-01-12 18:38:57 -0800303 *
Jonathan Basseric61b70d2017-04-21 15:53:51 -0700304 * <p>This allows IPsec traffic to pass through a NAT.
Nathan Harold330e1082017-01-12 18:38:57 -0800305 *
Jonathan Basseric61b70d2017-04-21 15:53:51 -0700306 * @see <a href="https://tools.ietf.org/html/rfc3948">RFC 3948, UDP Encapsulation of IPsec
Jonathan Basseri5fb92902017-11-16 10:58:01 -0800307 * ESP Packets</a>
Jonathan Basseric61b70d2017-04-21 15:53:51 -0700308 * @see <a href="https://tools.ietf.org/html/rfc7296#section-2.23">RFC 7296 section 2.23,
Jonathan Basseri5fb92902017-11-16 10:58:01 -0800309 * NAT Traversal of IKEv2</a>
Jonathan Basseric61b70d2017-04-21 15:53:51 -0700310 * @param localSocket a socket for sending and receiving encapsulated traffic
311 * @param remotePort the UDP port number of the remote host that will send and receive
312 * encapsulated traffic. In the case of IKEv2, this should be port 4500.
Nathan Harold330e1082017-01-12 18:38:57 -0800313 */
314 public IpSecTransform.Builder setIpv4Encapsulation(
Nathan Harolda2523312018-01-05 19:25:13 -0800315 @NonNull IpSecManager.UdpEncapsulationSocket localSocket, int remotePort) {
316 Preconditions.checkNotNull(localSocket);
Nathan Harolda10003d2017-08-23 13:46:33 -0700317 mConfig.setEncapType(ENCAP_ESPINUDP);
Nathan Harold6119d8d2017-12-13 18:51:35 -0800318 if (localSocket.getResourceId() == INVALID_RESOURCE_ID) {
319 throw new IllegalArgumentException("Invalid UdpEncapsulationSocket");
320 }
Nathan Harolda10003d2017-08-23 13:46:33 -0700321 mConfig.setEncapSocketResourceId(localSocket.getResourceId());
322 mConfig.setEncapRemotePort(remotePort);
Nathan Harold330e1082017-01-12 18:38:57 -0800323 return this;
324 }
325
326 // TODO: Decrease the minimum keepalive to maybe 10?
327 // TODO: Probably a better exception to throw for NATTKeepalive failure
328 // TODO: Specify the needed NATT keepalive permission.
329 /**
Jonathan Basseric61b70d2017-04-21 15:53:51 -0700330 * Set NAT-T keepalives to be sent with a given interval.
Nathan Harold330e1082017-01-12 18:38:57 -0800331 *
Jonathan Basseric61b70d2017-04-21 15:53:51 -0700332 * <p>This will set power-efficient keepalive packets to be sent by the system. If NAT-T
333 * keepalive is requested but cannot be activated, then creation of an {@link
334 * IpSecTransform} will fail when calling the build method.
335 *
336 * @param intervalSeconds the maximum number of seconds between keepalive packets. Must be
337 * between 20s and 3600s.
Nathan Harold330e1082017-01-12 18:38:57 -0800338 * @hide
339 */
340 @SystemApi
341 public IpSecTransform.Builder setNattKeepalive(int intervalSeconds) {
Nathan Harolda10003d2017-08-23 13:46:33 -0700342 mConfig.setNattKeepaliveInterval(intervalSeconds);
Nathan Harold330e1082017-01-12 18:38:57 -0800343 return this;
344 }
345
346 /**
Jonathan Basseric61b70d2017-04-21 15:53:51 -0700347 * Build a transport mode {@link IpSecTransform}.
Nathan Harold330e1082017-01-12 18:38:57 -0800348 *
Jonathan Basseric61b70d2017-04-21 15:53:51 -0700349 * <p>This builds and activates a transport mode transform. Note that an active transform
350 * will not affect any network traffic until it has been applied to one or more sockets.
Nathan Harold330e1082017-01-12 18:38:57 -0800351 *
Jonathan Basseric61b70d2017-04-21 15:53:51 -0700352 * @see IpSecManager#applyTransportModeTransform
Nathan Harolda2523312018-01-05 19:25:13 -0800353 * @param sourceAddress the source {@code InetAddress} of traffic on sockets that will use
354 * this transform; this address must belong to the Network used by all sockets that
355 * utilize this transform; if provided, then only traffic originating from the
356 * specified source address will be processed.
357 * @param spi a unique {@link IpSecManager.SecurityParameterIndex} to identify transformed
358 * traffic
Nathan Harold330e1082017-01-12 18:38:57 -0800359 * @throws IllegalArgumentException indicating that a particular combination of transform
Jonathan Basseric61b70d2017-04-21 15:53:51 -0700360 * properties is invalid
Nathan Harolda2523312018-01-05 19:25:13 -0800361 * @throws IpSecManager.ResourceUnavailableException indicating that too many transforms
362 * are active
Jonathan Basseric61b70d2017-04-21 15:53:51 -0700363 * @throws IpSecManager.SpiUnavailableException indicating the rare case where an SPI
364 * collides with an existing transform
365 * @throws IOException indicating other errors
Nathan Harold330e1082017-01-12 18:38:57 -0800366 */
Nathan Harolda2523312018-01-05 19:25:13 -0800367 public IpSecTransform buildTransportModeTransform(
368 @NonNull InetAddress sourceAddress,
369 @NonNull IpSecManager.SecurityParameterIndex spi)
Nathan Harold330e1082017-01-12 18:38:57 -0800370 throws IpSecManager.ResourceUnavailableException,
371 IpSecManager.SpiUnavailableException, IOException {
Nathan Harolda2523312018-01-05 19:25:13 -0800372 Preconditions.checkNotNull(sourceAddress);
373 Preconditions.checkNotNull(spi);
374 if (spi.getResourceId() == INVALID_RESOURCE_ID) {
375 throw new IllegalArgumentException("Invalid SecurityParameterIndex");
Nathan Harold6119d8d2017-12-13 18:51:35 -0800376 }
Nathan Harolda10003d2017-08-23 13:46:33 -0700377 mConfig.setMode(MODE_TRANSPORT);
Nathan Harolda2523312018-01-05 19:25:13 -0800378 mConfig.setSourceAddress(sourceAddress.getHostAddress());
379 mConfig.setSpiResourceId(spi.getResourceId());
Jonathan Basseric61b70d2017-04-21 15:53:51 -0700380 // FIXME: modifying a builder after calling build can change the built transform.
Nathan Harold330e1082017-01-12 18:38:57 -0800381 return new IpSecTransform(mContext, mConfig).activate();
382 }
383
384 /**
385 * Build and return an {@link IpSecTransform} object as a Tunnel Mode Transform. Some
386 * parameters have interdependencies that are checked at build time.
387 *
Nathan Harolda2523312018-01-05 19:25:13 -0800388 * @param sourceAddress the {@link InetAddress} that provides the source address for this
Nathan Harold330e1082017-01-12 18:38:57 -0800389 * IPsec tunnel. This is almost certainly an address belonging to the {@link Network}
390 * that will originate the traffic, which is set as the {@link #setUnderlyingNetwork}.
Nathan Harolda2523312018-01-05 19:25:13 -0800391 * @param spi a unique {@link IpSecManager.SecurityParameterIndex} to identify transformed
392 * traffic
Nathan Harold330e1082017-01-12 18:38:57 -0800393 * @throws IllegalArgumentException indicating that a particular combination of transform
394 * properties is invalid.
Nathan Harolda2523312018-01-05 19:25:13 -0800395 * @throws IpSecManager.ResourceUnavailableException indicating that too many transforms
396 * are active
397 * @throws IpSecManager.SpiUnavailableException indicating the rare case where an SPI
398 * collides with an existing transform
399 * @throws IOException indicating other errors
Nathan Harold330e1082017-01-12 18:38:57 -0800400 * @hide
401 */
Nathan Haroldc47eacc2018-01-17 16:09:24 -0800402 @SystemApi
Nathan Harold330e1082017-01-12 18:38:57 -0800403 public IpSecTransform buildTunnelModeTransform(
Nathan Harolda2523312018-01-05 19:25:13 -0800404 @NonNull InetAddress sourceAddress,
405 @NonNull IpSecManager.SecurityParameterIndex spi)
406 throws IpSecManager.ResourceUnavailableException,
407 IpSecManager.SpiUnavailableException, IOException {
408 Preconditions.checkNotNull(sourceAddress);
409 Preconditions.checkNotNull(spi);
410 if (spi.getResourceId() == INVALID_RESOURCE_ID) {
411 throw new IllegalArgumentException("Invalid SecurityParameterIndex");
Nathan Harold6119d8d2017-12-13 18:51:35 -0800412 }
Nathan Harolda10003d2017-08-23 13:46:33 -0700413 mConfig.setMode(MODE_TUNNEL);
Nathan Harolda2523312018-01-05 19:25:13 -0800414 mConfig.setSourceAddress(sourceAddress.getHostAddress());
415 mConfig.setSpiResourceId(spi.getResourceId());
Nathan Harold330e1082017-01-12 18:38:57 -0800416 return new IpSecTransform(mContext, mConfig);
417 }
418
419 /**
Jonathan Basseric61b70d2017-04-21 15:53:51 -0700420 * Create a new IpSecTransform.Builder.
Nathan Harold330e1082017-01-12 18:38:57 -0800421 *
Jonathan Basseric61b70d2017-04-21 15:53:51 -0700422 * @param context current context
Nathan Harold330e1082017-01-12 18:38:57 -0800423 */
Nathan Harold93962f32017-03-07 13:23:36 -0800424 public Builder(@NonNull Context context) {
425 Preconditions.checkNotNull(context);
Nathan Harold330e1082017-01-12 18:38:57 -0800426 mContext = context;
427 mConfig = new IpSecConfig();
428 }
Nathan Harold330e1082017-01-12 18:38:57 -0800429 }
430}