IpSecManager.java revision 6ea93c4bcaf5c2c8489695308e77b659b70b64d4
1330e1089da80cddcd68758512370d217b19f8890Nathan Harold/*
2330e1089da80cddcd68758512370d217b19f8890Nathan Harold * Copyright (C) 2017 The Android Open Source Project
3330e1089da80cddcd68758512370d217b19f8890Nathan Harold *
4330e1089da80cddcd68758512370d217b19f8890Nathan Harold * Licensed under the Apache License, Version 2.0 (the "License");
5330e1089da80cddcd68758512370d217b19f8890Nathan Harold * you may not use this file except in compliance with the License.
6330e1089da80cddcd68758512370d217b19f8890Nathan Harold * You may obtain a copy of the License at
7330e1089da80cddcd68758512370d217b19f8890Nathan Harold *
8330e1089da80cddcd68758512370d217b19f8890Nathan Harold *      http://www.apache.org/licenses/LICENSE-2.0
9330e1089da80cddcd68758512370d217b19f8890Nathan Harold *
10330e1089da80cddcd68758512370d217b19f8890Nathan Harold * Unless required by applicable law or agreed to in writing, software
11330e1089da80cddcd68758512370d217b19f8890Nathan Harold * distributed under the License is distributed on an "AS IS" BASIS,
12330e1089da80cddcd68758512370d217b19f8890Nathan Harold * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13330e1089da80cddcd68758512370d217b19f8890Nathan Harold * See the License for the specific language governing permissions and
14330e1089da80cddcd68758512370d217b19f8890Nathan Harold * limitations under the License.
15330e1089da80cddcd68758512370d217b19f8890Nathan Harold */
16330e1089da80cddcd68758512370d217b19f8890Nathan Haroldpackage android.net;
17330e1089da80cddcd68758512370d217b19f8890Nathan Harold
18330e1089da80cddcd68758512370d217b19f8890Nathan Haroldimport static com.android.internal.util.Preconditions.checkNotNull;
19330e1089da80cddcd68758512370d217b19f8890Nathan Harold
20a25233123b2d29fde83dd686f6313f0a232c5b2aNathan Haroldimport android.annotation.IntDef;
2193962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Haroldimport android.annotation.NonNull;
225a920ca377efaaaaabf3fe6c77111d8158202055Nathan Haroldimport android.annotation.RequiresPermission;
23c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Haroldimport android.annotation.SystemApi;
24d86b8fea43ebb6e5c31691b44d8ceb0d8d3c9072Jeff Sharkeyimport android.annotation.SystemService;
25c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseriimport android.annotation.TestApi;
26d86b8fea43ebb6e5c31691b44d8ceb0d8d3c9072Jeff Sharkeyimport android.content.Context;
2793962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Haroldimport android.os.Binder;
28330e1089da80cddcd68758512370d217b19f8890Nathan Haroldimport android.os.ParcelFileDescriptor;
2993962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Haroldimport android.os.RemoteException;
30330e1089da80cddcd68758512370d217b19f8890Nathan Haroldimport android.util.AndroidException;
318dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Haroldimport android.util.Log;
32b72821747cd8cfa9bcaff7f11247ebfce3255fbfNathan Harold
33a10003d5de52339f4d30fedd7294941378e5f13cNathan Haroldimport com.android.internal.annotations.VisibleForTesting;
34a10003d5de52339f4d30fedd7294941378e5f13cNathan Harold
35330e1089da80cddcd68758512370d217b19f8890Nathan Haroldimport dalvik.system.CloseGuard;
36b72821747cd8cfa9bcaff7f11247ebfce3255fbfNathan Harold
37330e1089da80cddcd68758512370d217b19f8890Nathan Haroldimport java.io.FileDescriptor;
38330e1089da80cddcd68758512370d217b19f8890Nathan Haroldimport java.io.IOException;
39a25233123b2d29fde83dd686f6313f0a232c5b2aNathan Haroldimport java.lang.annotation.Retention;
40a25233123b2d29fde83dd686f6313f0a232c5b2aNathan Haroldimport java.lang.annotation.RetentionPolicy;
41330e1089da80cddcd68758512370d217b19f8890Nathan Haroldimport java.net.DatagramSocket;
42330e1089da80cddcd68758512370d217b19f8890Nathan Haroldimport java.net.InetAddress;
43330e1089da80cddcd68758512370d217b19f8890Nathan Haroldimport java.net.Socket;
44330e1089da80cddcd68758512370d217b19f8890Nathan Harold
45330e1089da80cddcd68758512370d217b19f8890Nathan Harold/**
46c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri * This class contains methods for managing IPsec sessions. Once configured, the kernel will apply
47c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri * confidentiality (encryption) and integrity (authentication) to IP traffic.
48330e1089da80cddcd68758512370d217b19f8890Nathan Harold *
49c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri * <p>Note that not all aspects of IPsec are permitted by this API. Applications may create
50c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri * transport mode security associations and apply them to individual sockets. Applications looking
51c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri * to create a VPN should use {@link VpnService}.
52c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri *
53c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri * @see <a href="https://tools.ietf.org/html/rfc4301">RFC 4301, Security Architecture for the
545fb929032de14ca78163e1d0c42c34f6fb287da4Jonathan Basseri *     Internet Protocol</a>
55330e1089da80cddcd68758512370d217b19f8890Nathan Harold */
56d86b8fea43ebb6e5c31691b44d8ceb0d8d3c9072Jeff Sharkey@SystemService(Context.IPSEC_SERVICE)
57330e1089da80cddcd68758512370d217b19f8890Nathan Haroldpublic final class IpSecManager {
58330e1089da80cddcd68758512370d217b19f8890Nathan Harold    private static final String TAG = "IpSecManager";
59330e1089da80cddcd68758512370d217b19f8890Nathan Harold
60330e1089da80cddcd68758512370d217b19f8890Nathan Harold    /**
617b7bea048511a54a628a8c340a2890dc50e7b451Nathan Harold     * Used when applying a transform to direct traffic through an {@link IpSecTransform}
627b7bea048511a54a628a8c340a2890dc50e7b451Nathan Harold     * towards the host.
637b7bea048511a54a628a8c340a2890dc50e7b451Nathan Harold     *
647b7bea048511a54a628a8c340a2890dc50e7b451Nathan Harold     * <p>See {@link #applyTransportModeTransform(Socket, int, IpSecTransform)}.
65a25233123b2d29fde83dd686f6313f0a232c5b2aNathan Harold     */
66a25233123b2d29fde83dd686f6313f0a232c5b2aNathan Harold    public static final int DIRECTION_IN = 0;
67a25233123b2d29fde83dd686f6313f0a232c5b2aNathan Harold
68a25233123b2d29fde83dd686f6313f0a232c5b2aNathan Harold    /**
697b7bea048511a54a628a8c340a2890dc50e7b451Nathan Harold     * Used when applying a transform to direct traffic through an {@link IpSecTransform}
707b7bea048511a54a628a8c340a2890dc50e7b451Nathan Harold     * away from the host.
717b7bea048511a54a628a8c340a2890dc50e7b451Nathan Harold     *
727b7bea048511a54a628a8c340a2890dc50e7b451Nathan Harold     * <p>See {@link #applyTransportModeTransform(Socket, int, IpSecTransform)}.
73a25233123b2d29fde83dd686f6313f0a232c5b2aNathan Harold     */
74a25233123b2d29fde83dd686f6313f0a232c5b2aNathan Harold    public static final int DIRECTION_OUT = 1;
75a25233123b2d29fde83dd686f6313f0a232c5b2aNathan Harold
76a25233123b2d29fde83dd686f6313f0a232c5b2aNathan Harold    /** @hide */
77a25233123b2d29fde83dd686f6313f0a232c5b2aNathan Harold    @IntDef(value = {DIRECTION_IN, DIRECTION_OUT})
78a25233123b2d29fde83dd686f6313f0a232c5b2aNathan Harold    @Retention(RetentionPolicy.SOURCE)
79a25233123b2d29fde83dd686f6313f0a232c5b2aNathan Harold    public @interface PolicyDirection {}
80a25233123b2d29fde83dd686f6313f0a232c5b2aNathan Harold
81a25233123b2d29fde83dd686f6313f0a232c5b2aNathan Harold    /**
82c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri     * The Security Parameter Index (SPI) 0 indicates an unknown or invalid index.
8393962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold     *
8493962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold     * <p>No IPsec packet may contain an SPI of 0.
85c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri     *
86c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri     * @hide
8793962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold     */
885fb929032de14ca78163e1d0c42c34f6fb287da4Jonathan Basseri    @TestApi public static final int INVALID_SECURITY_PARAMETER_INDEX = 0;
8993962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold
9093962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold    /** @hide */
9193962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold    public interface Status {
9293962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold        public static final int OK = 0;
9393962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold        public static final int RESOURCE_UNAVAILABLE = 1;
9493962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold        public static final int SPI_UNAVAILABLE = 2;
9593962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold    }
9693962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold
9793962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold    /** @hide */
986119d8d1d0d89b0d4c4ac822e9e93bb47f1ebd9aNathan Harold    public static final int INVALID_RESOURCE_ID = -1;
9993962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold
10093962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold    /**
101c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri     * Thrown to indicate that a requested SPI is in use.
102c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri     *
103c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri     * <p>The combination of remote {@code InetAddress} and SPI must be unique across all apps on
104c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri     * one device. If this error is encountered, a new SPI is required before a transform may be
105c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri     * created. This error can be avoided by calling {@link
1065fb929032de14ca78163e1d0c42c34f6fb287da4Jonathan Basseri     * IpSecManager#allocateSecurityParameterIndex}.
107330e1089da80cddcd68758512370d217b19f8890Nathan Harold     */
108330e1089da80cddcd68758512370d217b19f8890Nathan Harold    public static final class SpiUnavailableException extends AndroidException {
109330e1089da80cddcd68758512370d217b19f8890Nathan Harold        private final int mSpi;
110330e1089da80cddcd68758512370d217b19f8890Nathan Harold
111330e1089da80cddcd68758512370d217b19f8890Nathan Harold        /**
112330e1089da80cddcd68758512370d217b19f8890Nathan Harold         * Construct an exception indicating that a transform with the given SPI is already in use
113330e1089da80cddcd68758512370d217b19f8890Nathan Harold         * or otherwise unavailable.
114330e1089da80cddcd68758512370d217b19f8890Nathan Harold         *
115c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri         * @param msg description indicating the colliding SPI
116330e1089da80cddcd68758512370d217b19f8890Nathan Harold         * @param spi the SPI that could not be used due to a collision
117330e1089da80cddcd68758512370d217b19f8890Nathan Harold         */
118330e1089da80cddcd68758512370d217b19f8890Nathan Harold        SpiUnavailableException(String msg, int spi) {
119c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri            super(msg + " (spi: " + spi + ")");
120330e1089da80cddcd68758512370d217b19f8890Nathan Harold            mSpi = spi;
121330e1089da80cddcd68758512370d217b19f8890Nathan Harold        }
122330e1089da80cddcd68758512370d217b19f8890Nathan Harold
123c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri        /** Get the SPI that caused a collision. */
124330e1089da80cddcd68758512370d217b19f8890Nathan Harold        public int getSpi() {
125330e1089da80cddcd68758512370d217b19f8890Nathan Harold            return mSpi;
126330e1089da80cddcd68758512370d217b19f8890Nathan Harold        }
127330e1089da80cddcd68758512370d217b19f8890Nathan Harold    }
128330e1089da80cddcd68758512370d217b19f8890Nathan Harold
129330e1089da80cddcd68758512370d217b19f8890Nathan Harold    /**
130c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri     * Thrown to indicate that an IPsec resource is unavailable.
131c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri     *
132c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri     * <p>This could apply to resources such as sockets, {@link SecurityParameterIndex}, {@link
133c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri     * IpSecTransform}, or other system resources. If this exception is thrown, users should release
134c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri     * allocated objects of the type requested.
135330e1089da80cddcd68758512370d217b19f8890Nathan Harold     */
136330e1089da80cddcd68758512370d217b19f8890Nathan Harold    public static final class ResourceUnavailableException extends AndroidException {
137330e1089da80cddcd68758512370d217b19f8890Nathan Harold
138330e1089da80cddcd68758512370d217b19f8890Nathan Harold        ResourceUnavailableException(String msg) {
139330e1089da80cddcd68758512370d217b19f8890Nathan Harold            super(msg);
140330e1089da80cddcd68758512370d217b19f8890Nathan Harold        }
141330e1089da80cddcd68758512370d217b19f8890Nathan Harold    }
142330e1089da80cddcd68758512370d217b19f8890Nathan Harold
1431afbef40c68373f3871eed087c546cfe1911ee36Nathan Harold    private final IIpSecService mService;
144330e1089da80cddcd68758512370d217b19f8890Nathan Harold
145c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri    /**
146c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri     * This class represents a reserved SPI.
147c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri     *
148c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri     * <p>Objects of this type are used to track reserved security parameter indices. They can be
1495fb929032de14ca78163e1d0c42c34f6fb287da4Jonathan Basseri     * obtained by calling {@link IpSecManager#allocateSecurityParameterIndex} and must be released
150c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri     * by calling {@link #close()} when they are no longer needed.
151c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri     */
152330e1089da80cddcd68758512370d217b19f8890Nathan Harold    public static final class SecurityParameterIndex implements AutoCloseable {
1531afbef40c68373f3871eed087c546cfe1911ee36Nathan Harold        private final IIpSecService mService;
154a25233123b2d29fde83dd686f6313f0a232c5b2aNathan Harold        private final InetAddress mDestinationAddress;
155330e1089da80cddcd68758512370d217b19f8890Nathan Harold        private final CloseGuard mCloseGuard = CloseGuard.get();
15693962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold        private int mSpi = INVALID_SECURITY_PARAMETER_INDEX;
1576119d8d1d0d89b0d4c4ac822e9e93bb47f1ebd9aNathan Harold        private int mResourceId = INVALID_RESOURCE_ID;
158330e1089da80cddcd68758512370d217b19f8890Nathan Harold
159c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri        /** Get the underlying SPI held by this object. */
160330e1089da80cddcd68758512370d217b19f8890Nathan Harold        public int getSpi() {
161330e1089da80cddcd68758512370d217b19f8890Nathan Harold            return mSpi;
162330e1089da80cddcd68758512370d217b19f8890Nathan Harold        }
163330e1089da80cddcd68758512370d217b19f8890Nathan Harold
164330e1089da80cddcd68758512370d217b19f8890Nathan Harold        /**
165330e1089da80cddcd68758512370d217b19f8890Nathan Harold         * Release an SPI that was previously reserved.
166330e1089da80cddcd68758512370d217b19f8890Nathan Harold         *
167c4f879925b58b1b5ca9a3cfdc898c20cbf56355aNathan Harold         * <p>Release an SPI for use by other users in the system. If a SecurityParameterIndex is
168c4f879925b58b1b5ca9a3cfdc898c20cbf56355aNathan Harold         * applied to an IpSecTransform, it will become unusable for future transforms but should
169c4f879925b58b1b5ca9a3cfdc898c20cbf56355aNathan Harold         * still be closed to ensure system resources are released.
170330e1089da80cddcd68758512370d217b19f8890Nathan Harold         */
171330e1089da80cddcd68758512370d217b19f8890Nathan Harold        @Override
172330e1089da80cddcd68758512370d217b19f8890Nathan Harold        public void close() {
1738dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold            try {
1748dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold                mService.releaseSecurityParameterIndex(mResourceId);
1756119d8d1d0d89b0d4c4ac822e9e93bb47f1ebd9aNathan Harold                mResourceId = INVALID_RESOURCE_ID;
1768dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold            } catch (RemoteException e) {
1778dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold                throw e.rethrowFromSystemServer();
1788dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold            }
179330e1089da80cddcd68758512370d217b19f8890Nathan Harold            mCloseGuard.close();
180330e1089da80cddcd68758512370d217b19f8890Nathan Harold        }
181330e1089da80cddcd68758512370d217b19f8890Nathan Harold
182c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri        /** Check that the SPI was closed properly. */
183330e1089da80cddcd68758512370d217b19f8890Nathan Harold        @Override
184440824f7434e1e2c343b21a9ca3e6f405b8e0ea1Nathan Harold        protected void finalize() throws Throwable {
185330e1089da80cddcd68758512370d217b19f8890Nathan Harold            if (mCloseGuard != null) {
186330e1089da80cddcd68758512370d217b19f8890Nathan Harold                mCloseGuard.warnIfOpen();
187330e1089da80cddcd68758512370d217b19f8890Nathan Harold            }
188330e1089da80cddcd68758512370d217b19f8890Nathan Harold
189330e1089da80cddcd68758512370d217b19f8890Nathan Harold            close();
190330e1089da80cddcd68758512370d217b19f8890Nathan Harold        }
191330e1089da80cddcd68758512370d217b19f8890Nathan Harold
19293962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold        private SecurityParameterIndex(
193a25233123b2d29fde83dd686f6313f0a232c5b2aNathan Harold                @NonNull IIpSecService service, InetAddress destinationAddress, int spi)
19493962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold                throws ResourceUnavailableException, SpiUnavailableException {
19593962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold            mService = service;
196a25233123b2d29fde83dd686f6313f0a232c5b2aNathan Harold            mDestinationAddress = destinationAddress;
19793962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold            try {
1988dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold                IpSecSpiResponse result =
1995fb929032de14ca78163e1d0c42c34f6fb287da4Jonathan Basseri                        mService.allocateSecurityParameterIndex(
200a25233123b2d29fde83dd686f6313f0a232c5b2aNathan Harold                                destinationAddress.getHostAddress(), spi, new Binder());
20193962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold
20293962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold                if (result == null) {
20393962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold                    throw new NullPointerException("Received null response from IpSecService");
20493962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold                }
20593962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold
2068dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold                int status = result.status;
20793962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold                switch (status) {
20893962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold                    case Status.OK:
20993962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold                        break;
21093962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold                    case Status.RESOURCE_UNAVAILABLE:
21193962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold                        throw new ResourceUnavailableException(
21293962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold                                "No more SPIs may be allocated by this requester.");
21393962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold                    case Status.SPI_UNAVAILABLE:
21493962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold                        throw new SpiUnavailableException("Requested SPI is unavailable", spi);
21593962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold                    default:
21693962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold                        throw new RuntimeException(
21793962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold                                "Unknown status returned by IpSecService: " + status);
21893962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold                }
2198dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold                mSpi = result.spi;
2208dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold                mResourceId = result.resourceId;
22193962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold
22293962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold                if (mSpi == INVALID_SECURITY_PARAMETER_INDEX) {
22393962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold                    throw new RuntimeException("Invalid SPI returned by IpSecService: " + status);
22493962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold                }
22593962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold
22693962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold                if (mResourceId == INVALID_RESOURCE_ID) {
22793962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold                    throw new RuntimeException(
22893962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold                            "Invalid Resource ID returned by IpSecService: " + status);
22993962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold                }
23093962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold
23193962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold            } catch (RemoteException e) {
23293962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold                throw e.rethrowFromSystemServer();
23393962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold            }
23493962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold            mCloseGuard.open("open");
23593962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold        }
2368dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold
2378dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold        /** @hide */
238a10003d5de52339f4d30fedd7294941378e5f13cNathan Harold        @VisibleForTesting
239a10003d5de52339f4d30fedd7294941378e5f13cNathan Harold        public int getResourceId() {
2408dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold            return mResourceId;
2418dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold        }
24293962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold    }
243330e1089da80cddcd68758512370d217b19f8890Nathan Harold
244330e1089da80cddcd68758512370d217b19f8890Nathan Harold    /**
245a25233123b2d29fde83dd686f6313f0a232c5b2aNathan Harold     * Reserve a random SPI for traffic bound to or from the specified destination address.
246330e1089da80cddcd68758512370d217b19f8890Nathan Harold     *
247330e1089da80cddcd68758512370d217b19f8890Nathan Harold     * <p>If successful, this SPI is guaranteed available until released by a call to {@link
248330e1089da80cddcd68758512370d217b19f8890Nathan Harold     * SecurityParameterIndex#close()}.
249330e1089da80cddcd68758512370d217b19f8890Nathan Harold     *
250a25233123b2d29fde83dd686f6313f0a232c5b2aNathan Harold     * @param destinationAddress the destination address for traffic bearing the requested SPI.
251a25233123b2d29fde83dd686f6313f0a232c5b2aNathan Harold     *     For inbound traffic, the destination should be an address currently assigned on-device.
252330e1089da80cddcd68758512370d217b19f8890Nathan Harold     * @return the reserved SecurityParameterIndex
253a25233123b2d29fde83dd686f6313f0a232c5b2aNathan Harold     * @throws {@link #ResourceUnavailableException} indicating that too many SPIs are
254a25233123b2d29fde83dd686f6313f0a232c5b2aNathan Harold     *     currently allocated for this user
255330e1089da80cddcd68758512370d217b19f8890Nathan Harold     */
2565cd64cc8012243c656875be6b84456caeabd60f5Nathan Harold    @NonNull
2575cd64cc8012243c656875be6b84456caeabd60f5Nathan Harold    public SecurityParameterIndex allocateSecurityParameterIndex(
2585cd64cc8012243c656875be6b84456caeabd60f5Nathan Harold                @NonNull InetAddress destinationAddress) throws ResourceUnavailableException {
2596045429b35ca4c1cbd920e5e0872dec9de493fdeNathan Harold        try {
2606045429b35ca4c1cbd920e5e0872dec9de493fdeNathan Harold            return new SecurityParameterIndex(
2616045429b35ca4c1cbd920e5e0872dec9de493fdeNathan Harold                    mService,
262a25233123b2d29fde83dd686f6313f0a232c5b2aNathan Harold                    destinationAddress,
2636045429b35ca4c1cbd920e5e0872dec9de493fdeNathan Harold                    IpSecManager.INVALID_SECURITY_PARAMETER_INDEX);
2646045429b35ca4c1cbd920e5e0872dec9de493fdeNathan Harold        } catch (SpiUnavailableException unlikely) {
2656045429b35ca4c1cbd920e5e0872dec9de493fdeNathan Harold            throw new ResourceUnavailableException("No SPIs available");
2666045429b35ca4c1cbd920e5e0872dec9de493fdeNathan Harold        }
2676045429b35ca4c1cbd920e5e0872dec9de493fdeNathan Harold    }
2686045429b35ca4c1cbd920e5e0872dec9de493fdeNathan Harold
2696045429b35ca4c1cbd920e5e0872dec9de493fdeNathan Harold    /**
270a25233123b2d29fde83dd686f6313f0a232c5b2aNathan Harold     * Reserve the requested SPI for traffic bound to or from the specified destination address.
2716045429b35ca4c1cbd920e5e0872dec9de493fdeNathan Harold     *
2726045429b35ca4c1cbd920e5e0872dec9de493fdeNathan Harold     * <p>If successful, this SPI is guaranteed available until released by a call to {@link
2736045429b35ca4c1cbd920e5e0872dec9de493fdeNathan Harold     * SecurityParameterIndex#close()}.
2746045429b35ca4c1cbd920e5e0872dec9de493fdeNathan Harold     *
275a25233123b2d29fde83dd686f6313f0a232c5b2aNathan Harold     * @param destinationAddress the destination address for traffic bearing the requested SPI.
276a25233123b2d29fde83dd686f6313f0a232c5b2aNathan Harold     *     For inbound traffic, the destination should be an address currently assigned on-device.
277c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri     * @param requestedSpi the requested SPI, or '0' to allocate a random SPI
2786045429b35ca4c1cbd920e5e0872dec9de493fdeNathan Harold     * @return the reserved SecurityParameterIndex
279a25233123b2d29fde83dd686f6313f0a232c5b2aNathan Harold     * @throws {@link #ResourceUnavailableException} indicating that too many SPIs are
280a25233123b2d29fde83dd686f6313f0a232c5b2aNathan Harold     *     currently allocated for this user
281a25233123b2d29fde83dd686f6313f0a232c5b2aNathan Harold     * @throws {@link #SpiUnavailableException} indicating that the requested SPI could not be
282a25233123b2d29fde83dd686f6313f0a232c5b2aNathan Harold     *     reserved
2836045429b35ca4c1cbd920e5e0872dec9de493fdeNathan Harold     */
2845cd64cc8012243c656875be6b84456caeabd60f5Nathan Harold    @NonNull
2855fb929032de14ca78163e1d0c42c34f6fb287da4Jonathan Basseri    public SecurityParameterIndex allocateSecurityParameterIndex(
2865cd64cc8012243c656875be6b84456caeabd60f5Nathan Harold            @NonNull InetAddress destinationAddress, int requestedSpi)
287330e1089da80cddcd68758512370d217b19f8890Nathan Harold            throws SpiUnavailableException, ResourceUnavailableException {
2886045429b35ca4c1cbd920e5e0872dec9de493fdeNathan Harold        if (requestedSpi == IpSecManager.INVALID_SECURITY_PARAMETER_INDEX) {
2896045429b35ca4c1cbd920e5e0872dec9de493fdeNathan Harold            throw new IllegalArgumentException("Requested SPI must be a valid (non-zero) SPI");
2906045429b35ca4c1cbd920e5e0872dec9de493fdeNathan Harold        }
291a25233123b2d29fde83dd686f6313f0a232c5b2aNathan Harold        return new SecurityParameterIndex(mService, destinationAddress, requestedSpi);
292330e1089da80cddcd68758512370d217b19f8890Nathan Harold    }
293330e1089da80cddcd68758512370d217b19f8890Nathan Harold
294330e1089da80cddcd68758512370d217b19f8890Nathan Harold    /**
295c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri     * Apply an IPsec transform to a stream socket.
296c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri     *
297c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri     * <p>This applies transport mode encapsulation to the given socket. Once applied, I/O on the
298c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri     * socket will be encapsulated according to the parameters of the {@code IpSecTransform}. When
299a25233123b2d29fde83dd686f6313f0a232c5b2aNathan Harold     * the transform is removed from the socket by calling {@link #removeTransportModeTransforms},
300c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri     * unprotected traffic can resume on that socket.
301c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri     *
302c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri     * <p>For security reasons, the destination address of any traffic on the socket must match the
3035fb929032de14ca78163e1d0c42c34f6fb287da4Jonathan Basseri     * remote {@code InetAddress} of the {@code IpSecTransform}. Attempts to send traffic to any
304c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri     * other IP address will result in an IOException. In addition, reads and writes on the socket
305c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri     * will throw IOException if the user deactivates the transform (by calling {@link
306a25233123b2d29fde83dd686f6313f0a232c5b2aNathan Harold     * IpSecTransform#close()}) without calling {@link #removeTransportModeTransforms}.
307c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri     *
308420fe002f1d35e870d519344a13de9f6501e4ddbBenedict Wong     * <p>Note that when applied to TCP sockets, calling {@link IpSecTransform#close()} on an
309420fe002f1d35e870d519344a13de9f6501e4ddbBenedict Wong     * applied transform before completion of graceful shutdown may result in the shutdown sequence
310420fe002f1d35e870d519344a13de9f6501e4ddbBenedict Wong     * failing to complete. As such, applications requiring graceful shutdown MUST close the socket
311420fe002f1d35e870d519344a13de9f6501e4ddbBenedict Wong     * prior to deactivating the applied transform. Socket closure may be performed asynchronously
312420fe002f1d35e870d519344a13de9f6501e4ddbBenedict Wong     * (in batches), so the returning of a close function does not guarantee shutdown of a socket.
313420fe002f1d35e870d519344a13de9f6501e4ddbBenedict Wong     * Setting an SO_LINGER timeout results in socket closure being performed synchronously, and is
314420fe002f1d35e870d519344a13de9f6501e4ddbBenedict Wong     * sufficient to ensure shutdown.
315420fe002f1d35e870d519344a13de9f6501e4ddbBenedict Wong     *
316420fe002f1d35e870d519344a13de9f6501e4ddbBenedict Wong     * Specifically, if the transform is deactivated (by calling {@link IpSecTransform#close()}),
317420fe002f1d35e870d519344a13de9f6501e4ddbBenedict Wong     * prior to the socket being closed, the standard [FIN - FIN/ACK - ACK], or the reset [RST]
318420fe002f1d35e870d519344a13de9f6501e4ddbBenedict Wong     * packets are dropped due to the lack of a valid Transform. Similarly, if a socket without the
319420fe002f1d35e870d519344a13de9f6501e4ddbBenedict Wong     * SO_LINGER option set is closed, the delayed/batched FIN packets may be dropped.
320420fe002f1d35e870d519344a13de9f6501e4ddbBenedict Wong     *
3215fb929032de14ca78163e1d0c42c34f6fb287da4Jonathan Basseri     * <h4>Rekey Procedure</h4>
3225fb929032de14ca78163e1d0c42c34f6fb287da4Jonathan Basseri     *
3237b7bea048511a54a628a8c340a2890dc50e7b451Nathan Harold     * <p>When applying a new tranform to a socket in the outbound direction, the previous transform
3247b7bea048511a54a628a8c340a2890dc50e7b451Nathan Harold     * will be removed and the new transform will take effect immediately, sending all traffic on
3257b7bea048511a54a628a8c340a2890dc50e7b451Nathan Harold     * the new transform; however, when applying a transform in the inbound direction, traffic
3267b7bea048511a54a628a8c340a2890dc50e7b451Nathan Harold     * on the old transform will continue to be decrypted and delivered until that transform is
3277b7bea048511a54a628a8c340a2890dc50e7b451Nathan Harold     * deallocated by calling {@link IpSecTransform#close()}. This overlap allows lossless rekey
3287b7bea048511a54a628a8c340a2890dc50e7b451Nathan Harold     * procedures where both transforms are valid until both endpoints are using the new transform
3297b7bea048511a54a628a8c340a2890dc50e7b451Nathan Harold     * and all in-flight packets have been received.
330330e1089da80cddcd68758512370d217b19f8890Nathan Harold     *
331330e1089da80cddcd68758512370d217b19f8890Nathan Harold     * @param socket a stream socket
3327b7bea048511a54a628a8c340a2890dc50e7b451Nathan Harold     * @param direction the direction in which the transform should be applied
333c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri     * @param transform a transport mode {@code IpSecTransform}
334c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri     * @throws IOException indicating that the transform could not be applied
335330e1089da80cddcd68758512370d217b19f8890Nathan Harold     */
3365cd64cc8012243c656875be6b84456caeabd60f5Nathan Harold    public void applyTransportModeTransform(@NonNull Socket socket,
3375cd64cc8012243c656875be6b84456caeabd60f5Nathan Harold            @PolicyDirection int direction, @NonNull IpSecTransform transform) throws IOException {
338b548d251b7995a5b76e495978b61ad6c3c4183d1Nathan Harold        applyTransportModeTransform(socket.getFileDescriptor$(), direction, transform);
339330e1089da80cddcd68758512370d217b19f8890Nathan Harold    }
340330e1089da80cddcd68758512370d217b19f8890Nathan Harold
341330e1089da80cddcd68758512370d217b19f8890Nathan Harold    /**
342c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri     * Apply an IPsec transform to a datagram socket.
343c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri     *
344c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri     * <p>This applies transport mode encapsulation to the given socket. Once applied, I/O on the
345c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri     * socket will be encapsulated according to the parameters of the {@code IpSecTransform}. When
346a25233123b2d29fde83dd686f6313f0a232c5b2aNathan Harold     * the transform is removed from the socket by calling {@link #removeTransportModeTransforms},
347c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri     * unprotected traffic can resume on that socket.
348c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri     *
349c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri     * <p>For security reasons, the destination address of any traffic on the socket must match the
350c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri     * remote {@code InetAddress} of the {@code IpSecTransform}. Attempts to send traffic to any
351c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri     * other IP address will result in an IOException. In addition, reads and writes on the socket
352c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri     * will throw IOException if the user deactivates the transform (by calling {@link
353a25233123b2d29fde83dd686f6313f0a232c5b2aNathan Harold     * IpSecTransform#close()}) without calling {@link #removeTransportModeTransforms}.
354c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri     *
3555fb929032de14ca78163e1d0c42c34f6fb287da4Jonathan Basseri     * <h4>Rekey Procedure</h4>
3565fb929032de14ca78163e1d0c42c34f6fb287da4Jonathan Basseri     *
3577b7bea048511a54a628a8c340a2890dc50e7b451Nathan Harold     * <p>When applying a new tranform to a socket in the outbound direction, the previous transform
3587b7bea048511a54a628a8c340a2890dc50e7b451Nathan Harold     * will be removed and the new transform will take effect immediately, sending all traffic on
3597b7bea048511a54a628a8c340a2890dc50e7b451Nathan Harold     * the new transform; however, when applying a transform in the inbound direction, traffic
3607b7bea048511a54a628a8c340a2890dc50e7b451Nathan Harold     * on the old transform will continue to be decrypted and delivered until that transform is
3617b7bea048511a54a628a8c340a2890dc50e7b451Nathan Harold     * deallocated by calling {@link IpSecTransform#close()}. This overlap allows lossless rekey
3627b7bea048511a54a628a8c340a2890dc50e7b451Nathan Harold     * procedures where both transforms are valid until both endpoints are using the new transform
3637b7bea048511a54a628a8c340a2890dc50e7b451Nathan Harold     * and all in-flight packets have been received.
364330e1089da80cddcd68758512370d217b19f8890Nathan Harold     *
365330e1089da80cddcd68758512370d217b19f8890Nathan Harold     * @param socket a datagram socket
3667b7bea048511a54a628a8c340a2890dc50e7b451Nathan Harold     * @param direction the direction in which the transform should be applied
367c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri     * @param transform a transport mode {@code IpSecTransform}
368c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri     * @throws IOException indicating that the transform could not be applied
369330e1089da80cddcd68758512370d217b19f8890Nathan Harold     */
3705cd64cc8012243c656875be6b84456caeabd60f5Nathan Harold    public void applyTransportModeTransform(@NonNull DatagramSocket socket,
3715cd64cc8012243c656875be6b84456caeabd60f5Nathan Harold            @PolicyDirection int direction, @NonNull IpSecTransform transform) throws IOException {
372b548d251b7995a5b76e495978b61ad6c3c4183d1Nathan Harold        applyTransportModeTransform(socket.getFileDescriptor$(), direction, transform);
37393962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold    }
374330e1089da80cddcd68758512370d217b19f8890Nathan Harold
375330e1089da80cddcd68758512370d217b19f8890Nathan Harold    /**
376c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri     * Apply an IPsec transform to a socket.
377c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri     *
378c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri     * <p>This applies transport mode encapsulation to the given socket. Once applied, I/O on the
379c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri     * socket will be encapsulated according to the parameters of the {@code IpSecTransform}. When
380a25233123b2d29fde83dd686f6313f0a232c5b2aNathan Harold     * the transform is removed from the socket by calling {@link #removeTransportModeTransforms},
381c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri     * unprotected traffic can resume on that socket.
382c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri     *
383c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri     * <p>For security reasons, the destination address of any traffic on the socket must match the
384c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri     * remote {@code InetAddress} of the {@code IpSecTransform}. Attempts to send traffic to any
385c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri     * other IP address will result in an IOException. In addition, reads and writes on the socket
386c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri     * will throw IOException if the user deactivates the transform (by calling {@link
387a25233123b2d29fde83dd686f6313f0a232c5b2aNathan Harold     * IpSecTransform#close()}) without calling {@link #removeTransportModeTransforms}.
388c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri     *
389420fe002f1d35e870d519344a13de9f6501e4ddbBenedict Wong     * <p>Note that when applied to TCP sockets, calling {@link IpSecTransform#close()} on an
390420fe002f1d35e870d519344a13de9f6501e4ddbBenedict Wong     * applied transform before completion of graceful shutdown may result in the shutdown sequence
391420fe002f1d35e870d519344a13de9f6501e4ddbBenedict Wong     * failing to complete. As such, applications requiring graceful shutdown MUST close the socket
392420fe002f1d35e870d519344a13de9f6501e4ddbBenedict Wong     * prior to deactivating the applied transform. Socket closure may be performed asynchronously
393420fe002f1d35e870d519344a13de9f6501e4ddbBenedict Wong     * (in batches), so the returning of a close function does not guarantee shutdown of a socket.
394420fe002f1d35e870d519344a13de9f6501e4ddbBenedict Wong     * Setting an SO_LINGER timeout results in socket closure being performed synchronously, and is
395420fe002f1d35e870d519344a13de9f6501e4ddbBenedict Wong     * sufficient to ensure shutdown.
396420fe002f1d35e870d519344a13de9f6501e4ddbBenedict Wong     *
397420fe002f1d35e870d519344a13de9f6501e4ddbBenedict Wong     * Specifically, if the transform is deactivated (by calling {@link IpSecTransform#close()}),
398420fe002f1d35e870d519344a13de9f6501e4ddbBenedict Wong     * prior to the socket being closed, the standard [FIN - FIN/ACK - ACK], or the reset [RST]
399420fe002f1d35e870d519344a13de9f6501e4ddbBenedict Wong     * packets are dropped due to the lack of a valid Transform. Similarly, if a socket without the
400420fe002f1d35e870d519344a13de9f6501e4ddbBenedict Wong     * SO_LINGER option set is closed, the delayed/batched FIN packets may be dropped.
401420fe002f1d35e870d519344a13de9f6501e4ddbBenedict Wong     *
4025fb929032de14ca78163e1d0c42c34f6fb287da4Jonathan Basseri     * <h4>Rekey Procedure</h4>
4035fb929032de14ca78163e1d0c42c34f6fb287da4Jonathan Basseri     *
4047b7bea048511a54a628a8c340a2890dc50e7b451Nathan Harold     * <p>When applying a new tranform to a socket in the outbound direction, the previous transform
4057b7bea048511a54a628a8c340a2890dc50e7b451Nathan Harold     * will be removed and the new transform will take effect immediately, sending all traffic on
4067b7bea048511a54a628a8c340a2890dc50e7b451Nathan Harold     * the new transform; however, when applying a transform in the inbound direction, traffic
4077b7bea048511a54a628a8c340a2890dc50e7b451Nathan Harold     * on the old transform will continue to be decrypted and delivered until that transform is
4087b7bea048511a54a628a8c340a2890dc50e7b451Nathan Harold     * deallocated by calling {@link IpSecTransform#close()}. This overlap allows lossless rekey
4097b7bea048511a54a628a8c340a2890dc50e7b451Nathan Harold     * procedures where both transforms are valid until both endpoints are using the new transform
4107b7bea048511a54a628a8c340a2890dc50e7b451Nathan Harold     * and all in-flight packets have been received.
411b64993559b049327365bb63e81e8046a892a1033Nathan Harold     *
412b64993559b049327365bb63e81e8046a892a1033Nathan Harold     * @param socket a socket file descriptor
4137b7bea048511a54a628a8c340a2890dc50e7b451Nathan Harold     * @param direction the direction in which the transform should be applied
414c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri     * @param transform a transport mode {@code IpSecTransform}
415c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri     * @throws IOException indicating that the transform could not be applied
416b64993559b049327365bb63e81e8046a892a1033Nathan Harold     */
4175cd64cc8012243c656875be6b84456caeabd60f5Nathan Harold    public void applyTransportModeTransform(@NonNull FileDescriptor socket,
4185cd64cc8012243c656875be6b84456caeabd60f5Nathan Harold            @PolicyDirection int direction, @NonNull IpSecTransform transform) throws IOException {
4198dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold        // We dup() the FileDescriptor here because if we don't, then the ParcelFileDescriptor()
420b548d251b7995a5b76e495978b61ad6c3c4183d1Nathan Harold        // constructor takes control and closes the user's FD when we exit the method.
4218dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold        try (ParcelFileDescriptor pfd = ParcelFileDescriptor.dup(socket)) {
422a25233123b2d29fde83dd686f6313f0a232c5b2aNathan Harold            mService.applyTransportModeTransform(pfd, direction, transform.getResourceId());
4238dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold        } catch (RemoteException e) {
4248dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold            throw e.rethrowFromSystemServer();
4258dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold        }
426b64993559b049327365bb63e81e8046a892a1033Nathan Harold    }
427b64993559b049327365bb63e81e8046a892a1033Nathan Harold
428b64993559b049327365bb63e81e8046a892a1033Nathan Harold    /**
429c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri     * Remove an IPsec transform from a stream socket.
430c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri     *
431f73d252c8f51936eec49313f4cc26f1da7727b6cNathan Harold     * <p>Once removed, traffic on the socket will not be encrypted. Removing transforms from a
432f73d252c8f51936eec49313f4cc26f1da7727b6cNathan Harold     * socket allows the socket to be reused for communication in the clear.
433c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri     *
434c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri     * <p>If an {@code IpSecTransform} object applied to this socket was deallocated by calling
435c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri     * {@link IpSecTransform#close()}, then communication on the socket will fail until this method
436c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri     * is called.
437330e1089da80cddcd68758512370d217b19f8890Nathan Harold     *
438c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri     * @param socket a socket that previously had a transform applied to it
439c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri     * @throws IOException indicating that the transform could not be removed from the socket
440330e1089da80cddcd68758512370d217b19f8890Nathan Harold     */
4415cd64cc8012243c656875be6b84456caeabd60f5Nathan Harold    public void removeTransportModeTransforms(@NonNull Socket socket) throws IOException {
442f73d252c8f51936eec49313f4cc26f1da7727b6cNathan Harold        removeTransportModeTransforms(socket.getFileDescriptor$());
443330e1089da80cddcd68758512370d217b19f8890Nathan Harold    }
444330e1089da80cddcd68758512370d217b19f8890Nathan Harold
445330e1089da80cddcd68758512370d217b19f8890Nathan Harold    /**
446c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri     * Remove an IPsec transform from a datagram socket.
447330e1089da80cddcd68758512370d217b19f8890Nathan Harold     *
448f73d252c8f51936eec49313f4cc26f1da7727b6cNathan Harold     * <p>Once removed, traffic on the socket will not be encrypted. Removing transforms from a
449f73d252c8f51936eec49313f4cc26f1da7727b6cNathan Harold     * socket allows the socket to be reused for communication in the clear.
450c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri     *
451c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri     * <p>If an {@code IpSecTransform} object applied to this socket was deallocated by calling
452c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri     * {@link IpSecTransform#close()}, then communication on the socket will fail until this method
453c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri     * is called.
454c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri     *
455c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri     * @param socket a socket that previously had a transform applied to it
456c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri     * @throws IOException indicating that the transform could not be removed from the socket
457330e1089da80cddcd68758512370d217b19f8890Nathan Harold     */
4585cd64cc8012243c656875be6b84456caeabd60f5Nathan Harold    public void removeTransportModeTransforms(@NonNull DatagramSocket socket) throws IOException {
459f73d252c8f51936eec49313f4cc26f1da7727b6cNathan Harold        removeTransportModeTransforms(socket.getFileDescriptor$());
460330e1089da80cddcd68758512370d217b19f8890Nathan Harold    }
461330e1089da80cddcd68758512370d217b19f8890Nathan Harold
462b64993559b049327365bb63e81e8046a892a1033Nathan Harold    /**
463c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri     * Remove an IPsec transform from a socket.
464c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri     *
465f73d252c8f51936eec49313f4cc26f1da7727b6cNathan Harold     * <p>Once removed, traffic on the socket will not be encrypted. Removing transforms from a
466f73d252c8f51936eec49313f4cc26f1da7727b6cNathan Harold     * socket allows the socket to be reused for communication in the clear.
467b64993559b049327365bb63e81e8046a892a1033Nathan Harold     *
468c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri     * <p>If an {@code IpSecTransform} object applied to this socket was deallocated by calling
469c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri     * {@link IpSecTransform#close()}, then communication on the socket will fail until this method
470c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri     * is called.
471c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri     *
472c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri     * @param socket a socket that previously had a transform applied to it
473c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri     * @throws IOException indicating that the transform could not be removed from the socket
474b64993559b049327365bb63e81e8046a892a1033Nathan Harold     */
4755cd64cc8012243c656875be6b84456caeabd60f5Nathan Harold    public void removeTransportModeTransforms(@NonNull FileDescriptor socket) throws IOException {
4768dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold        try (ParcelFileDescriptor pfd = ParcelFileDescriptor.dup(socket)) {
477f73d252c8f51936eec49313f4cc26f1da7727b6cNathan Harold            mService.removeTransportModeTransforms(pfd);
47893962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold        } catch (RemoteException e) {
47993962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold            throw e.rethrowFromSystemServer();
48093962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold        }
48193962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold    }
482330e1089da80cddcd68758512370d217b19f8890Nathan Harold
483330e1089da80cddcd68758512370d217b19f8890Nathan Harold    /**
484330e1089da80cddcd68758512370d217b19f8890Nathan Harold     * Remove a Tunnel Mode IPsec Transform from a {@link Network}. This must be used as part of
485330e1089da80cddcd68758512370d217b19f8890Nathan Harold     * cleanup if a tunneled Network experiences a change in default route. The Network will drop
486330e1089da80cddcd68758512370d217b19f8890Nathan Harold     * all traffic that cannot be routed to the Tunnel's outbound interface. If that interface is
487330e1089da80cddcd68758512370d217b19f8890Nathan Harold     * lost, all traffic will drop.
488330e1089da80cddcd68758512370d217b19f8890Nathan Harold     *
4895fb929032de14ca78163e1d0c42c34f6fb287da4Jonathan Basseri     * <p>TODO: Update javadoc for tunnel mode APIs at the same time the APIs are re-worked.
4905fb929032de14ca78163e1d0c42c34f6fb287da4Jonathan Basseri     *
491330e1089da80cddcd68758512370d217b19f8890Nathan Harold     * @param net a network that currently has transform applied to it.
492330e1089da80cddcd68758512370d217b19f8890Nathan Harold     * @param transform a Tunnel Mode IPsec Transform that has been previously applied to the given
493330e1089da80cddcd68758512370d217b19f8890Nathan Harold     *     network
494330e1089da80cddcd68758512370d217b19f8890Nathan Harold     * @hide
495330e1089da80cddcd68758512370d217b19f8890Nathan Harold     */
496330e1089da80cddcd68758512370d217b19f8890Nathan Harold    public void removeTunnelModeTransform(Network net, IpSecTransform transform) {}
497330e1089da80cddcd68758512370d217b19f8890Nathan Harold
498330e1089da80cddcd68758512370d217b19f8890Nathan Harold    /**
499c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri     * This class provides access to a UDP encapsulation Socket.
500330e1089da80cddcd68758512370d217b19f8890Nathan Harold     *
501c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri     * <p>{@code UdpEncapsulationSocket} wraps a system-provided datagram socket intended for IKEv2
502c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri     * signalling and UDP encapsulated IPsec traffic. Instances can be obtained by calling {@link
503c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri     * IpSecManager#openUdpEncapsulationSocket}. The provided socket cannot be re-bound by the
504c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri     * caller. The caller should not close the {@code FileDescriptor} returned by {@link
5056ea93c4bcaf5c2c8489695308e77b659b70b64d4Benedict Wong     * #getFileDescriptor}, but should use {@link #close} instead.
506c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri     *
507c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri     * <p>Allowing the user to close or unbind a UDP encapsulation socket could impact the traffic
508c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri     * of the next user who binds to that port. To prevent this scenario, these sockets are held
509c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri     * open by the system so that they may only be closed by calling {@link #close} or when the user
510c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri     * process exits.
511330e1089da80cddcd68758512370d217b19f8890Nathan Harold     */
512330e1089da80cddcd68758512370d217b19f8890Nathan Harold    public static final class UdpEncapsulationSocket implements AutoCloseable {
5138dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold        private final ParcelFileDescriptor mPfd;
5141afbef40c68373f3871eed087c546cfe1911ee36Nathan Harold        private final IIpSecService mService;
5156119d8d1d0d89b0d4c4ac822e9e93bb47f1ebd9aNathan Harold        private int mResourceId = INVALID_RESOURCE_ID;
5168dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold        private final int mPort;
517330e1089da80cddcd68758512370d217b19f8890Nathan Harold        private final CloseGuard mCloseGuard = CloseGuard.get();
518330e1089da80cddcd68758512370d217b19f8890Nathan Harold
51993962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold        private UdpEncapsulationSocket(@NonNull IIpSecService service, int port)
5208dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold                throws ResourceUnavailableException, IOException {
5211afbef40c68373f3871eed087c546cfe1911ee36Nathan Harold            mService = service;
5228dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold            try {
5238dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold                IpSecUdpEncapResponse result =
5248dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold                        mService.openUdpEncapsulationSocket(port, new Binder());
5258dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold                switch (result.status) {
5268dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold                    case Status.OK:
5278dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold                        break;
5288dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold                    case Status.RESOURCE_UNAVAILABLE:
5298dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold                        throw new ResourceUnavailableException(
5308dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold                                "No more Sockets may be allocated by this requester.");
5318dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold                    default:
5328dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold                        throw new RuntimeException(
5338dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold                                "Unknown status returned by IpSecService: " + result.status);
5348dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold                }
5358dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold                mResourceId = result.resourceId;
5368dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold                mPort = result.port;
5378dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold                mPfd = result.fileDescriptor;
5388dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold            } catch (RemoteException e) {
5398dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold                throw e.rethrowFromSystemServer();
5408dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold            }
541330e1089da80cddcd68758512370d217b19f8890Nathan Harold            mCloseGuard.open("constructor");
542330e1089da80cddcd68758512370d217b19f8890Nathan Harold        }
543330e1089da80cddcd68758512370d217b19f8890Nathan Harold
5446ea93c4bcaf5c2c8489695308e77b659b70b64d4Benedict Wong        /** Get the encapsulation socket's file descriptor. */
5456ea93c4bcaf5c2c8489695308e77b659b70b64d4Benedict Wong        public FileDescriptor getFileDescriptor() {
5468dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold            if (mPfd == null) {
5478dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold                return null;
5488dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold            }
5498dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold            return mPfd.getFileDescriptor();
550330e1089da80cddcd68758512370d217b19f8890Nathan Harold        }
551330e1089da80cddcd68758512370d217b19f8890Nathan Harold
552c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri        /** Get the bound port of the wrapped socket. */
553330e1089da80cddcd68758512370d217b19f8890Nathan Harold        public int getPort() {
5548dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold            return mPort;
555330e1089da80cddcd68758512370d217b19f8890Nathan Harold        }
556330e1089da80cddcd68758512370d217b19f8890Nathan Harold
557330e1089da80cddcd68758512370d217b19f8890Nathan Harold        /**
558c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri         * Close this socket.
559330e1089da80cddcd68758512370d217b19f8890Nathan Harold         *
560c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri         * <p>This closes the wrapped socket. Open encapsulation sockets count against a user's
561c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri         * resource limits, and forgetting to close them eventually will result in {@link
562c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri         * ResourceUnavailableException} being thrown.
563330e1089da80cddcd68758512370d217b19f8890Nathan Harold         */
564c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri        @Override
5650bfb2075320a9f648fc2b3fcdfc58f425c9a685aNathan Harold        public void close() throws IOException {
5668dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold            try {
5678dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold                mService.closeUdpEncapsulationSocket(mResourceId);
5686119d8d1d0d89b0d4c4ac822e9e93bb47f1ebd9aNathan Harold                mResourceId = INVALID_RESOURCE_ID;
5698dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold            } catch (RemoteException e) {
5708dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold                throw e.rethrowFromSystemServer();
5718dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold            }
5728dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold
5738dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold            try {
5748dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold                mPfd.close();
5758dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold            } catch (IOException e) {
5768dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold                Log.e(TAG, "Failed to close UDP Encapsulation Socket with Port= " + mPort);
5778dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold                throw e;
5788dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold            }
579330e1089da80cddcd68758512370d217b19f8890Nathan Harold            mCloseGuard.close();
580330e1089da80cddcd68758512370d217b19f8890Nathan Harold        }
581330e1089da80cddcd68758512370d217b19f8890Nathan Harold
582c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri        /** Check that the socket was closed properly. */
583330e1089da80cddcd68758512370d217b19f8890Nathan Harold        @Override
584330e1089da80cddcd68758512370d217b19f8890Nathan Harold        protected void finalize() throws Throwable {
585330e1089da80cddcd68758512370d217b19f8890Nathan Harold            if (mCloseGuard != null) {
586330e1089da80cddcd68758512370d217b19f8890Nathan Harold                mCloseGuard.warnIfOpen();
587330e1089da80cddcd68758512370d217b19f8890Nathan Harold            }
588330e1089da80cddcd68758512370d217b19f8890Nathan Harold            close();
589330e1089da80cddcd68758512370d217b19f8890Nathan Harold        }
5908dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold
5918dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold        /** @hide */
592a10003d5de52339f4d30fedd7294941378e5f13cNathan Harold        @VisibleForTesting
593a10003d5de52339f4d30fedd7294941378e5f13cNathan Harold        public int getResourceId() {
5948dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold            return mResourceId;
5958dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold        }
596330e1089da80cddcd68758512370d217b19f8890Nathan Harold    };
597330e1089da80cddcd68758512370d217b19f8890Nathan Harold
598330e1089da80cddcd68758512370d217b19f8890Nathan Harold    /**
599c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri     * Open a socket for UDP encapsulation and bind to the given port.
600330e1089da80cddcd68758512370d217b19f8890Nathan Harold     *
601c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri     * <p>See {@link UdpEncapsulationSocket} for the proper way to close the returned socket.
602330e1089da80cddcd68758512370d217b19f8890Nathan Harold     *
603c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri     * @param port a local UDP port
604c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri     * @return a socket that is bound to the given port
605c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri     * @throws IOException indicating that the socket could not be opened or bound
606c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri     * @throws ResourceUnavailableException indicating that too many encapsulation sockets are open
607330e1089da80cddcd68758512370d217b19f8890Nathan Harold     */
608330e1089da80cddcd68758512370d217b19f8890Nathan Harold    // Returning a socket in this fashion that has been created and bound by the system
609330e1089da80cddcd68758512370d217b19f8890Nathan Harold    // is the only safe way to ensure that a socket is both accessible to the user and
610330e1089da80cddcd68758512370d217b19f8890Nathan Harold    // safely usable for Encapsulation without allowing a user to possibly unbind from/close
611330e1089da80cddcd68758512370d217b19f8890Nathan Harold    // the port, which could potentially impact the traffic of the next user who binds to that
612330e1089da80cddcd68758512370d217b19f8890Nathan Harold    // socket.
6135cd64cc8012243c656875be6b84456caeabd60f5Nathan Harold    @NonNull
614330e1089da80cddcd68758512370d217b19f8890Nathan Harold    public UdpEncapsulationSocket openUdpEncapsulationSocket(int port)
615330e1089da80cddcd68758512370d217b19f8890Nathan Harold            throws IOException, ResourceUnavailableException {
6168dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold        /*
6178dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold         * Most range checking is done in the service, but this version of the constructor expects
6188dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold         * a valid port number, and zero cannot be checked after being passed to the service.
6198dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold         */
6208dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold        if (port == 0) {
6218dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold            throw new IllegalArgumentException("Specified port must be a valid port number!");
6228dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold        }
6231afbef40c68373f3871eed087c546cfe1911ee36Nathan Harold        return new UdpEncapsulationSocket(mService, port);
624330e1089da80cddcd68758512370d217b19f8890Nathan Harold    }
625330e1089da80cddcd68758512370d217b19f8890Nathan Harold
626330e1089da80cddcd68758512370d217b19f8890Nathan Harold    /**
627c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri     * Open a socket for UDP encapsulation.
628330e1089da80cddcd68758512370d217b19f8890Nathan Harold     *
629c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri     * <p>See {@link UdpEncapsulationSocket} for the proper way to close the returned socket.
630330e1089da80cddcd68758512370d217b19f8890Nathan Harold     *
631c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri     * <p>The local port of the returned socket can be obtained by calling {@link
632c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri     * UdpEncapsulationSocket#getPort()}.
633330e1089da80cddcd68758512370d217b19f8890Nathan Harold     *
634c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri     * @return a socket that is bound to a local port
635c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri     * @throws IOException indicating that the socket could not be opened or bound
636c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri     * @throws ResourceUnavailableException indicating that too many encapsulation sockets are open
637330e1089da80cddcd68758512370d217b19f8890Nathan Harold     */
638330e1089da80cddcd68758512370d217b19f8890Nathan Harold    // Returning a socket in this fashion that has been created and bound by the system
639330e1089da80cddcd68758512370d217b19f8890Nathan Harold    // is the only safe way to ensure that a socket is both accessible to the user and
640330e1089da80cddcd68758512370d217b19f8890Nathan Harold    // safely usable for Encapsulation without allowing a user to possibly unbind from/close
641330e1089da80cddcd68758512370d217b19f8890Nathan Harold    // the port, which could potentially impact the traffic of the next user who binds to that
642330e1089da80cddcd68758512370d217b19f8890Nathan Harold    // socket.
6435cd64cc8012243c656875be6b84456caeabd60f5Nathan Harold    @NonNull
644330e1089da80cddcd68758512370d217b19f8890Nathan Harold    public UdpEncapsulationSocket openUdpEncapsulationSocket()
645330e1089da80cddcd68758512370d217b19f8890Nathan Harold            throws IOException, ResourceUnavailableException {
6468dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold        return new UdpEncapsulationSocket(mService, 0);
647330e1089da80cddcd68758512370d217b19f8890Nathan Harold    }
648330e1089da80cddcd68758512370d217b19f8890Nathan Harold
649330e1089da80cddcd68758512370d217b19f8890Nathan Harold    /**
650c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold     * This class represents an IpSecTunnelInterface
651c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold     *
652c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold     * <p>IpSecTunnelInterface objects track tunnel interfaces that serve as
653c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold     * local endpoints for IPsec tunnels.
654c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold     *
655c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold     * <p>Creating an IpSecTunnelInterface creates a device to which IpSecTransforms may be
656c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold     * applied to provide IPsec security to packets sent through the tunnel. While a tunnel
657c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold     * cannot be used in standalone mode within Android, the higher layers may use the tunnel
658c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold     * to create Network objects which are accessible to the Android system.
659c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold     * @hide
660c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold     */
661c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold    @SystemApi
662c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold    public static final class IpSecTunnelInterface implements AutoCloseable {
663c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold        private final IIpSecService mService;
664c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold        private final InetAddress mRemoteAddress;
665c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold        private final InetAddress mLocalAddress;
666c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold        private final Network mUnderlyingNetwork;
667c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold        private final CloseGuard mCloseGuard = CloseGuard.get();
668c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold        private String mInterfaceName;
669c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold        private int mResourceId = INVALID_RESOURCE_ID;
670c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold
671c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold        /** Get the underlying SPI held by this object. */
6725cd64cc8012243c656875be6b84456caeabd60f5Nathan Harold        @NonNull
673c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold        public String getInterfaceName() {
674c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold            return mInterfaceName;
675c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold        }
676c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold
677c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold        /**
678c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold         * Add an address to the IpSecTunnelInterface
679c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold         *
680c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold         * <p>Add an address which may be used as the local inner address for
681c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold         * tunneled traffic.
682c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold         *
683c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold         * @param address the local address for traffic inside the tunnel
684c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold         * @hide
685c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold         */
686c8f63060adc880eb6cfdee1e08cafcf2f379096aNathan Harold        @SystemApi
687159788455c79fa47847d0c40fcee7aceff2551aeNathan Harold        @RequiresPermission(android.Manifest.permission.MANAGE_IPSEC_TUNNELS)
6885cd64cc8012243c656875be6b84456caeabd60f5Nathan Harold        public void addAddress(@NonNull LinkAddress address) throws IOException {
689da4b0c65a5cbebf6c5e66b869b75dd3a6625cd2eBenedict Wong            try {
690da4b0c65a5cbebf6c5e66b869b75dd3a6625cd2eBenedict Wong                mService.addAddressToTunnelInterface(mResourceId, address);
691da4b0c65a5cbebf6c5e66b869b75dd3a6625cd2eBenedict Wong            } catch (RemoteException e) {
692da4b0c65a5cbebf6c5e66b869b75dd3a6625cd2eBenedict Wong                throw e.rethrowFromSystemServer();
693da4b0c65a5cbebf6c5e66b869b75dd3a6625cd2eBenedict Wong            }
694c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold        }
695c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold
696c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold        /**
697c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold         * Remove an address from the IpSecTunnelInterface
698c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold         *
699c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold         * <p>Remove an address which was previously added to the IpSecTunnelInterface
700c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold         *
701c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold         * @param address to be removed
702c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold         * @hide
703c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold         */
704c8f63060adc880eb6cfdee1e08cafcf2f379096aNathan Harold        @SystemApi
705159788455c79fa47847d0c40fcee7aceff2551aeNathan Harold        @RequiresPermission(android.Manifest.permission.MANAGE_IPSEC_TUNNELS)
7065cd64cc8012243c656875be6b84456caeabd60f5Nathan Harold        public void removeAddress(@NonNull LinkAddress address) throws IOException {
707da4b0c65a5cbebf6c5e66b869b75dd3a6625cd2eBenedict Wong            try {
708da4b0c65a5cbebf6c5e66b869b75dd3a6625cd2eBenedict Wong                mService.removeAddressFromTunnelInterface(mResourceId, address);
709da4b0c65a5cbebf6c5e66b869b75dd3a6625cd2eBenedict Wong            } catch (RemoteException e) {
710da4b0c65a5cbebf6c5e66b869b75dd3a6625cd2eBenedict Wong                throw e.rethrowFromSystemServer();
711da4b0c65a5cbebf6c5e66b869b75dd3a6625cd2eBenedict Wong            }
712c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold        }
713c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold
714c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold        private IpSecTunnelInterface(@NonNull IIpSecService service,
715c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold                @NonNull InetAddress localAddress, @NonNull InetAddress remoteAddress,
716c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold                @NonNull Network underlyingNetwork)
717c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold                throws ResourceUnavailableException, IOException {
718c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold            mService = service;
719c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold            mLocalAddress = localAddress;
720c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold            mRemoteAddress = remoteAddress;
721c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold            mUnderlyingNetwork = underlyingNetwork;
7228149f6eb6c0280078dc41d72027d1241e875ea02Benedict Wong
7238149f6eb6c0280078dc41d72027d1241e875ea02Benedict Wong            try {
7248149f6eb6c0280078dc41d72027d1241e875ea02Benedict Wong                IpSecTunnelInterfaceResponse result =
7258149f6eb6c0280078dc41d72027d1241e875ea02Benedict Wong                        mService.createTunnelInterface(
7268149f6eb6c0280078dc41d72027d1241e875ea02Benedict Wong                                localAddress.getHostAddress(),
7278149f6eb6c0280078dc41d72027d1241e875ea02Benedict Wong                                remoteAddress.getHostAddress(),
7288149f6eb6c0280078dc41d72027d1241e875ea02Benedict Wong                                underlyingNetwork,
7298149f6eb6c0280078dc41d72027d1241e875ea02Benedict Wong                                new Binder());
7308149f6eb6c0280078dc41d72027d1241e875ea02Benedict Wong                switch (result.status) {
7318149f6eb6c0280078dc41d72027d1241e875ea02Benedict Wong                    case Status.OK:
7328149f6eb6c0280078dc41d72027d1241e875ea02Benedict Wong                        break;
7338149f6eb6c0280078dc41d72027d1241e875ea02Benedict Wong                    case Status.RESOURCE_UNAVAILABLE:
7348149f6eb6c0280078dc41d72027d1241e875ea02Benedict Wong                        throw new ResourceUnavailableException(
7358149f6eb6c0280078dc41d72027d1241e875ea02Benedict Wong                                "No more tunnel interfaces may be allocated by this requester.");
7368149f6eb6c0280078dc41d72027d1241e875ea02Benedict Wong                    default:
7378149f6eb6c0280078dc41d72027d1241e875ea02Benedict Wong                        throw new RuntimeException(
7388149f6eb6c0280078dc41d72027d1241e875ea02Benedict Wong                                "Unknown status returned by IpSecService: " + result.status);
7398149f6eb6c0280078dc41d72027d1241e875ea02Benedict Wong                }
7408149f6eb6c0280078dc41d72027d1241e875ea02Benedict Wong                mResourceId = result.resourceId;
7418149f6eb6c0280078dc41d72027d1241e875ea02Benedict Wong                mInterfaceName = result.interfaceName;
7428149f6eb6c0280078dc41d72027d1241e875ea02Benedict Wong            } catch (RemoteException e) {
7438149f6eb6c0280078dc41d72027d1241e875ea02Benedict Wong                throw e.rethrowFromSystemServer();
7448149f6eb6c0280078dc41d72027d1241e875ea02Benedict Wong            }
7458149f6eb6c0280078dc41d72027d1241e875ea02Benedict Wong            mCloseGuard.open("constructor");
746c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold        }
747c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold
748c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold        /**
749c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold         * Delete an IpSecTunnelInterface
750c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold         *
751c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold         * <p>Calling close will deallocate the IpSecTunnelInterface and all of its system
752c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold         * resources. Any packets bound for this interface either inbound or outbound will
753c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold         * all be lost.
754c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold         */
755c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold        @Override
756c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold        public void close() {
7578149f6eb6c0280078dc41d72027d1241e875ea02Benedict Wong            try {
7588149f6eb6c0280078dc41d72027d1241e875ea02Benedict Wong                mService.deleteTunnelInterface(mResourceId);
7598149f6eb6c0280078dc41d72027d1241e875ea02Benedict Wong                mResourceId = INVALID_RESOURCE_ID;
7608149f6eb6c0280078dc41d72027d1241e875ea02Benedict Wong            } catch (RemoteException e) {
7618149f6eb6c0280078dc41d72027d1241e875ea02Benedict Wong                throw e.rethrowFromSystemServer();
7628149f6eb6c0280078dc41d72027d1241e875ea02Benedict Wong            }
763c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold            mCloseGuard.close();
764c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold        }
765c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold
766c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold        /** Check that the Interface was closed properly. */
767c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold        @Override
768c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold        protected void finalize() throws Throwable {
769c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold            if (mCloseGuard != null) {
770c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold                mCloseGuard.warnIfOpen();
771c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold            }
772c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold            close();
773c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold        }
7748149f6eb6c0280078dc41d72027d1241e875ea02Benedict Wong
7758149f6eb6c0280078dc41d72027d1241e875ea02Benedict Wong        /** @hide */
7768149f6eb6c0280078dc41d72027d1241e875ea02Benedict Wong        @VisibleForTesting
7778149f6eb6c0280078dc41d72027d1241e875ea02Benedict Wong        public int getResourceId() {
7788149f6eb6c0280078dc41d72027d1241e875ea02Benedict Wong            return mResourceId;
7798149f6eb6c0280078dc41d72027d1241e875ea02Benedict Wong        }
780c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold    }
781c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold
782c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold    /**
783c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold     * Create a new IpSecTunnelInterface as a local endpoint for tunneled IPsec traffic.
784c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold     *
7858149f6eb6c0280078dc41d72027d1241e875ea02Benedict Wong     * <p>An application that creates tunnels is responsible for cleaning up the tunnel when the
7868149f6eb6c0280078dc41d72027d1241e875ea02Benedict Wong     * underlying network goes away, and the onLost() callback is received.
7878149f6eb6c0280078dc41d72027d1241e875ea02Benedict Wong     *
788c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold     * @param localAddress The local addres of the tunnel
789c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold     * @param remoteAddress The local addres of the tunnel
790c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold     * @param underlyingNetwork the {@link Network} that will carry traffic for this tunnel.
791c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold     *        This network should almost certainly be a network such as WiFi with an L2 address.
792c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold     * @return a new {@link IpSecManager#IpSecTunnelInterface} with the specified properties
793c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold     * @throws IOException indicating that the socket could not be opened or bound
794c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold     * @throws ResourceUnavailableException indicating that too many encapsulation sockets are open
795c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold     * @hide
796c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold     */
797c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold    @SystemApi
7985cd64cc8012243c656875be6b84456caeabd60f5Nathan Harold    @NonNull
799159788455c79fa47847d0c40fcee7aceff2551aeNathan Harold    @RequiresPermission(android.Manifest.permission.MANAGE_IPSEC_TUNNELS)
800c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold    public IpSecTunnelInterface createIpSecTunnelInterface(@NonNull InetAddress localAddress,
801c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold            @NonNull InetAddress remoteAddress, @NonNull Network underlyingNetwork)
802c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold            throws ResourceUnavailableException, IOException {
803c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold        return new IpSecTunnelInterface(mService, localAddress, remoteAddress, underlyingNetwork);
804c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold    }
805c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold
806c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold    /**
8077b7bea048511a54a628a8c340a2890dc50e7b451Nathan Harold     * Apply an active Tunnel Mode IPsec Transform to a {@link IpSecTunnelInterface}, which will
8087b7bea048511a54a628a8c340a2890dc50e7b451Nathan Harold     * tunnel all traffic for the given direction through the underlying network's interface with
8097b7bea048511a54a628a8c340a2890dc50e7b451Nathan Harold     * IPsec (applies an outer IP header and IPsec Header to all traffic, and expects an additional
8107b7bea048511a54a628a8c340a2890dc50e7b451Nathan Harold     * IP header and IPsec Header on all inbound traffic).
8117b7bea048511a54a628a8c340a2890dc50e7b451Nathan Harold     * <p>Applications should probably not use this API directly.
8127b7bea048511a54a628a8c340a2890dc50e7b451Nathan Harold     *
813c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold     *
814c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold     * @param tunnel The {@link IpSecManager#IpSecTunnelInterface} that will use the supplied
815c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold     *        transform.
816c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold     * @param direction the direction, {@link DIRECTION_OUT} or {@link #DIRECTION_IN} in which
817c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold     *        the transform will be used.
818c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold     * @param transform an {@link IpSecTransform} created in tunnel mode
819c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold     * @throws IOException indicating that the transform could not be applied due to a lower
820c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold     *         layer failure.
821c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold     * @hide
822c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold     */
823c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold    @SystemApi
824159788455c79fa47847d0c40fcee7aceff2551aeNathan Harold    @RequiresPermission(android.Manifest.permission.MANAGE_IPSEC_TUNNELS)
8255cd64cc8012243c656875be6b84456caeabd60f5Nathan Harold    public void applyTunnelModeTransform(@NonNull IpSecTunnelInterface tunnel,
8265cd64cc8012243c656875be6b84456caeabd60f5Nathan Harold            @PolicyDirection int direction, @NonNull IpSecTransform transform) throws IOException {
8278149f6eb6c0280078dc41d72027d1241e875ea02Benedict Wong        try {
8288149f6eb6c0280078dc41d72027d1241e875ea02Benedict Wong            mService.applyTunnelModeTransform(
8298149f6eb6c0280078dc41d72027d1241e875ea02Benedict Wong                    tunnel.getResourceId(), direction, transform.getResourceId());
8308149f6eb6c0280078dc41d72027d1241e875ea02Benedict Wong        } catch (RemoteException e) {
8318149f6eb6c0280078dc41d72027d1241e875ea02Benedict Wong            throw e.rethrowFromSystemServer();
8328149f6eb6c0280078dc41d72027d1241e875ea02Benedict Wong        }
833c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold    }
8347b7bea048511a54a628a8c340a2890dc50e7b451Nathan Harold
835c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold    /**
836c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri     * Construct an instance of IpSecManager within an application context.
837330e1089da80cddcd68758512370d217b19f8890Nathan Harold     *
838330e1089da80cddcd68758512370d217b19f8890Nathan Harold     * @param context the application context for this manager
839330e1089da80cddcd68758512370d217b19f8890Nathan Harold     * @hide
840330e1089da80cddcd68758512370d217b19f8890Nathan Harold     */
8411afbef40c68373f3871eed087c546cfe1911ee36Nathan Harold    public IpSecManager(IIpSecService service) {
842330e1089da80cddcd68758512370d217b19f8890Nathan Harold        mService = checkNotNull(service, "missing service");
843330e1089da80cddcd68758512370d217b19f8890Nathan Harold    }
844330e1089da80cddcd68758512370d217b19f8890Nathan Harold}
845