• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2019 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  */
16 
17 package android.net.ipsec.ike;
18 
19 import static android.system.OsConstants.AF_INET;
20 import static android.system.OsConstants.AF_INET6;
21 
22 import static com.android.internal.net.ipsec.ike.utils.IkeCertUtils.certificateFromByteArray;
23 import static com.android.internal.net.ipsec.ike.utils.IkeCertUtils.privateKeyFromByteArray;
24 
25 import android.annotation.IntDef;
26 import android.annotation.IntRange;
27 import android.annotation.NonNull;
28 import android.annotation.Nullable;
29 import android.annotation.SuppressLint;
30 import android.annotation.SystemApi;
31 import android.content.Context;
32 import android.net.ConnectivityManager;
33 import android.net.Network;
34 import android.net.eap.EapSessionConfig;
35 import android.net.ipsec.ike.ike3gpp.Ike3gppExtension;
36 import android.os.PersistableBundle;
37 
38 import com.android.internal.annotations.VisibleForTesting;
39 import com.android.internal.net.ipsec.ike.message.IkeConfigPayload.ConfigAttribute;
40 import com.android.internal.net.ipsec.ike.message.IkeConfigPayload.ConfigAttributeIpv4Pcscf;
41 import com.android.internal.net.ipsec.ike.message.IkeConfigPayload.ConfigAttributeIpv6Pcscf;
42 import com.android.internal.net.ipsec.ike.message.IkeConfigPayload.IkeConfigAttribute;
43 import com.android.internal.net.ipsec.ike.message.IkePayload;
44 import com.android.modules.utils.build.SdkLevel;
45 import com.android.server.vcn.util.PersistableBundleUtils;
46 
47 import java.lang.annotation.Retention;
48 import java.lang.annotation.RetentionPolicy;
49 import java.net.Inet4Address;
50 import java.net.Inet6Address;
51 import java.net.InetAddress;
52 import java.security.PrivateKey;
53 import java.security.cert.CertificateEncodingException;
54 import java.security.cert.TrustAnchor;
55 import java.security.cert.X509Certificate;
56 import java.security.interfaces.RSAKey;
57 import java.util.ArrayList;
58 import java.util.Arrays;
59 import java.util.Collections;
60 import java.util.LinkedList;
61 import java.util.List;
62 import java.util.Objects;
63 import java.util.concurrent.TimeUnit;
64 
65 /**
66  * IkeSessionParams contains all user provided configurations for negotiating an {@link IkeSession}.
67  *
68  * <p>Note that all negotiated configurations will be reused during rekey including SA Proposal and
69  * lifetime.
70  */
71 public final class IkeSessionParams {
72     /** @hide */
73     @Retention(RetentionPolicy.SOURCE)
74     @IntDef({IKE_AUTH_METHOD_PSK, IKE_AUTH_METHOD_PUB_KEY_SIGNATURE, IKE_AUTH_METHOD_EAP})
75     public @interface IkeAuthMethod {}
76 
77     // Constants to describe user configured authentication methods.
78     /** @hide */
79     public static final int IKE_AUTH_METHOD_PSK = 1;
80     /** @hide */
81     public static final int IKE_AUTH_METHOD_PUB_KEY_SIGNATURE = 2;
82     /** @hide */
83     public static final int IKE_AUTH_METHOD_EAP = 3;
84 
85     /** @hide */
86     @Retention(RetentionPolicy.SOURCE)
87     @IntDef({AUTH_DIRECTION_LOCAL, AUTH_DIRECTION_REMOTE, AUTH_DIRECTION_BOTH})
88     public @interface AuthDirection {}
89 
90     // Constants to describe which side (local and/or remote) the authentication configuration will
91     // be used.
92     /** @hide */
93     public static final int AUTH_DIRECTION_LOCAL = 1;
94     /** @hide */
95     public static final int AUTH_DIRECTION_REMOTE = 2;
96     /** @hide */
97     public static final int AUTH_DIRECTION_BOTH = 3;
98 
99     /** @hide */
100     @Retention(RetentionPolicy.SOURCE)
101     @IntDef({
102         IKE_OPTION_ACCEPT_ANY_REMOTE_ID,
103         IKE_OPTION_EAP_ONLY_AUTH,
104         IKE_OPTION_MOBIKE,
105         IKE_OPTION_FORCE_PORT_4500,
106         IKE_OPTION_INITIAL_CONTACT,
107         IKE_OPTION_REKEY_MOBILITY,
108         IKE_OPTION_AUTOMATIC_ADDRESS_FAMILY_SELECTION,
109         IKE_OPTION_AUTOMATIC_NATT_KEEPALIVES,
110         IKE_OPTION_AUTOMATIC_KEEPALIVE_ON_OFF
111     })
112     public @interface IkeOption {}
113 
114     /**
115      * If set, the IKE library will accept any remote (server) identity, even if it does not match
116      * the configured remote identity
117      *
118      * <p>See {@link Builder#setRemoteIdentification(IkeIdentification)}
119      */
120     public static final int IKE_OPTION_ACCEPT_ANY_REMOTE_ID = 0;
121     /**
122      * If set, and EAP has been configured as the authentication method, the IKE library will
123      * request that the remote (also) use an EAP-only authentication flow.
124      *
125      * <p>@see {@link Builder#setAuthEap(X509Certificate, EapSessionConfig)}
126      */
127     public static final int IKE_OPTION_EAP_ONLY_AUTH = 1;
128 
129     /**
130      * If set, the IKE Session will attempt to handle IP address changes using RFC4555 MOBIKE.
131      *
132      * <p>Upon IP address changes (including Network changes), the IKE session will initiate an RFC
133      * 4555 MOBIKE procedure, migrating both this IKE Session and associated IPsec Transforms to the
134      * new local and remote address pair.
135      *
136      * <p>The IKE library will first attempt to enable MOBIKE to handle the changes of underlying
137      * network and addresses. For callers targeting SDK {@link android.os.Build.VERSION_CODES#S_V2}
138      * and earlier, this option will implicitly enable the support for rekey-based mobility, and
139      * thus if the server does not support MOBIKE, the IKE Session will try migration by rekeying
140      * all associated IPsec SAs. This rekey-based mobility feature is not best-practice and has
141      * technical issues; accordingly, it will no longer be enabled for callers targeting SDK {@link
142      * android.os.Build.VERSION_CODES#TIRAMISU} and above.
143      *
144      * <p>Checking whether or not MOBIKE is supported by both the IKE library and the server in an
145      * IKE Session is done via {@link IkeSessionConfiguration#isIkeExtensionEnabled(int)}.
146      *
147      * <p>It is recommended that IKE_OPTION_MOBIKE be enabled unless precluded for compatibility
148      * reasons.
149      *
150      * <p>If this option is set for an IKE Session, Transport-mode SAs will not be allowed in that
151      * Session.
152      *
153      * <p>Callers that need to perform migration of IPsec transforms and tunnels MUST implement
154      * migration specific methods in {@link IkeSessionCallback} and {@link ChildSessionCallback}.
155      */
156     public static final int IKE_OPTION_MOBIKE = 2;
157 
158     /**
159      * Configures the IKE session to always send to port 4500.
160      *
161      * <p>If set, the IKE Session will be initiated and maintained exclusively using
162      * destination port 4500, regardless of the presence of NAT. Otherwise, the IKE Session will
163      * be initiated on destination port 500; then, if either a NAT is detected or both MOBIKE
164      * and NAT-T are supported by the peer, it will proceed on port 4500.
165      */
166     public static final int IKE_OPTION_FORCE_PORT_4500 = 3;
167 
168     /**
169      * If set, the IKE library will send INITIAL_CONTACT notification to the peers.
170      *
171      * <p>If this option is set, the INITIAL_CONTACT notification payload is sent in IKE_AUTH. The
172      * client can use this option to assert to the peer that this IKE SA is the only IKE SA
173      * currently active between the authenticated identities.
174      *
175      * <p>@see "https://tools.ietf.org/html/rfc7296#section-2.4" RFC 7296, Internet Key Exchange
176      * Protocol Version 2 (IKEv2)
177      *
178      * <p>@see {@link Builder#addIkeOption(int)}
179      */
180     public static final int IKE_OPTION_INITIAL_CONTACT = 4;
181 
182     /**
183      * If set, the IKE Session will attempt to handle IP address changes by rekeying with new
184      * addresses.
185      *
186      * <p>Upon IP address changes (including Network changes), the IKE session will initiate a
187      * standard rekey Child procedure using the new local address to replace the existing associated
188      * IPsec transforms with new transforms tied to the new addresses. At the same time the IKE
189      * library will notify the remote of the address change and implicitly migrate itself to the new
190      * address.
191      *
192      * <p>This capability is NOT negotiated; it is the responsibility of the caller to ensure that
193      * the remote supports rekey-based mobility. Failure to do so may lead to increased disruption
194      * during mobility events.
195      *
196      * <p>This option may be set together with {@link #IKE_OPTION_MOBIKE} as a fallback. If both
197      * {@link #IKE_OPTION_MOBIKE} and {@link #IKE_OPTION_REKEY_MOBILITY} are set:
198      *
199      * <ul>
200      *   <li>If the server has indicated MOBIKE support, MOBIKE will be used for mobility
201      *   <li>Otherwise, Rekey will be used for mobility
202      * </ul>
203      *
204      * <p>For callers targeting SDK {@link android.os.Build.VERSION_CODES#S_V2} or earlier, setting
205      * {@link #IKE_OPTION_MOBIKE} will implicitly set {@link #IKE_OPTION_REKEY_MOBILITY}.
206      *
207      * <p>If this option is set for an IKE Session, Transport-mode SAs will not be allowed in that
208      * Session.
209      *
210      * <p>Callers that need to perform migration of IPsec transforms and tunnels MUST implement
211      * migration specific methods in {@link IkeSessionCallback} and {@link ChildSessionCallback}.
212      *
213      * @see {@link IKE_OPTION_MOBIKE}
214      * @see {@link IkeSession#setNetwork(Network)}
215      * @hide
216      */
217     @SystemApi public static final int IKE_OPTION_REKEY_MOBILITY = 5;
218 
219     /**
220      * If set, IKE Session will automatically select address families.
221      *
222      * <p>IP address families often have different performance characteristics on any given network.
223      * For example, IPv6 ESP may not be hardware-accelerated by middleboxes, or completely
224      * black-holed. This option allows the IKE session to automatically select based on the IP
225      * address family it perceives as the most likely to work well.
226      *
227      * @hide
228      */
229     public static final int IKE_OPTION_AUTOMATIC_ADDRESS_FAMILY_SELECTION = 6;
230 
231     /**
232      * If set, the IKE session will select the NATT keepalive timers automatically.
233      *
234      * <p>NATT keepalive timers will be selected and adjusted based on the underlying network
235      * configurations, and updated as underlying network configurations change.
236      *
237      * @hide
238      */
239     public static final int IKE_OPTION_AUTOMATIC_NATT_KEEPALIVES = 7;
240 
241     /**
242      * If set, the IKE session will start the NATT keepalive with a power optimization flag.
243      *
244      * <p>IKE session will start the keepalive with {@link SocketKeepalive#FLAG_AUTOMATIC_ON_OFF}.
245      * The system will automatically disable keepalives when no TCP connections are open on the
246      * network that is associated with the IKE session.
247      *
248      * <p>For callers relying on long-lived UDP port mappings through the IPsec layer, this flag
249      * should never be used since the keepalive may be stopped unexpectedly.
250      *
251      * <p>This option applies to only hardware keepalive. When keepalive switches to software
252      * keepalive because of errors on hardware keepalive, this option may be ignored.
253      *
254      * @hide
255      */
256     // TODO(b/269200616): Move software keepalive mechanism to other place with the required
257     //  permission to get TCP socket status via netlink commands to also get benefit from this
258     //  option.
259     @SystemApi
260     public static final int IKE_OPTION_AUTOMATIC_KEEPALIVE_ON_OFF = 8;
261 
262     private static final int MIN_IKE_OPTION = IKE_OPTION_ACCEPT_ANY_REMOTE_ID;
263     private static final int MAX_IKE_OPTION = IKE_OPTION_AUTOMATIC_KEEPALIVE_ON_OFF;
264 
265     /**
266      * Automatically choose the IP version for ESP packets.
267      * @hide
268      */
269     @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES)
270     public static final int ESP_IP_VERSION_AUTO = 0;
271 
272     /**
273      * Use IPv4 for ESP packets.
274      * @hide
275      */
276     @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES)
277     public static final int ESP_IP_VERSION_IPV4 = 4;
278 
279     /**
280      * Use IPv6 for ESP packets.
281      * @hide
282      */
283     @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES)
284     public static final int ESP_IP_VERSION_IPV6 = 6;
285 
286     // IP version to store in mEspIpVersion.
287     /** @hide */
288     @Retention(RetentionPolicy.SOURCE)
289     @IntDef({
290             ESP_IP_VERSION_AUTO,
291             ESP_IP_VERSION_IPV4,
292             ESP_IP_VERSION_IPV6,
293     })
294     public @interface EspIpVersion {}
295 
296     /**
297      * Automatically choose the encapsulation type for ESP packets.
298      * @hide
299      */
300     @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES)
301     public static final int ESP_ENCAP_TYPE_AUTO = 0;
302 
303     /**
304      * Do not encapsulate ESP packets in transport layer protocol.
305      *
306      * Under this encapsulation type, the IKE Session will send NAT detection only when it is
307      * performing mobility update from an environment with a NAT, as an attempt to stop using
308      * UDP encapsulation for the ESP packets. If IKE Session still detects a NAT in this case,
309      * the IKE Session will be terminated.
310      *
311      * @hide
312      */
313     @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES)
314     public static final int ESP_ENCAP_TYPE_NONE = -1;
315 
316     /**
317      * Encapsulate ESP packets in UDP.
318      *
319      * Under this encapsulation type, the IKE Session will send NAT detection and fake a local
320      * NAT. In this case the IKE Session will always encapsulate ESP packets in UDP as long as
321      * the server also supports NAT traversal.
322      *
323      * @hide
324      */
325     @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES)
326     public static final int ESP_ENCAP_TYPE_UDP = 17;
327 
328     // Encap type to store in mEspEncapType.
329     /** @hide */
330     @Retention(RetentionPolicy.SOURCE)
331     @IntDef({
332             ESP_ENCAP_TYPE_AUTO,
333             ESP_ENCAP_TYPE_NONE,
334             ESP_ENCAP_TYPE_UDP,
335     })
336     public @interface EspEncapType {}
337 
338     /**
339      * Automatically choose the keepalive interval.
340      *
341      * This constant can be passed to
342      * {@link com.android.internal.net.ipsec.ike.IkeSessionStateMachine#setNetwork} to signify
343      * that the keepalive delay should be deduced automatically from the underlying network.
344      *
345      * @see #getNattKeepAliveDelaySeconds
346      * @hide
347      */
348     @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES)
349     public static final int NATT_KEEPALIVE_INTERVAL_AUTO = -1;
350 
351     /** @hide */
352     @VisibleForTesting static final int IKE_HARD_LIFETIME_SEC_MINIMUM = 300; // 5 minutes
353     /** @hide */
354     @VisibleForTesting static final int IKE_HARD_LIFETIME_SEC_MAXIMUM = 86400; // 24 hours
355     /** @hide */
356     @VisibleForTesting static final int IKE_HARD_LIFETIME_SEC_DEFAULT = 14400; // 4 hours
357 
358     /** @hide */
359     @VisibleForTesting static final int IKE_SOFT_LIFETIME_SEC_MINIMUM = 120; // 2 minutes
360     /** @hide */
361     @VisibleForTesting static final int IKE_SOFT_LIFETIME_SEC_DEFAULT = 7200; // 2 hours
362 
363     /** @hide */
364     @VisibleForTesting
365     static final int IKE_LIFETIME_MARGIN_SEC_MINIMUM = (int) TimeUnit.MINUTES.toSeconds(1L);
366 
367     /** @hide */
368     @VisibleForTesting static final int IKE_DPD_DELAY_SEC_MIN = 20;
369     /** @hide */
370     @VisibleForTesting static final int IKE_DPD_DELAY_SEC_MAX = 1800; // 30 minutes
371     /** @hide */
372     @VisibleForTesting static final int IKE_DPD_DELAY_SEC_DEFAULT = 120; // 2 minutes
373     /** @hide */
374     public static final int IKE_DPD_DELAY_SEC_DISABLED = Integer.MAX_VALUE;
375 
376     /** @hide */
377     @VisibleForTesting public static final int IKE_NATT_KEEPALIVE_DELAY_SEC_MIN = 10;
378     /** @hide */
379     @VisibleForTesting public static final int IKE_NATT_KEEPALIVE_DELAY_SEC_MAX = 3600;
380     /** @hide */
381     @VisibleForTesting static final int IKE_NATT_KEEPALIVE_DELAY_SEC_DEFAULT = 10;
382 
383     /** @hide */
384     @VisibleForTesting static final int DSCP_MIN = 0;
385     /** @hide */
386     @VisibleForTesting static final int DSCP_MAX = 63;
387     /** @hide */
388     @VisibleForTesting static final int DSCP_DEFAULT = 0;
389 
390     /** @hide */
391     @VisibleForTesting static final int IKE_RETRANS_TIMEOUT_MS_MIN = 500;
392     /** @hide */
393     @VisibleForTesting
394     static final int IKE_RETRANS_TIMEOUT_MS_MAX = (int) TimeUnit.MINUTES.toMillis(30L);
395     /** @hide */
396     @VisibleForTesting static final int IKE_RETRANS_MAX_ATTEMPTS_MAX = 10;
397     /** @hide */
398     @VisibleForTesting
399     static final int[] IKE_RETRANS_TIMEOUT_MS_LIST_DEFAULT =
400             new int[] {500, 1000, 2000, 4000, 8000};
401 
402     private static final String SERVER_HOST_NAME_KEY = "mServerHostname";
403     private static final String SA_PROPOSALS_KEY = "mSaProposals";
404     private static final String LOCAL_ID_KEY = "mLocalIdentification";
405     private static final String REMOTE_ID_KEY = "mRemoteIdentification";
406     private static final String LOCAL_AUTH_KEY = "mLocalAuthConfig";
407     private static final String REMOTE_AUTH_KEY = "mRemoteAuthConfig";
408     private static final String CONFIG_ATTRIBUTES_KEY = "mConfigRequests";
409     private static final String RETRANS_TIMEOUTS_KEY = "mRetransTimeoutMsList";
410     private static final String IKE_OPTIONS_KEY = "mIkeOptions";
411     private static final String HARD_LIFETIME_SEC_KEY = "mHardLifetimeSec";
412     private static final String SOFT_LIFETIME_SEC_KEY = "mSoftLifetimeSec";
413     private static final String DPD_DELAY_SEC_KEY = "mDpdDelaySec";
414     private static final String NATT_KEEPALIVE_DELAY_SEC_KEY = "mNattKeepaliveDelaySec";
415     private static final String DSCP_KEY = "mDscp";
416     private static final String IS_IKE_FRAGMENT_SUPPORTED_KEY = "mIsIkeFragmentationSupported";
417     private static final String IP_VERSION_KEY = "mIpVersion";
418     private static final String ENCAP_TYPE_KEY = "mEncapType";
419 
420     @NonNull private final String mServerHostname;
421 
422     // @see #getNetwork for reasons of changing the annotation from @NonNull to @Nullable in SDK S.
423     // Do not include mDefaultOrConfiguredNetwork in #hashCode or #equal because when it represents
424     // configured network, it always has the same value as mCallerConfiguredNetwork. When it
425     // represents a default network it can only reflects the device status at the IkeSessionParams
426     // creation time. Since the actually default network may change after IkeSessionParams is
427     // constructed, depending on mDefaultOrConfiguredNetwork in #hashCode and #equal to decide
428     // if this object equals to another object does not make sense.
429     @Nullable private final Network mDefaultOrConfiguredNetwork;
430 
431     @Nullable private final Network mCallerConfiguredNetwork;
432 
433     @NonNull private final IkeSaProposal[] mSaProposals;
434 
435     @NonNull private final IkeIdentification mLocalIdentification;
436     @NonNull private final IkeIdentification mRemoteIdentification;
437 
438     @NonNull private final IkeAuthConfig mLocalAuthConfig;
439     @NonNull private final IkeAuthConfig mRemoteAuthConfig;
440 
441     @NonNull private final IkeConfigAttribute[] mConfigRequests;
442 
443     @NonNull private final int[] mRetransTimeoutMsList;
444 
445     @Nullable private final Ike3gppExtension mIke3gppExtension;
446 
447     private final long mIkeOptions;
448 
449     private final int mHardLifetimeSec;
450     private final int mSoftLifetimeSec;
451 
452     private final int mDpdDelaySec;
453     private final int mNattKeepaliveDelaySec;
454     private final int mDscp;
455     @EspIpVersion private final int mIpVersion;
456     @EspEncapType private final int mEncapType;
457 
458     private final boolean mIsIkeFragmentationSupported;
459 
IkeSessionParams( @onNull String serverHostname, @NonNull Network defaultOrConfiguredNetwork, @NonNull Network callerConfiguredNetwork, @NonNull IkeSaProposal[] proposals, @NonNull IkeIdentification localIdentification, @NonNull IkeIdentification remoteIdentification, @NonNull IkeAuthConfig localAuthConfig, @NonNull IkeAuthConfig remoteAuthConfig, @NonNull IkeConfigAttribute[] configRequests, @NonNull int[] retransTimeoutMsList, @Nullable Ike3gppExtension ike3gppExtension, long ikeOptions, int hardLifetimeSec, int softLifetimeSec, int dpdDelaySec, int nattKeepaliveDelaySec, int dscp, @EspIpVersion int espIpVersion, @EspEncapType int espEncapType, boolean isIkeFragmentationSupported)460     private IkeSessionParams(
461             @NonNull String serverHostname,
462             @NonNull Network defaultOrConfiguredNetwork,
463             @NonNull Network callerConfiguredNetwork,
464             @NonNull IkeSaProposal[] proposals,
465             @NonNull IkeIdentification localIdentification,
466             @NonNull IkeIdentification remoteIdentification,
467             @NonNull IkeAuthConfig localAuthConfig,
468             @NonNull IkeAuthConfig remoteAuthConfig,
469             @NonNull IkeConfigAttribute[] configRequests,
470             @NonNull int[] retransTimeoutMsList,
471             @Nullable Ike3gppExtension ike3gppExtension,
472             long ikeOptions,
473             int hardLifetimeSec,
474             int softLifetimeSec,
475             int dpdDelaySec,
476             int nattKeepaliveDelaySec,
477             int dscp,
478             @EspIpVersion int espIpVersion,
479             @EspEncapType int espEncapType,
480             boolean isIkeFragmentationSupported) {
481         mServerHostname = serverHostname;
482         mDefaultOrConfiguredNetwork = defaultOrConfiguredNetwork;
483         mCallerConfiguredNetwork = callerConfiguredNetwork;
484 
485         mSaProposals = proposals;
486 
487         mLocalIdentification = localIdentification;
488         mRemoteIdentification = remoteIdentification;
489 
490         mLocalAuthConfig = localAuthConfig;
491         mRemoteAuthConfig = remoteAuthConfig;
492 
493         mConfigRequests = configRequests;
494 
495         mRetransTimeoutMsList = retransTimeoutMsList;
496 
497         mIke3gppExtension = ike3gppExtension;
498 
499         mIkeOptions = ikeOptions;
500 
501         mHardLifetimeSec = hardLifetimeSec;
502         mSoftLifetimeSec = softLifetimeSec;
503 
504         mDpdDelaySec = dpdDelaySec;
505         mNattKeepaliveDelaySec = nattKeepaliveDelaySec;
506         mDscp = dscp;
507 
508         mIpVersion = espIpVersion;
509         mEncapType = espEncapType;
510 
511         mIsIkeFragmentationSupported = isIkeFragmentationSupported;
512     }
513 
validateIkeOptionOrThrow(@keOption int ikeOption)514     private static void validateIkeOptionOrThrow(@IkeOption int ikeOption) {
515         if (ikeOption < MIN_IKE_OPTION || ikeOption > MAX_IKE_OPTION) {
516             throw new IllegalArgumentException("Invalid IKE Option: " + ikeOption);
517         }
518     }
519 
getOptionBitValue(int ikeOption)520     private static long getOptionBitValue(int ikeOption) {
521         return 1 << ikeOption;
522     }
523 
524     /**
525      * Constructs this object by deserializing a PersistableBundle
526      *
527      * <p>Constructed IkeSessionParams is guaranteed to be valid, as checked by the
528      * IkeSessionParams.Builder
529      *
530      * @hide
531      */
532     @NonNull
fromPersistableBundle(@onNull PersistableBundle in)533     public static IkeSessionParams fromPersistableBundle(@NonNull PersistableBundle in) {
534         Objects.requireNonNull(in, "PersistableBundle is null");
535 
536         IkeSessionParams.Builder builder = new IkeSessionParams.Builder();
537 
538         builder.setServerHostname(in.getString(SERVER_HOST_NAME_KEY));
539 
540         PersistableBundle proposalBundle = in.getPersistableBundle(SA_PROPOSALS_KEY);
541         Objects.requireNonNull(in, "SA Proposals is null");
542         List<IkeSaProposal> saProposals =
543                 PersistableBundleUtils.toList(proposalBundle, IkeSaProposal::fromPersistableBundle);
544         for (IkeSaProposal proposal : saProposals) {
545             builder.addSaProposal(proposal);
546         }
547 
548         builder.setLocalIdentification(
549                 IkeIdentification.fromPersistableBundle(in.getPersistableBundle(LOCAL_ID_KEY)));
550         builder.setRemoteIdentification(
551                 IkeIdentification.fromPersistableBundle(in.getPersistableBundle(REMOTE_ID_KEY)));
552         builder.setAuth(
553                 IkeAuthConfig.fromPersistableBundle(in.getPersistableBundle(LOCAL_AUTH_KEY)),
554                 IkeAuthConfig.fromPersistableBundle(in.getPersistableBundle(REMOTE_AUTH_KEY)));
555 
556         PersistableBundle configBundle = in.getPersistableBundle(CONFIG_ATTRIBUTES_KEY);
557         Objects.requireNonNull(configBundle, "configBundle is null");
558         List<ConfigAttribute> configList =
559                 PersistableBundleUtils.toList(configBundle, ConfigAttribute::fromPersistableBundle);
560         for (ConfigAttribute configAttribute : configList) {
561             builder.addConfigRequest((IkeConfigAttribute) configAttribute);
562         }
563 
564         builder.setRetransmissionTimeoutsMillis(in.getIntArray(RETRANS_TIMEOUTS_KEY));
565 
566         long ikeOptions = in.getLong(IKE_OPTIONS_KEY);
567         for (int option = MIN_IKE_OPTION; option <= MAX_IKE_OPTION; option++) {
568             if (hasIkeOption(ikeOptions, option)) {
569                 builder.addIkeOptionInternal(option);
570             } else {
571                 builder.removeIkeOption(option);
572             }
573         }
574 
575         builder.setLifetimeSeconds(
576                 in.getInt(HARD_LIFETIME_SEC_KEY), in.getInt(SOFT_LIFETIME_SEC_KEY));
577         builder.setDpdDelaySeconds(in.getInt(DPD_DELAY_SEC_KEY));
578         builder.setNattKeepAliveDelaySeconds(in.getInt(NATT_KEEPALIVE_DELAY_SEC_KEY));
579 
580         builder.setIpVersion(in.getInt(IP_VERSION_KEY));
581         builder.setEncapType(in.getInt(ENCAP_TYPE_KEY));
582 
583         // Fragmentation policy is not configurable. IkeSessionParams will always be constructed to
584         // support fragmentation.
585         if (!in.getBoolean(IS_IKE_FRAGMENT_SUPPORTED_KEY)) {
586             throw new IllegalArgumentException("Invalid fragmentation policy");
587         }
588 
589         return builder.build();
590     }
591     /**
592      * Serializes this object to a PersistableBundle
593      *
594      * @hide
595      */
596     @NonNull
toPersistableBundle()597     public PersistableBundle toPersistableBundle() {
598         if (mCallerConfiguredNetwork != null || mIke3gppExtension != null) {
599             throw new IllegalStateException(
600                     "Cannot convert a IkeSessionParams with a caller configured network or with"
601                             + " 3GPP extension enabled");
602         }
603         final PersistableBundle result = new PersistableBundle();
604 
605         result.putString(SERVER_HOST_NAME_KEY, mServerHostname);
606 
607         PersistableBundle saProposalBundle =
608                 PersistableBundleUtils.fromList(
609                         Arrays.asList(mSaProposals), IkeSaProposal::toPersistableBundle);
610         result.putPersistableBundle(SA_PROPOSALS_KEY, saProposalBundle);
611 
612         result.putPersistableBundle(LOCAL_ID_KEY, mLocalIdentification.toPersistableBundle());
613         result.putPersistableBundle(REMOTE_ID_KEY, mRemoteIdentification.toPersistableBundle());
614         result.putPersistableBundle(LOCAL_AUTH_KEY, mLocalAuthConfig.toPersistableBundle());
615         result.putPersistableBundle(REMOTE_AUTH_KEY, mRemoteAuthConfig.toPersistableBundle());
616 
617         PersistableBundle configAttributeBundle =
618                 PersistableBundleUtils.fromList(
619                         Arrays.asList(mConfigRequests), ConfigAttribute::toPersistableBundle);
620         result.putPersistableBundle(CONFIG_ATTRIBUTES_KEY, configAttributeBundle);
621 
622         result.putIntArray(RETRANS_TIMEOUTS_KEY, mRetransTimeoutMsList);
623         result.putLong(IKE_OPTIONS_KEY, mIkeOptions);
624         result.putInt(HARD_LIFETIME_SEC_KEY, mHardLifetimeSec);
625         result.putInt(SOFT_LIFETIME_SEC_KEY, mSoftLifetimeSec);
626         result.putInt(DPD_DELAY_SEC_KEY, mDpdDelaySec);
627         result.putInt(NATT_KEEPALIVE_DELAY_SEC_KEY, mNattKeepaliveDelaySec);
628         result.putInt(DSCP_KEY, mDscp);
629         result.putBoolean(IS_IKE_FRAGMENT_SUPPORTED_KEY, mIsIkeFragmentationSupported);
630         result.putInt(IP_VERSION_KEY, mIpVersion);
631         result.putInt(ENCAP_TYPE_KEY, mEncapType);
632 
633         return result;
634     }
635 
636     /**
637      * Retrieves the configured server hostname
638      *
639      * <p>The configured server hostname will be resolved during IKE Session creation.
640      */
641     @NonNull
getServerHostname()642     public String getServerHostname() {
643         return mServerHostname;
644     }
645 
646     /**
647      * Retrieves the configured {@link Network}, or null if was not set
648      *
649      * <p>This getter is for internal use. Not matter {@link Builder#Builder(Context)} or {@link
650      * Builder#Builder()} is used, this method will always return null if no Network was set by the
651      * caller.
652      *
653      * @hide
654      */
655     @Nullable
getConfiguredNetwork()656     public Network getConfiguredNetwork() {
657         return mCallerConfiguredNetwork;
658     }
659 
660     // This method was first released as a @NonNull System APi and has been changed to @Nullable
661     // since Android S. This method needs to be @Nullable because a new Builder constructor {@link
662     // Builder#Builder() was added in Android S, and by using the new constructor the return value
663     // of this method will be null if no network was set.
664     // For apps that are using a null-safe language, making this method @Nullable will break
665     // compilation, and apps need to update their code. For apps that are not using null-safe
666     // language, making this change will not break the backwards compatibility because for any app
667     // that uses the deprecated constructor {@link Builder#Builder(Context)}, the return value of
668     // this method is still guaranteed to be non-null.
669     /**
670      * Retrieves the configured {@link Network}, or null if was not set.
671      *
672      * <p>@see {@link Builder#setNetwork(Network)}
673      */
674     @Nullable
getNetwork()675     public Network getNetwork() {
676         return mDefaultOrConfiguredNetwork;
677     }
678 
679     /**
680      * Retrieves all IkeSaProposals configured
681      *
682      * @deprecated Callers should use {@link #getIkeSaProposals()}. This method is deprecated
683      *     because its name does not match the return type.
684      * @hide
685      */
686     @Deprecated
687     @SystemApi
688     @NonNull
getSaProposals()689     public List<IkeSaProposal> getSaProposals() {
690         return getIkeSaProposals();
691     }
692 
693     /** Retrieves all IkeSaProposals configured */
694     @NonNull
getIkeSaProposals()695     public List<IkeSaProposal> getIkeSaProposals() {
696         return Arrays.asList(mSaProposals);
697     }
698 
699     /** @hide */
getSaProposalsInternal()700     public IkeSaProposal[] getSaProposalsInternal() {
701         return mSaProposals;
702     }
703 
704     /** Retrieves the local (client) identity */
705     @NonNull
getLocalIdentification()706     public IkeIdentification getLocalIdentification() {
707         return mLocalIdentification;
708     }
709 
710     /** Retrieves the required remote (server) identity */
711     @NonNull
getRemoteIdentification()712     public IkeIdentification getRemoteIdentification() {
713         return mRemoteIdentification;
714     }
715 
716     /** Retrieves the local (client) authentication configuration */
717     @NonNull
getLocalAuthConfig()718     public IkeAuthConfig getLocalAuthConfig() {
719         return mLocalAuthConfig;
720     }
721 
722     /** Retrieves the remote (server) authentication configuration */
723     @NonNull
getRemoteAuthConfig()724     public IkeAuthConfig getRemoteAuthConfig() {
725         return mRemoteAuthConfig;
726     }
727 
728     /** Retrieves hard lifetime in seconds */
729     // Use "second" because smaller unit won't make sense to describe a rekey interval.
730     @SuppressLint("MethodNameUnits")
731     @IntRange(from = IKE_HARD_LIFETIME_SEC_MINIMUM, to = IKE_HARD_LIFETIME_SEC_MAXIMUM)
getHardLifetimeSeconds()732     public int getHardLifetimeSeconds() {
733         return mHardLifetimeSec;
734     }
735 
736     /** Retrieves soft lifetime in seconds */
737     // Use "second" because smaller unit does not make sense to a rekey interval.
738     @SuppressLint("MethodNameUnits")
739     @IntRange(from = IKE_SOFT_LIFETIME_SEC_MINIMUM, to = IKE_HARD_LIFETIME_SEC_MAXIMUM)
getSoftLifetimeSeconds()740     public int getSoftLifetimeSeconds() {
741         return mSoftLifetimeSec;
742     }
743 
744     /** Retrieves the Dead Peer Detection(DPD) delay in seconds */
745     // Use "second" because smaller unit does not make sense to a DPD delay.
746     @SuppressLint("MethodNameUnits")
747     @IntRange(from = IKE_DPD_DELAY_SEC_MIN, to = IKE_DPD_DELAY_SEC_MAX)
getDpdDelaySeconds()748     public int getDpdDelaySeconds() {
749         return mDpdDelaySec;
750     }
751 
752     /** Retrieves the Network Address Translation Traversal (NATT) keepalive delay in seconds */
753     // Use "second" because smaller unit does not make sense for a NATT Keepalive delay.
754     @SuppressLint("MethodNameUnits")
755     @IntRange(from = IKE_NATT_KEEPALIVE_DELAY_SEC_MIN, to = IKE_NATT_KEEPALIVE_DELAY_SEC_MAX)
getNattKeepAliveDelaySeconds()756     public int getNattKeepAliveDelaySeconds() {
757         return mNattKeepaliveDelaySec;
758     }
759 
760     /**
761      * Retrieves the DSCP field of IKE packets.
762      *
763      * @hide
764      */
765     @SystemApi
766     @IntRange(from = DSCP_MIN, to = DSCP_MAX)
getDscp()767     public int getDscp() {
768         return mDscp;
769     }
770 
771     /**
772      * Retrieves the IP version.
773      * @hide
774      */
775     @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES)
getIpVersion()776     @EspIpVersion public int getIpVersion() {
777         return mIpVersion;
778     }
779 
780     /**
781      * Retrieves the encap type.
782      * @hide
783      */
784     @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES)
getEncapType()785     @EspEncapType public int getEncapType() {
786         return mEncapType;
787     }
788 
789     /**
790      * Retrieves the relative retransmission timeout list in milliseconds
791      *
792      * <p>@see {@link Builder#setRetransmissionTimeoutsMillis(int[])}
793      */
794     @NonNull
getRetransmissionTimeoutsMillis()795     public int[] getRetransmissionTimeoutsMillis() {
796         return mRetransTimeoutMsList;
797     }
798 
799     /**
800      * Retrieves the configured Ike3gppExtension, or null if it was not set.
801      *
802      * @hide
803      */
804     @SystemApi
805     @Nullable
getIke3gppExtension()806     public Ike3gppExtension getIke3gppExtension() {
807         return mIke3gppExtension;
808     }
809 
hasIkeOption(long ikeOptionsRecord, @IkeOption int ikeOption)810     private static boolean hasIkeOption(long ikeOptionsRecord, @IkeOption int ikeOption) {
811         validateIkeOptionOrThrow(ikeOption);
812         return (ikeOptionsRecord & getOptionBitValue(ikeOption)) != 0;
813     }
814 
815     /**
816      * Checks if the given IKE Session negotiation option is set
817      *
818      * @param ikeOption the option to check.
819      * @throws IllegalArgumentException if the provided option is invalid.
820      */
hasIkeOption(@keOption int ikeOption)821     public boolean hasIkeOption(@IkeOption int ikeOption) {
822         return hasIkeOption(mIkeOptions, ikeOption);
823     }
824 
825     /** @hide */
getHardLifetimeMsInternal()826     public long getHardLifetimeMsInternal() {
827         return TimeUnit.SECONDS.toMillis((long) mHardLifetimeSec);
828     }
829 
830     /** @hide */
getSoftLifetimeMsInternal()831     public long getSoftLifetimeMsInternal() {
832         return TimeUnit.SECONDS.toMillis((long) mSoftLifetimeSec);
833     }
834 
835     /** @hide */
isIkeFragmentationSupported()836     public boolean isIkeFragmentationSupported() {
837         return mIsIkeFragmentationSupported;
838     }
839 
840     /** @hide */
getConfigurationAttributesInternal()841     public IkeConfigAttribute[] getConfigurationAttributesInternal() {
842         return mConfigRequests;
843     }
844 
845     /**
846      * Retrieves the list of Configuration Requests
847      *
848      * @hide
849      */
850     @SystemApi
851     @NonNull
getConfigurationRequests()852     public List<IkeConfigRequest> getConfigurationRequests() {
853         return Collections.unmodifiableList(Arrays.asList(mConfigRequests));
854     }
855 
856     /** @hide */
857     @Override
hashCode()858     public int hashCode() {
859         return Objects.hash(
860                 mServerHostname,
861                 mCallerConfiguredNetwork,
862                 Arrays.hashCode(mSaProposals),
863                 mLocalIdentification,
864                 mRemoteIdentification,
865                 mLocalAuthConfig,
866                 mRemoteAuthConfig,
867                 mIke3gppExtension,
868                 Arrays.hashCode(mConfigRequests),
869                 Arrays.hashCode(mRetransTimeoutMsList),
870                 mIkeOptions,
871                 mHardLifetimeSec,
872                 mSoftLifetimeSec,
873                 mDpdDelaySec,
874                 mNattKeepaliveDelaySec,
875                 mDscp,
876                 mIsIkeFragmentationSupported,
877                 mIpVersion,
878                 mEncapType);
879     }
880 
881     /** @hide */
882     @Override
equals(Object o)883     public boolean equals(Object o) {
884         if (!(o instanceof IkeSessionParams)) {
885             return false;
886         }
887 
888         IkeSessionParams other = (IkeSessionParams) o;
889 
890         return mServerHostname.equals(other.mServerHostname)
891                 && Objects.equals(mCallerConfiguredNetwork, other.mCallerConfiguredNetwork)
892                 && Arrays.equals(mSaProposals, other.mSaProposals)
893                 && mLocalIdentification.equals(other.mLocalIdentification)
894                 && mRemoteIdentification.equals(other.mRemoteIdentification)
895                 && mLocalAuthConfig.equals(other.mLocalAuthConfig)
896                 && mRemoteAuthConfig.equals(other.mRemoteAuthConfig)
897                 && Objects.equals(mIke3gppExtension, other.mIke3gppExtension)
898                 && Arrays.equals(mConfigRequests, other.mConfigRequests)
899                 && Arrays.equals(mRetransTimeoutMsList, other.mRetransTimeoutMsList)
900                 && mIkeOptions == other.mIkeOptions
901                 && mHardLifetimeSec == other.mHardLifetimeSec
902                 && mSoftLifetimeSec == other.mSoftLifetimeSec
903                 && mDpdDelaySec == other.mDpdDelaySec
904                 && mNattKeepaliveDelaySec == other.mNattKeepaliveDelaySec
905                 && mDscp == other.mDscp
906                 && mIsIkeFragmentationSupported == other.mIsIkeFragmentationSupported
907                 && mIpVersion == other.mIpVersion
908                 && mEncapType == other.mEncapType;
909     }
910 
911     /**
912      * Represents an IKE session configuration request type
913      *
914      * @hide
915      */
916     @SystemApi
917     public interface IkeConfigRequest {}
918 
919     /**
920      * Represents an IPv4 P_CSCF request
921      *
922      * @hide
923      */
924     @SystemApi
925     public interface ConfigRequestIpv4PcscfServer extends IkeConfigRequest {
926         /**
927          * Retrieves the requested IPv4 P_CSCF server address
928          *
929          * @return The requested P_CSCF server address, or null if no specific P_CSCF server was
930          *     requested
931          */
932         @Nullable
getAddress()933         Inet4Address getAddress();
934     }
935 
936     /**
937      * Represents an IPv6 P_CSCF request
938      *
939      * @hide
940      */
941     @SystemApi
942     public interface ConfigRequestIpv6PcscfServer extends IkeConfigRequest {
943         /**
944          * Retrieves the requested IPv6 P_CSCF server address
945          *
946          * @return The requested P_CSCF server address, or null if no specific P_CSCF server was
947          *     requested
948          */
949         @Nullable
getAddress()950         Inet6Address getAddress();
951     }
952 
953     /** This class contains common information of an IKEv2 authentication configuration. */
954     public abstract static class IkeAuthConfig {
955         private static final String AUTH_METHOD_KEY = "mAuthMethod";
956         private static final String AUTH_DIRECTION_KEY = "mAuthDirection";
957         /** @hide */
958         @IkeAuthMethod public final int mAuthMethod;
959         /** @hide */
960         @AuthDirection public final int mAuthDirection;
961 
962         /** @hide */
IkeAuthConfig(@keAuthMethod int authMethod, @AuthDirection int authDirection)963         IkeAuthConfig(@IkeAuthMethod int authMethod, @AuthDirection int authDirection) {
964             mAuthMethod = authMethod;
965             mAuthDirection = authDirection;
966         }
967 
968         /**
969          * Constructs this object by deserializing a PersistableBundle
970          *
971          * @hide
972          */
973         @NonNull
fromPersistableBundle(PersistableBundle in)974         public static IkeAuthConfig fromPersistableBundle(PersistableBundle in) {
975             Objects.requireNonNull(in, "PersistableBundle is null");
976 
977             int authMethod = in.getInt(AUTH_METHOD_KEY);
978             switch (authMethod) {
979                 case IKE_AUTH_METHOD_PSK:
980                     return IkeAuthPskConfig.fromPersistableBundle(in);
981                 case IKE_AUTH_METHOD_PUB_KEY_SIGNATURE:
982                     switch (in.getInt(AUTH_DIRECTION_KEY)) {
983                         case AUTH_DIRECTION_LOCAL:
984                             return IkeAuthDigitalSignLocalConfig.fromPersistableBundle(in);
985                         case AUTH_DIRECTION_REMOTE:
986                             return IkeAuthDigitalSignRemoteConfig.fromPersistableBundle(in);
987                         default:
988                             throw new IllegalArgumentException(
989                                     "Digital-signature-based auth configuration with invalid"
990                                             + " direction: "
991                                             + in.getInt(AUTH_DIRECTION_KEY));
992                     }
993                 case IKE_AUTH_METHOD_EAP:
994                     return IkeAuthEapConfig.fromPersistableBundle(in);
995                 default:
996                     throw new IllegalArgumentException("Invalid Auth Method: " + authMethod);
997             }
998         }
999 
1000         /**
1001          * Serializes this object to a PersistableBundle
1002          *
1003          * @hide
1004          */
1005         @NonNull
toPersistableBundle()1006         protected PersistableBundle toPersistableBundle() {
1007             final PersistableBundle result = new PersistableBundle();
1008 
1009             result.putInt(AUTH_METHOD_KEY, mAuthMethod);
1010             result.putInt(AUTH_DIRECTION_KEY, mAuthDirection);
1011             return result;
1012         }
1013 
1014         @Override
hashCode()1015         public int hashCode() {
1016             return Objects.hash(mAuthMethod, mAuthDirection);
1017         }
1018 
1019         @Override
equals(Object o)1020         public boolean equals(Object o) {
1021             if (!(o instanceof IkeAuthConfig)) {
1022                 return false;
1023             }
1024 
1025             IkeAuthConfig other = (IkeAuthConfig) o;
1026 
1027             return mAuthMethod == other.mAuthMethod && mAuthDirection == other.mAuthDirection;
1028         }
1029     }
1030 
1031     /**
1032      * This class represents the configuration to support IKEv2 pre-shared-key-based authentication
1033      * of local or remote side.
1034      */
1035     public static class IkeAuthPskConfig extends IkeAuthConfig {
1036         private static final String PSK_KEY = "mPsk";
1037         /** @hide */
1038         @NonNull public final byte[] mPsk;
1039 
1040         /** @hide */
1041         @VisibleForTesting
IkeAuthPskConfig(byte[] psk)1042         IkeAuthPskConfig(byte[] psk) {
1043             super(IKE_AUTH_METHOD_PSK, AUTH_DIRECTION_BOTH);
1044             mPsk = psk;
1045         }
1046 
1047         /**
1048          * Constructs this object by deserializing a PersistableBundle
1049          *
1050          * @hide
1051          */
1052         @NonNull
fromPersistableBundle(@onNull PersistableBundle in)1053         public static IkeAuthPskConfig fromPersistableBundle(@NonNull PersistableBundle in) {
1054             Objects.requireNonNull(in, "PersistableBundle is null");
1055 
1056             PersistableBundle pskBundle = in.getPersistableBundle(PSK_KEY);
1057             Objects.requireNonNull(in, "PSK bundle is null");
1058 
1059             return new IkeAuthPskConfig(PersistableBundleUtils.toByteArray(pskBundle));
1060         }
1061 
1062         /**
1063          * Serializes this object to a PersistableBundle
1064          *
1065          * @hide
1066          */
1067         @Override
1068         @NonNull
toPersistableBundle()1069         public PersistableBundle toPersistableBundle() {
1070             final PersistableBundle result = super.toPersistableBundle();
1071 
1072             result.putPersistableBundle(PSK_KEY, PersistableBundleUtils.fromByteArray(mPsk));
1073             return result;
1074         }
1075 
1076         /** Retrieves the pre-shared key */
1077         @NonNull
getPsk()1078         public byte[] getPsk() {
1079             return Arrays.copyOf(mPsk, mPsk.length);
1080         }
1081 
1082         @Override
hashCode()1083         public int hashCode() {
1084             return Objects.hash(super.hashCode(), Arrays.hashCode(mPsk));
1085         }
1086 
1087         @Override
equals(Object o)1088         public boolean equals(Object o) {
1089             if (!super.equals(o) || !(o instanceof IkeAuthPskConfig)) {
1090                 return false;
1091             }
1092 
1093             return Arrays.equals(mPsk, ((IkeAuthPskConfig) o).mPsk);
1094         }
1095     }
1096 
1097     /**
1098      * This class represents the configuration to support IKEv2 public-key-signature-based
1099      * authentication of the remote side.
1100      */
1101     public static class IkeAuthDigitalSignRemoteConfig extends IkeAuthConfig {
1102         private static final String TRUST_CERT_KEY = "TRUST_CERT_KEY";
1103         /** @hide */
1104         @Nullable public final TrustAnchor mTrustAnchor;
1105 
1106         /**
1107          * If a certificate is provided, it MUST be the root CA used by the remote (server), or
1108          * authentication will fail. If no certificate is provided, any root CA in the system's
1109          * truststore is considered acceptable.
1110          *
1111          * @hide
1112          */
1113         @VisibleForTesting
IkeAuthDigitalSignRemoteConfig(@ullable X509Certificate caCert)1114         IkeAuthDigitalSignRemoteConfig(@Nullable X509Certificate caCert) {
1115             super(IKE_AUTH_METHOD_PUB_KEY_SIGNATURE, AUTH_DIRECTION_REMOTE);
1116             if (caCert == null) {
1117                 mTrustAnchor = null;
1118             } else {
1119                 // The name constraints extension, defined in RFC 5280, indicates a name space
1120                 // within which all subject names in subsequent certificates in a certification path
1121                 // MUST be located.
1122                 mTrustAnchor = new TrustAnchor(caCert, null /*nameConstraints*/);
1123 
1124                 // TODO: Investigate if we need to support the name constraints extension.
1125             }
1126         }
1127 
1128         /**
1129          * Constructs this object by deserializing a PersistableBundle
1130          *
1131          * @hide
1132          */
1133         @NonNull
fromPersistableBundle( @onNull PersistableBundle in)1134         public static IkeAuthDigitalSignRemoteConfig fromPersistableBundle(
1135                 @NonNull PersistableBundle in) {
1136             Objects.requireNonNull(in, "PersistableBundle is null");
1137 
1138             PersistableBundle trustCertBundle = in.getPersistableBundle(TRUST_CERT_KEY);
1139 
1140             X509Certificate caCert = null;
1141             if (trustCertBundle != null) {
1142                 byte[] encodedCert = PersistableBundleUtils.toByteArray(trustCertBundle);
1143                 caCert = certificateFromByteArray(encodedCert);
1144             }
1145 
1146             return new IkeAuthDigitalSignRemoteConfig(caCert);
1147         }
1148 
1149         /**
1150          * Serializes this object to a PersistableBundle
1151          *
1152          * @hide
1153          */
1154         @Override
1155         @NonNull
toPersistableBundle()1156         public PersistableBundle toPersistableBundle() {
1157             final PersistableBundle result = super.toPersistableBundle();
1158 
1159             try {
1160                 if (mTrustAnchor != null) {
1161                     result.putPersistableBundle(
1162                             TRUST_CERT_KEY,
1163                             PersistableBundleUtils.fromByteArray(
1164                                     mTrustAnchor.getTrustedCert().getEncoded()));
1165                 }
1166 
1167             } catch (CertificateEncodingException e) {
1168                 throw new IllegalArgumentException("Fail to encode the certificate");
1169             }
1170 
1171             return result;
1172         }
1173 
1174         /** Retrieves the provided CA certificate for validating the remote certificate(s) */
1175         @Nullable
getRemoteCaCert()1176         public X509Certificate getRemoteCaCert() {
1177             if (mTrustAnchor == null) return null;
1178             return mTrustAnchor.getTrustedCert();
1179         }
1180 
1181         @Override
hashCode()1182         public int hashCode() {
1183             // Use #getTrustedCert() because TrustAnchor does not override #hashCode()
1184             return Objects.hash(
1185                     super.hashCode(),
1186                     (mTrustAnchor == null) ? null : mTrustAnchor.getTrustedCert());
1187         }
1188 
1189         @Override
equals(Object o)1190         public boolean equals(Object o) {
1191             if (!super.equals(o) || !(o instanceof IkeAuthDigitalSignRemoteConfig)) {
1192                 return false;
1193             }
1194 
1195             IkeAuthDigitalSignRemoteConfig other = (IkeAuthDigitalSignRemoteConfig) o;
1196 
1197             if (mTrustAnchor == null && other.mTrustAnchor == null) {
1198                 return true;
1199             }
1200 
1201             // Compare #getTrustedCert() because TrustAnchor does not override #equals(Object)
1202             return mTrustAnchor != null
1203                     && other.mTrustAnchor != null
1204                     && Objects.equals(
1205                             mTrustAnchor.getTrustedCert(), other.mTrustAnchor.getTrustedCert());
1206         }
1207     }
1208 
1209     /**
1210      * This class represents the configuration to support IKEv2 public-key-signature-based
1211      * authentication of the local side.
1212      */
1213     public static class IkeAuthDigitalSignLocalConfig extends IkeAuthConfig {
1214         private static final String END_CERT_KEY = "mEndCert";
1215         private static final String INTERMEDIATE_CERTS_KEY = "mIntermediateCerts";
1216         private static final String PRIVATE_KEY_KEY = "mPrivateKey";
1217         /** @hide */
1218         @NonNull public final X509Certificate mEndCert;
1219 
1220         /** @hide */
1221         @NonNull public final List<X509Certificate> mIntermediateCerts;
1222 
1223         /** @hide */
1224         @NonNull public final PrivateKey mPrivateKey;
1225 
1226         /** @hide */
1227         @VisibleForTesting
IkeAuthDigitalSignLocalConfig( @onNull X509Certificate clientEndCert, @NonNull List<X509Certificate> clientIntermediateCerts, @NonNull PrivateKey privateKey)1228         IkeAuthDigitalSignLocalConfig(
1229                 @NonNull X509Certificate clientEndCert,
1230                 @NonNull List<X509Certificate> clientIntermediateCerts,
1231                 @NonNull PrivateKey privateKey) {
1232             super(IKE_AUTH_METHOD_PUB_KEY_SIGNATURE, AUTH_DIRECTION_LOCAL);
1233             mEndCert = clientEndCert;
1234             mIntermediateCerts = clientIntermediateCerts;
1235             mPrivateKey = privateKey;
1236         }
1237 
1238         /**
1239          * Constructs this object by deserializing a PersistableBundle
1240          *
1241          * @hide
1242          */
1243         @NonNull
fromPersistableBundle( @onNull PersistableBundle in)1244         public static IkeAuthDigitalSignLocalConfig fromPersistableBundle(
1245                 @NonNull PersistableBundle in) {
1246             Objects.requireNonNull(in, "PersistableBundle is null");
1247 
1248             PersistableBundle endCertBundle = in.getPersistableBundle(END_CERT_KEY);
1249             Objects.requireNonNull(endCertBundle, "End cert not provided");
1250             byte[] encodedCert = PersistableBundleUtils.toByteArray(endCertBundle);
1251             X509Certificate endCert = certificateFromByteArray(encodedCert);
1252 
1253             PersistableBundle certsBundle = in.getPersistableBundle(INTERMEDIATE_CERTS_KEY);
1254             Objects.requireNonNull(certsBundle, "Intermediate certs not provided");
1255             List<byte[]> encodedCertList =
1256                     PersistableBundleUtils.toList(certsBundle, PersistableBundleUtils::toByteArray);
1257             List<X509Certificate> certList = new ArrayList<>(encodedCertList.size());
1258             for (byte[] encoded : encodedCertList) {
1259                 certList.add(certificateFromByteArray(encoded));
1260             }
1261 
1262             PersistableBundle privateKeyBundle = in.getPersistableBundle(PRIVATE_KEY_KEY);
1263             Objects.requireNonNull(privateKeyBundle, "PrivateKey bundle is null");
1264             PrivateKey privateKey =
1265                     privateKeyFromByteArray(PersistableBundleUtils.toByteArray(privateKeyBundle));
1266             Objects.requireNonNull(privateKeyBundle, "PrivateKey is null");
1267 
1268             return new IkeAuthDigitalSignLocalConfig(endCert, certList, privateKey);
1269         }
1270 
1271         /**
1272          * Serializes this object to a PersistableBundle
1273          *
1274          * @hide
1275          */
1276         @Override
1277         @NonNull
toPersistableBundle()1278         public PersistableBundle toPersistableBundle() {
1279             final PersistableBundle result = super.toPersistableBundle();
1280 
1281             try {
1282                 result.putPersistableBundle(
1283                         END_CERT_KEY, PersistableBundleUtils.fromByteArray(mEndCert.getEncoded()));
1284 
1285                 List<byte[]> encodedCertList = new ArrayList<>(mIntermediateCerts.size());
1286                 for (X509Certificate cert : mIntermediateCerts) {
1287                     encodedCertList.add(cert.getEncoded());
1288                 }
1289                 PersistableBundle certsBundle =
1290                         PersistableBundleUtils.fromList(
1291                                 encodedCertList, PersistableBundleUtils::fromByteArray);
1292                 result.putPersistableBundle(INTERMEDIATE_CERTS_KEY, certsBundle);
1293             } catch (CertificateEncodingException e) {
1294                 throw new IllegalArgumentException("Fail to encode certificate");
1295             }
1296 
1297             // TODO: b/170670506 Consider putting PrivateKey in Android KeyStore
1298             result.putPersistableBundle(
1299                     PRIVATE_KEY_KEY,
1300                     PersistableBundleUtils.fromByteArray(mPrivateKey.getEncoded()));
1301 
1302             return result;
1303         }
1304 
1305         /** Retrieves the client end certificate */
1306         @NonNull
getClientEndCertificate()1307         public X509Certificate getClientEndCertificate() {
1308             return mEndCert;
1309         }
1310 
1311         /** Retrieves the intermediate certificates */
1312         @NonNull
getIntermediateCertificates()1313         public List<X509Certificate> getIntermediateCertificates() {
1314             return mIntermediateCerts;
1315         }
1316 
1317         /** Retrieves the private key */
1318         @NonNull
getPrivateKey()1319         public PrivateKey getPrivateKey() {
1320             return mPrivateKey;
1321         }
1322 
1323         @Override
hashCode()1324         public int hashCode() {
1325             return Objects.hash(super.hashCode(), mEndCert, mIntermediateCerts, mPrivateKey);
1326         }
1327 
1328         @Override
equals(Object o)1329         public boolean equals(Object o) {
1330             if (!super.equals(o) || !(o instanceof IkeAuthDigitalSignLocalConfig)) {
1331                 return false;
1332             }
1333 
1334             IkeAuthDigitalSignLocalConfig other = (IkeAuthDigitalSignLocalConfig) o;
1335 
1336             return mEndCert.equals(other.mEndCert)
1337                     && mIntermediateCerts.equals(other.mIntermediateCerts)
1338                     && mPrivateKey.equals(other.mPrivateKey);
1339         }
1340     }
1341 
1342     /**
1343      * This class represents the configuration to support EAP authentication of the local side.
1344      *
1345      * <p>@see {@link IkeSessionParams.Builder#setAuthEap(X509Certificate, EapSessionConfig)}
1346      */
1347     public static class IkeAuthEapConfig extends IkeAuthConfig {
1348         private static final String EAP_CONFIG_KEY = "mEapConfig";
1349 
1350         /** @hide */
1351         @NonNull public final EapSessionConfig mEapConfig;
1352 
1353         /** @hide */
1354         @VisibleForTesting
IkeAuthEapConfig(EapSessionConfig eapConfig)1355         IkeAuthEapConfig(EapSessionConfig eapConfig) {
1356             super(IKE_AUTH_METHOD_EAP, AUTH_DIRECTION_LOCAL);
1357 
1358             mEapConfig = eapConfig;
1359         }
1360 
1361         /**
1362          * Constructs this object by deserializing a PersistableBundle
1363          *
1364          * @hide
1365          */
1366         @NonNull
fromPersistableBundle(@onNull PersistableBundle in)1367         public static IkeAuthEapConfig fromPersistableBundle(@NonNull PersistableBundle in) {
1368             Objects.requireNonNull(in, "PersistableBundle null");
1369 
1370             PersistableBundle eapBundle = in.getPersistableBundle(EAP_CONFIG_KEY);
1371             Objects.requireNonNull(in, "EAP Config bundle is null");
1372 
1373             EapSessionConfig eapConfig = EapSessionConfig.fromPersistableBundle(eapBundle);
1374             Objects.requireNonNull(eapConfig, "EAP Config is null");
1375 
1376             return new IkeAuthEapConfig(eapConfig);
1377         }
1378 
1379         /**
1380          * Serializes this object to a PersistableBundle
1381          *
1382          * @hide
1383          */
1384         @Override
1385         @NonNull
toPersistableBundle()1386         public PersistableBundle toPersistableBundle() {
1387             final PersistableBundle result = super.toPersistableBundle();
1388             result.putPersistableBundle(EAP_CONFIG_KEY, mEapConfig.toPersistableBundle());
1389             return result;
1390         }
1391 
1392         /** Retrieves EAP configuration */
1393         @NonNull
getEapConfig()1394         public EapSessionConfig getEapConfig() {
1395             return mEapConfig;
1396         }
1397 
1398         @Override
hashCode()1399         public int hashCode() {
1400             return Objects.hash(super.hashCode(), mEapConfig);
1401         }
1402 
1403         @Override
equals(Object o)1404         public boolean equals(Object o) {
1405             if (!super.equals(o) || !(o instanceof IkeAuthEapConfig)) {
1406                 return false;
1407             }
1408 
1409             return mEapConfig.equals(((IkeAuthEapConfig) o).mEapConfig);
1410         }
1411     }
1412 
1413     /** This class can be used to incrementally construct a {@link IkeSessionParams}. */
1414     public static final class Builder {
1415         // This field has changed from @NonNull to @Nullable since Android S. It has to be @Nullable
1416         // because the new constructor #Builder() will not need and will not able to get a
1417         // ConnectivityManager instance anymore. Making it @Nullable does not break the backwards
1418         // compatibility because if apps use the old constructor #Builder(Context), the Builder and
1419         // the IkeSessionParams built from it will still work in the old way. @see #Builder(Context)
1420         @Nullable private ConnectivityManager mConnectivityManager;
1421 
1422         @NonNull private final List<IkeSaProposal> mSaProposalList = new LinkedList<>();
1423         @NonNull private final List<IkeConfigAttribute> mConfigRequestList = new ArrayList<>();
1424 
1425         @NonNull
1426         private int[] mRetransTimeoutMsList =
1427                 Arrays.copyOf(
1428                         IKE_RETRANS_TIMEOUT_MS_LIST_DEFAULT,
1429                         IKE_RETRANS_TIMEOUT_MS_LIST_DEFAULT.length);
1430 
1431         @NonNull private String mServerHostname;
1432         @Nullable private Network mCallerConfiguredNetwork;
1433 
1434         @Nullable private IkeIdentification mLocalIdentification;
1435         @Nullable private IkeIdentification mRemoteIdentification;
1436 
1437         @Nullable private IkeAuthConfig mLocalAuthConfig;
1438         @Nullable private IkeAuthConfig mRemoteAuthConfig;
1439 
1440         @Nullable private Ike3gppExtension mIke3gppExtension;
1441 
1442         private long mIkeOptions = 0;
1443 
1444         private int mHardLifetimeSec = IKE_HARD_LIFETIME_SEC_DEFAULT;
1445         private int mSoftLifetimeSec = IKE_SOFT_LIFETIME_SEC_DEFAULT;
1446 
1447         private int mDpdDelaySec = IKE_DPD_DELAY_SEC_DEFAULT;
1448         private int mNattKeepaliveDelaySec = IKE_NATT_KEEPALIVE_DELAY_SEC_DEFAULT;
1449         private int mDscp = DSCP_DEFAULT;
1450         private final boolean mIsIkeFragmentationSupported = true;
1451 
1452         @EspIpVersion private int mIpVersion = ESP_IP_VERSION_AUTO;
1453         @EspEncapType private int mEncapType = ESP_ENCAP_TYPE_AUTO;
1454 
1455         /**
1456          * Construct Builder
1457          *
1458          * <p>This constructor is deprecated since Android S. Apps that use this constructor can
1459          * still expect {@link #build()} to throw if no configured or default network was found. But
1460          * apps that use {@link #Builder()} MUST NOT expect that behavior anymore.
1461          *
1462          * <p>For a caller that used this constructor and did not set any Network, {@link
1463          * IkeSessionParams#getNetwork()} will return the default Network resolved in {@link
1464          * IkeSessionParams.Builder#build()}. This return value is only informational because if
1465          * MOBIKE is enabled, IKE Session may switch to a different default Network.
1466          *
1467          * @param context a valid {@link Context} instance.
1468          * @deprecated Callers should use {@link #Builder()}.This method is deprecated because it is
1469          *     unnecessary to try resolving a default network or to validate network is connected
1470          *     before {@link IkeSession} starts the setup process.
1471          * @hide
1472          */
1473         @Deprecated
1474         @SystemApi
Builder(@onNull Context context)1475         public Builder(@NonNull Context context) {
1476             this((ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE));
1477         }
1478 
1479         /**
1480          * Construct Builder
1481          */
Builder()1482         public Builder() {}
1483 
1484         /** @hide */
1485         // TODO: b/178389011 This constructor should be removed when #Builder(Context) can be safely
1486         // removed. See #Builder(Context) for reasons.
1487         @VisibleForTesting
Builder(ConnectivityManager connectManager)1488         public Builder(ConnectivityManager connectManager) {
1489             mConnectivityManager = connectManager;
1490         }
1491 
1492         /**
1493          * Construct Builder from the {@link IkeSessionParams} object.
1494          *
1495          * @param ikeSessionParams the object this Builder will be constructed with.
1496          */
Builder(@onNull IkeSessionParams ikeSessionParams)1497         public Builder(@NonNull IkeSessionParams ikeSessionParams) {
1498             mSaProposalList.addAll(ikeSessionParams.getSaProposals());
1499             mConfigRequestList.addAll(Arrays.asList(ikeSessionParams.mConfigRequests));
1500 
1501             int[] retransmissionTimeouts = ikeSessionParams.getRetransmissionTimeoutsMillis();
1502             mRetransTimeoutMsList =
1503                     Arrays.copyOf(retransmissionTimeouts, retransmissionTimeouts.length);
1504 
1505             mServerHostname = ikeSessionParams.getServerHostname();
1506             mCallerConfiguredNetwork = ikeSessionParams.getConfiguredNetwork();
1507             mLocalIdentification = ikeSessionParams.getLocalIdentification();
1508             mRemoteIdentification = ikeSessionParams.getRemoteIdentification();
1509             mLocalAuthConfig = ikeSessionParams.getLocalAuthConfig();
1510             mRemoteAuthConfig = ikeSessionParams.getRemoteAuthConfig();
1511 
1512             mIke3gppExtension = ikeSessionParams.getIke3gppExtension();
1513 
1514             mHardLifetimeSec = ikeSessionParams.getHardLifetimeSeconds();
1515             mSoftLifetimeSec = ikeSessionParams.getSoftLifetimeSeconds();
1516             mDpdDelaySec = ikeSessionParams.getDpdDelaySeconds();
1517             mNattKeepaliveDelaySec = ikeSessionParams.getNattKeepAliveDelaySeconds();
1518             mDscp = ikeSessionParams.getDscp();
1519             mIpVersion = ikeSessionParams.getIpVersion();
1520             mEncapType = ikeSessionParams.getEncapType();
1521 
1522             mIkeOptions = ikeSessionParams.mIkeOptions;
1523 
1524             if (!ikeSessionParams.mIsIkeFragmentationSupported) {
1525                 throw new IllegalStateException(
1526                         "mIsIkeFragmentationSupported should never be false");
1527             }
1528         }
1529 
1530         /**
1531          * Sets the server hostname for the {@link IkeSessionParams} being built.
1532          *
1533          * @param serverHostname the hostname of the IKE server, such as "ike.android.com".
1534          * @return Builder this, to facilitate chaining.
1535          */
1536         @NonNull
setServerHostname(@onNull String serverHostname)1537         public Builder setServerHostname(@NonNull String serverHostname) {
1538             Objects.requireNonNull(serverHostname, "Required argument not provided");
1539 
1540             mServerHostname = serverHostname;
1541             return this;
1542         }
1543 
1544         /**
1545          * Sets the {@link Network} for the {@link IkeSessionParams} being built.
1546          *
1547          * <p>If no {@link Network} is provided, the default Network (as per {@link
1548          * ConnectivityManager#getActiveNetwork()}) will be used when constructing an {@link
1549          * IkeSession}.
1550          *
1551          * @param network the {@link Network} that IKE Session will use, or {@code null} to clear
1552          *     the previously set {@link Network}
1553          * @return Builder this, to facilitate chaining.
1554          */
1555         @NonNull
setNetwork(@ullable Network network)1556         public Builder setNetwork(@Nullable Network network) {
1557             mCallerConfiguredNetwork = network;
1558             return this;
1559         }
1560 
1561         /**
1562          * Sets local IKE identification for the {@link IkeSessionParams} being built.
1563          *
1564          * <p>It is not allowed to use KEY ID together with digital-signature-based authentication
1565          * as per RFC 7296.
1566          *
1567          * @param identification the local IKE identification.
1568          * @return Builder this, to facilitate chaining.
1569          */
1570         @NonNull
setLocalIdentification(@onNull IkeIdentification identification)1571         public Builder setLocalIdentification(@NonNull IkeIdentification identification) {
1572             if (identification == null) {
1573                 throw new NullPointerException("Required argument not provided");
1574             }
1575 
1576             mLocalIdentification = identification;
1577             return this;
1578         }
1579 
1580         /**
1581          * Sets remote IKE identification for the {@link IkeSessionParams} being built.
1582          *
1583          * @param identification the remote IKE identification.
1584          * @return Builder this, to facilitate chaining.
1585          */
1586         @NonNull
setRemoteIdentification(@onNull IkeIdentification identification)1587         public Builder setRemoteIdentification(@NonNull IkeIdentification identification) {
1588             if (identification == null) {
1589                 throw new NullPointerException("Required argument not provided");
1590             }
1591 
1592             mRemoteIdentification = identification;
1593             return this;
1594         }
1595 
1596         /**
1597          * Adds an IKE SA proposal to the {@link IkeSessionParams} being built.
1598          *
1599          * @param proposal IKE SA proposal.
1600          * @return Builder this, to facilitate chaining.
1601          * @deprecated Callers should use {@link #addIkeSaProposal(IkeSaProposal)}. This method is
1602          *     deprecated because its name does not match the input type.
1603          * @hide
1604          */
1605         @Deprecated
1606         @SystemApi
1607         @NonNull
addSaProposal(@onNull IkeSaProposal proposal)1608         public Builder addSaProposal(@NonNull IkeSaProposal proposal) {
1609             return addIkeSaProposal(proposal);
1610         }
1611 
1612         /**
1613          * Adds an IKE SA proposal to the {@link IkeSessionParams} being built.
1614          *
1615          * @param proposal IKE SA proposal.
1616          * @return Builder this, to facilitate chaining.
1617          */
1618         @NonNull
addIkeSaProposal(@onNull IkeSaProposal proposal)1619         public Builder addIkeSaProposal(@NonNull IkeSaProposal proposal) {
1620             if (proposal == null) {
1621                 throw new NullPointerException("Required argument not provided");
1622             }
1623 
1624             if (proposal.getProtocolId() != IkePayload.PROTOCOL_ID_IKE) {
1625                 throw new IllegalArgumentException(
1626                         "Expected IKE SA Proposal but received Child SA proposal");
1627             }
1628             mSaProposalList.add(proposal);
1629             return this;
1630         }
1631 
1632         /**
1633          * Configures authentication for IKE Session. Internal use only.
1634          *
1635          * @hide
1636          */
1637         @NonNull
setAuth(IkeAuthConfig local, IkeAuthConfig remote)1638         private Builder setAuth(IkeAuthConfig local, IkeAuthConfig remote) {
1639             mLocalAuthConfig = local;
1640             mRemoteAuthConfig = remote;
1641             return this;
1642         }
1643 
1644         /**
1645          * Configures the {@link IkeSession} to use pre-shared-key-based authentication.
1646          *
1647          * <p>Both client and server MUST be authenticated using the provided shared key. IKE
1648          * authentication will fail if the remote peer tries to use other authentication methods.
1649          *
1650          * <p>Callers MUST declare only one authentication method. Calling this function will
1651          * override the previously set authentication configuration.
1652          *
1653          * <p>Callers SHOULD NOT use this if any other authentication methods can be used; PSK-based
1654          * authentication is generally considered insecure.
1655          *
1656          * @param sharedKey the shared key.
1657          * @return Builder this, to facilitate chaining.
1658          */
1659         // #getLocalAuthConfig and #getRemoveAuthConfig are defined to retrieve
1660         // authentication configurations
1661         @SuppressLint("MissingGetterMatchingBuilder")
1662         @NonNull
setAuthPsk(@onNull byte[] sharedKey)1663         public Builder setAuthPsk(@NonNull byte[] sharedKey) {
1664             if (sharedKey == null) {
1665                 throw new NullPointerException("Required argument not provided");
1666             }
1667 
1668             return setAuth(new IkeAuthPskConfig(sharedKey), new IkeAuthPskConfig(sharedKey));
1669         }
1670 
1671         /**
1672          * Configures the {@link IkeSession} to use EAP authentication.
1673          *
1674          * <p>Not all EAP methods provide mutual authentication. As such EAP MUST be used in
1675          * conjunction with a public-key-signature-based authentication of the remote server, unless
1676          * EAP-Only authentication is enabled.
1677          *
1678          * <p>Callers may enable EAP-Only authentication by setting {@link
1679          * #IKE_OPTION_EAP_ONLY_AUTH}, which will make IKE library request the remote to use
1680          * EAP-Only authentication. The remote may opt to reject the request, at which point the
1681          * received certificates and authentication payload WILL be validated with the provided root
1682          * CA or system's truststore as usual. Only safe EAP methods as listed in RFC 5998 will be
1683          * accepted for EAP-Only authentication.
1684          *
1685          * <p>If {@link #IKE_OPTION_EAP_ONLY_AUTH} is set, callers MUST configure EAP as the
1686          * authentication method and all EAP methods set in EAP Session configuration MUST be safe
1687          * methods that are accepted for EAP-Only authentication. Otherwise callers will get an
1688          * exception when building the {@link IkeSessionParams}
1689          *
1690          * <p>Callers MUST declare only one authentication method. Calling this function will
1691          * override the previously set authentication configuration.
1692          *
1693          * @see <a href="https://tools.ietf.org/html/rfc5280">RFC 5280, Internet X.509 Public Key
1694          *     Infrastructure Certificate and Certificate Revocation List (CRL) Profile</a>
1695          * @see <a href="https://tools.ietf.org/html/rfc5998">RFC 5998, An Extension for EAP-Only
1696          *     Authentication in IKEv2</a>
1697          * @param serverCaCert the CA certificate for validating the received server certificate(s).
1698          *     If a certificate is provided, it MUST be the root CA used by the server, or
1699          *     authentication will fail. If no certificate is provided, any root CA in the system's
1700          *     truststore is considered acceptable.
1701          * @return Builder this, to facilitate chaining.
1702          */
1703         // TODO(b/151667921): Consider also supporting configuring EAP method that is not accepted
1704         // by EAP-Only when {@link #IKE_OPTION_EAP_ONLY_AUTH} is set
1705         // MissingGetterMatchingBuilder: #getLocalAuthConfig and #getRemoveAuthConfig are defined to
1706         // retrieve authentication configurations
1707         @SuppressLint("MissingGetterMatchingBuilder")
1708         @NonNull
setAuthEap( @ullable X509Certificate serverCaCert, @NonNull EapSessionConfig eapConfig)1709         public Builder setAuthEap(
1710                 @Nullable X509Certificate serverCaCert, @NonNull EapSessionConfig eapConfig) {
1711             if (eapConfig == null) {
1712                 throw new NullPointerException("Required argument not provided");
1713             }
1714 
1715             return setAuth(
1716                     new IkeAuthEapConfig(eapConfig),
1717                     new IkeAuthDigitalSignRemoteConfig(serverCaCert));
1718         }
1719 
1720         /**
1721          * Configures the {@link IkeSession} to use public-key-signature-based authentication.
1722          *
1723          * <p>The public key included by the client end certificate and the private key used for
1724          * signing MUST be a matching key pair.
1725          *
1726          * <p>The IKE library will use the strongest signature algorithm supported by both sides.
1727          *
1728          * <p>Currenly only RSA digital signature is supported.
1729          *
1730          * @param serverCaCert the CA certificate for validating the received server certificate(s).
1731          *     If a certificate is provided, it MUST be the root CA used by the server, or
1732          *     authentication will fail. If no certificate is provided, any root CA in the system's
1733          *     truststore is considered acceptable.
1734          * @param clientEndCert the end certificate for remote server to verify the locally
1735          *     generated signature.
1736          * @param clientPrivateKey private key to generate outbound digital signature. The {@link
1737          *     PrivateKey} MUST be an instance of {@link RSAKey}.
1738          * @return Builder this, to facilitate chaining.
1739          */
1740         // #getLocalAuthConfig and #getRemoveAuthConfig are defined to retrieve
1741         // authentication configurations
1742         @SuppressLint("MissingGetterMatchingBuilder")
1743         @NonNull
setAuthDigitalSignature( @ullable X509Certificate serverCaCert, @NonNull X509Certificate clientEndCert, @NonNull PrivateKey clientPrivateKey)1744         public Builder setAuthDigitalSignature(
1745                 @Nullable X509Certificate serverCaCert,
1746                 @NonNull X509Certificate clientEndCert,
1747                 @NonNull PrivateKey clientPrivateKey) {
1748             return setAuthDigitalSignature(
1749                     serverCaCert,
1750                     clientEndCert,
1751                     new LinkedList<X509Certificate>(),
1752                     clientPrivateKey);
1753         }
1754 
1755         /**
1756          * Configures the {@link IkeSession} to use public-key-signature-based authentication.
1757          *
1758          * <p>The public key included by the client end certificate and the private key used for
1759          * signing MUST be a matching key pair.
1760          *
1761          * <p>The IKE library will use the strongest signature algorithm supported by both sides.
1762          *
1763          * <p>Currenly only RSA digital signature is supported.
1764          *
1765          * @param serverCaCert the CA certificate for validating the received server certificate(s).
1766          *     If a null value is provided, IKE library will try all default CA certificates stored
1767          *     in Android system to do the validation. Otherwise, it will only use the provided CA
1768          *     certificate.
1769          * @param clientEndCert the end certificate for remote server to verify locally generated
1770          *     signature.
1771          * @param clientIntermediateCerts intermediate certificates for the remote server to
1772          *     validate the end certificate.
1773          * @param clientPrivateKey private key to generate outbound digital signature. The {@link
1774          *     PrivateKey} MUST be an instance of {@link RSAKey}.
1775          * @return Builder this, to facilitate chaining.
1776          */
1777         // #getLocalAuthConfig and #getRemoveAuthConfig are defined to retrieve
1778         // authentication configurations
1779         @SuppressLint("MissingGetterMatchingBuilder")
1780         @NonNull
setAuthDigitalSignature( @ullable X509Certificate serverCaCert, @NonNull X509Certificate clientEndCert, @NonNull List<X509Certificate> clientIntermediateCerts, @NonNull PrivateKey clientPrivateKey)1781         public Builder setAuthDigitalSignature(
1782                 @Nullable X509Certificate serverCaCert,
1783                 @NonNull X509Certificate clientEndCert,
1784                 @NonNull List<X509Certificate> clientIntermediateCerts,
1785                 @NonNull PrivateKey clientPrivateKey) {
1786             if (clientEndCert == null
1787                     || clientIntermediateCerts == null
1788                     || clientPrivateKey == null) {
1789                 throw new NullPointerException("Required argument not provided");
1790             }
1791 
1792             if (!(clientPrivateKey instanceof RSAKey)) {
1793                 throw new IllegalArgumentException("Unsupported private key type");
1794             }
1795 
1796             IkeAuthConfig localConfig =
1797                     new IkeAuthDigitalSignLocalConfig(
1798                             clientEndCert, clientIntermediateCerts, clientPrivateKey);
1799             IkeAuthConfig remoteConfig = new IkeAuthDigitalSignRemoteConfig(serverCaCert);
1800 
1801             return setAuth(localConfig, remoteConfig);
1802         }
1803 
1804         /**
1805          * Adds a configuration request. Internal use only.
1806          *
1807          * @hide
1808          */
1809         @NonNull
addConfigRequest(IkeConfigAttribute configReq)1810         private Builder addConfigRequest(IkeConfigAttribute configReq) {
1811             mConfigRequestList.add(configReq);
1812             return this;
1813         }
1814 
1815         /**
1816          * Adds a specific internal P_CSCF server request to the {@link IkeSessionParams} being
1817          * built.
1818          *
1819          * @param address the requested P_CSCF address.
1820          * @return Builder this, to facilitate chaining.
1821          * @hide
1822          */
1823         // #getConfigurationRequests is defined to retrieve PCSCF server requests
1824         @SuppressLint("MissingGetterMatchingBuilder")
1825         @SystemApi
1826         @NonNull
addPcscfServerRequest(@onNull InetAddress address)1827         public Builder addPcscfServerRequest(@NonNull InetAddress address) {
1828             if (address == null) {
1829                 throw new NullPointerException("Required argument not provided");
1830             }
1831 
1832             if (address instanceof Inet4Address) {
1833                 return addConfigRequest(new ConfigAttributeIpv4Pcscf((Inet4Address) address));
1834             } else if (address instanceof Inet6Address) {
1835                 return addConfigRequest(new ConfigAttributeIpv6Pcscf((Inet6Address) address));
1836             } else {
1837                 throw new IllegalArgumentException("Invalid address family");
1838             }
1839         }
1840 
1841         /**
1842          * Adds a internal P_CSCF server request to the {@link IkeSessionParams} being built.
1843          *
1844          * @param addressFamily the address family. Only {@code AF_INET} and {@code AF_INET6} are
1845          *     allowed.
1846          * @return Builder this, to facilitate chaining.
1847          * @hide
1848          */
1849         // #getConfigurationRequests is defined to retrieve PCSCF server requests
1850         @SuppressLint("MissingGetterMatchingBuilder")
1851         @SystemApi
1852         @NonNull
addPcscfServerRequest(int addressFamily)1853         public Builder addPcscfServerRequest(int addressFamily) {
1854             if (addressFamily == AF_INET) {
1855                 return addConfigRequest(new ConfigAttributeIpv4Pcscf());
1856             } else if (addressFamily == AF_INET6) {
1857                 return addConfigRequest(new ConfigAttributeIpv6Pcscf());
1858             } else {
1859                 throw new IllegalArgumentException("Invalid address family: " + addressFamily);
1860             }
1861         }
1862 
1863         /**
1864          * Sets hard and soft lifetimes.
1865          *
1866          * <p>Lifetimes will not be negotiated with the remote IKE server.
1867          *
1868          * @param hardLifetimeSeconds number of seconds after which IKE SA will expire. Defaults to
1869          *     14400 seconds (4 hours). MUST be a value from 300 seconds (5 minutes) to 86400
1870          *     seconds (24 hours), inclusive.
1871          * @param softLifetimeSeconds number of seconds after which IKE SA will request rekey.
1872          *     Defaults to 7200 seconds (2 hours). MUST be at least 120 seconds (2 minutes), and at
1873          *     least 60 seconds (1 minute) shorter than the hard lifetime.
1874          * @return Builder this, to facilitate chaining.
1875          */
1876         // #getHardLifetimeSeconds and #getSoftLifetimeSeconds are defined for callers to retrieve
1877         // the lifetimes
1878         @SuppressLint("MissingGetterMatchingBuilder")
1879         @NonNull
setLifetimeSeconds( @ntRangefrom = IKE_HARD_LIFETIME_SEC_MINIMUM, to = IKE_HARD_LIFETIME_SEC_MAXIMUM) int hardLifetimeSeconds, @IntRange(from = IKE_SOFT_LIFETIME_SEC_MINIMUM, to = IKE_HARD_LIFETIME_SEC_MAXIMUM) int softLifetimeSeconds)1880         public Builder setLifetimeSeconds(
1881                 @IntRange(from = IKE_HARD_LIFETIME_SEC_MINIMUM, to = IKE_HARD_LIFETIME_SEC_MAXIMUM)
1882                         int hardLifetimeSeconds,
1883                 @IntRange(from = IKE_SOFT_LIFETIME_SEC_MINIMUM, to = IKE_HARD_LIFETIME_SEC_MAXIMUM)
1884                         int softLifetimeSeconds) {
1885             if (hardLifetimeSeconds < IKE_HARD_LIFETIME_SEC_MINIMUM
1886                     || hardLifetimeSeconds > IKE_HARD_LIFETIME_SEC_MAXIMUM
1887                     || softLifetimeSeconds < IKE_SOFT_LIFETIME_SEC_MINIMUM
1888                     || hardLifetimeSeconds - softLifetimeSeconds
1889                             < IKE_LIFETIME_MARGIN_SEC_MINIMUM) {
1890                 throw new IllegalArgumentException("Invalid lifetime value");
1891             }
1892 
1893             mHardLifetimeSec = hardLifetimeSeconds;
1894             mSoftLifetimeSec = softLifetimeSeconds;
1895             return this;
1896         }
1897 
1898         /**
1899          * Sets the Dead Peer Detection(DPD) delay in seconds.
1900          *
1901          * @param dpdDelaySeconds number of seconds after which IKE SA will initiate DPD if no
1902          *     inbound cryptographically protected IKE message was received. Defaults to 120
1903          *     seconds. MUST be a value greater than or equal to than 20 seconds. Setting the value
1904          *     to {@link java.lang.Integer#MAX_VALUE} will disable DPD.
1905          * @return Builder this, to facilitate chaining.
1906          */
1907         // TODO: b/240206579 Align the @IntRange with the implementation.
1908         @NonNull
setDpdDelaySeconds( @ntRangefrom = IKE_DPD_DELAY_SEC_MIN, to = IKE_DPD_DELAY_SEC_MAX) int dpdDelaySeconds)1909         public Builder setDpdDelaySeconds(
1910                 @IntRange(from = IKE_DPD_DELAY_SEC_MIN, to = IKE_DPD_DELAY_SEC_MAX)
1911                         int dpdDelaySeconds) {
1912             if (dpdDelaySeconds < IKE_DPD_DELAY_SEC_MIN) {
1913                 throw new IllegalArgumentException("Invalid DPD delay value");
1914             }
1915             mDpdDelaySec = dpdDelaySeconds;
1916             return this;
1917         }
1918 
1919         /**
1920          * Sets the Network Address Translation Traversal (NATT) keepalive delay in seconds.
1921          *
1922          * @param nattKeepaliveDelaySeconds number of seconds between keepalive packet
1923          *     transmissions. Defaults to 10 seconds. MUST be a value from 10 seconds to 3600
1924          *     seconds, inclusive.
1925          * @return Builder this, to facilitate chaining.
1926          */
1927         @NonNull
setNattKeepAliveDelaySeconds( @ntRange from = IKE_NATT_KEEPALIVE_DELAY_SEC_MIN, to = IKE_NATT_KEEPALIVE_DELAY_SEC_MAX) int nattKeepaliveDelaySeconds)1928         public Builder setNattKeepAliveDelaySeconds(
1929                 @IntRange(
1930                                 from = IKE_NATT_KEEPALIVE_DELAY_SEC_MIN,
1931                                 to = IKE_NATT_KEEPALIVE_DELAY_SEC_MAX)
1932                         int nattKeepaliveDelaySeconds) {
1933             if (nattKeepaliveDelaySeconds < IKE_NATT_KEEPALIVE_DELAY_SEC_MIN
1934                     || nattKeepaliveDelaySeconds > IKE_NATT_KEEPALIVE_DELAY_SEC_MAX) {
1935                 throw new IllegalArgumentException("Invalid NATT keepalive delay value");
1936             }
1937             mNattKeepaliveDelaySec = nattKeepaliveDelaySeconds;
1938             return this;
1939         }
1940 
1941         /**
1942          * Sets the DSCP field of the IKE packets.
1943          *
1944          * <p>Differentiated services code point (DSCP) is a 6-bit field in the IP header that is
1945          * used for packet classification and prioritization. The DSCP field is encoded in the 6
1946          * higher order bits of the Type of Service (ToS) in IPv4 header, or the traffic class (TC)
1947          * field in IPv6 header.
1948          *
1949          * <p>Any 6-bit values (0 to 63) are acceptable, whether IANA-defined, or
1950          * implementation-specific values.
1951          *
1952          * @see <a href="https://tools.ietf.org/html/rfc2474">RFC 2474, Definition of the
1953          *     Differentiated Services Field (DS Field) in the IPv4 and IPv6 Headers</a>
1954          * @see <a href="https://www.iana.org/assignments/dscp-registry/dscp-registry.xhtml">
1955          *     Differentiated Services Field Codepoints (DSCP)</a>
1956          * @param dscp the dscp value. Defaults to 0.
1957          * @return Builder this, to facilitate chaining.
1958          * @hide
1959          */
1960         @SystemApi
1961         @NonNull
setDscp(@ntRangefrom = DSCP_MIN, to = DSCP_MAX) int dscp)1962         public Builder setDscp(@IntRange(from = DSCP_MIN, to = DSCP_MAX) int dscp) {
1963             if (dscp < DSCP_MIN || dscp > DSCP_MAX) {
1964                 throw new IllegalArgumentException("Invalid DSCP value");
1965             }
1966             mDscp = dscp;
1967             return this;
1968         }
1969 
1970         /**
1971          * Sets the IP version to use for ESP packets.
1972          *
1973          * @param ipVersion the IP version to use.
1974          * @return the {@code Builder} to facilitate chaining.
1975          * @hide
1976          */
1977         @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES)
1978         @NonNull
setIpVersion(@spIpVersion int ipVersion)1979         public Builder setIpVersion(@EspIpVersion int ipVersion) {
1980             if (ESP_IP_VERSION_AUTO != ipVersion
1981                     && ESP_IP_VERSION_IPV4 != ipVersion
1982                     && ESP_IP_VERSION_IPV6 != ipVersion) {
1983                 throw new IllegalArgumentException("Invalid IP version : " + ipVersion);
1984             }
1985             mIpVersion = ipVersion;
1986             return this;
1987         }
1988 
1989         /**
1990          * Sets the encapsulation type to use for ESP packets.
1991          *
1992          * @param encapType the IP version to use.
1993          * @return the {@code Builder} to facilitate chaining.
1994          * @hide
1995          */
1996         @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES)
1997         @NonNull
setEncapType(@spEncapType int encapType)1998         public Builder setEncapType(@EspEncapType int encapType) {
1999             if (ESP_ENCAP_TYPE_AUTO != encapType
2000                     && ESP_ENCAP_TYPE_NONE != encapType
2001                     && ESP_ENCAP_TYPE_UDP != encapType) {
2002                 throw new IllegalArgumentException("Invalid encap type : " + encapType);
2003             }
2004             mEncapType = encapType;
2005             return this;
2006         }
2007 
2008         /**
2009          * Sets the retransmission timeout list in milliseconds.
2010          *
2011          * <p>Configures the retransmission by providing an array of relative retransmission
2012          * timeouts in milliseconds. After sending out a request and before receiving the response,
2013          * the IKE Session will iterate through the array and wait for the relative timeout before
2014          * the next retry. If the last timeout is exceeded, the IKE Session will be terminated.
2015          *
2016          * <p>Each element in the array MUST be a value from 500 ms to 1800000 ms (30 minutes). The
2017          * length of the array MUST NOT exceed 10. This retransmission timeout list defaults to
2018          * {0.5s, 1s, 2s, 4s, 8s}
2019          *
2020          * @param retransTimeoutMillisList the array of relative retransmission timeout in
2021          *     milliseconds.
2022          * @return Builder this, to facilitate chaining.
2023          */
2024         @NonNull
setRetransmissionTimeoutsMillis(@onNull int[] retransTimeoutMillisList)2025         public Builder setRetransmissionTimeoutsMillis(@NonNull int[] retransTimeoutMillisList) {
2026             boolean isValid = true;
2027             if (retransTimeoutMillisList == null
2028                     || retransTimeoutMillisList.length == 0
2029                     || retransTimeoutMillisList.length > IKE_RETRANS_MAX_ATTEMPTS_MAX) {
2030                 isValid = false;
2031             }
2032             for (int t : retransTimeoutMillisList) {
2033                 if (t < IKE_RETRANS_TIMEOUT_MS_MIN || t > IKE_RETRANS_TIMEOUT_MS_MAX) {
2034                     isValid = false;
2035                 }
2036             }
2037             if (!isValid) throw new IllegalArgumentException("Invalid retransmission timeout list");
2038 
2039             mRetransTimeoutMsList = retransTimeoutMillisList;
2040             return this;
2041         }
2042 
2043         /**
2044          * Sets the parameters to be used for 3GPP-specific behavior during the IKE Session.
2045          *
2046          * <p>Setting the Ike3gppExtension also enables support for non-configurable payloads, such
2047          * as the Notify - BACKOFF_TIMER payload.
2048          *
2049          * @see 3GPP ETSI TS 24.302: Access to the 3GPP Evolved Packet Core (EPC) via non-3GPP
2050          *     access networks
2051          * @param ike3gppExtension the Ike3gppExtension to use for this IKE Session.
2052          * @return Builder this, to facilitate chaining.
2053          * @hide
2054          */
2055         @SystemApi
2056         @NonNull
setIke3gppExtension(@onNull Ike3gppExtension ike3gppExtension)2057         public Builder setIke3gppExtension(@NonNull Ike3gppExtension ike3gppExtension) {
2058             Objects.requireNonNull(ike3gppExtension, "ike3gppExtension must not be null");
2059 
2060             mIke3gppExtension = ike3gppExtension;
2061             return this;
2062         }
2063 
2064         /**
2065          * Sets the specified IKE Option as enabled.
2066          *
2067          * @param ikeOption the option to be enabled.
2068          * @return Builder this, to facilitate chaining.
2069          * @throws IllegalArgumentException if the provided option is invalid.
2070          */
2071         // Use #hasIkeOption instead of @getIkeOptions because #hasIkeOption allows callers to check
2072         // the presence of one IKE option more easily
2073         @SuppressLint("MissingGetterMatchingBuilder")
2074         @NonNull
addIkeOption(@keOption int ikeOption)2075         public Builder addIkeOption(@IkeOption int ikeOption) {
2076             return addIkeOptionInternal(ikeOption);
2077         }
2078 
2079         /** @hide */
2080         @NonNull
addIkeOptionInternal(@keOption int ikeOption)2081         public Builder addIkeOptionInternal(@IkeOption int ikeOption) {
2082             validateIkeOptionOrThrow(ikeOption);
2083             if (ikeOption == IKE_OPTION_MOBIKE || ikeOption == IKE_OPTION_REKEY_MOBILITY) {
2084                 if (!SdkLevel.isAtLeastS()) {
2085                     throw new UnsupportedOperationException("Mobility only supported for S/S+");
2086                 } else if (!SdkLevel.isAtLeastT() && ikeOption == IKE_OPTION_MOBIKE) {
2087                     // Automatically enable IKE_OPTION_REKEY_MOBILITY if S <= SDK < T for
2088                     // compatibility
2089                     mIkeOptions |= getOptionBitValue(IKE_OPTION_REKEY_MOBILITY);
2090                 }
2091             }
2092 
2093             mIkeOptions |= getOptionBitValue(ikeOption);
2094             return this;
2095         }
2096 
2097         /**
2098          * Resets (disables) the specified IKE Option.
2099          *
2100          * @param ikeOption the option to be disabled.
2101          * @return Builder this, to facilitate chaining.
2102          * @throws IllegalArgumentException if the provided option is invalid.
2103          */
2104         // Use #removeIkeOption instead of #clearIkeOption because "clear" sounds indicating
2105         // clearing all enabled IKE options
2106         @SuppressLint("BuilderSetStyle")
2107         @NonNull
removeIkeOption(@keOption int ikeOption)2108         public Builder removeIkeOption(@IkeOption int ikeOption) {
2109             validateIkeOptionOrThrow(ikeOption);
2110             mIkeOptions &= ~getOptionBitValue(ikeOption);
2111             return this;
2112         }
2113 
2114         /**
2115          * Validates and builds the {@link IkeSessionParams}.
2116          *
2117          * @return IkeSessionParams the validated IkeSessionParams.
2118          */
2119         @NonNull
build()2120         public IkeSessionParams build() {
2121             if (mSaProposalList.isEmpty()) {
2122                 throw new IllegalArgumentException("IKE SA proposal not found");
2123             }
2124 
2125             // TODO: b/178389011 This code block should be removed when
2126             // IkeSessionParams#getNetwork() and #Builder(Context) can be safely removed. This block
2127             // makes sure if the Builder is constructed with the deprecated constructor
2128             // #Builder(Context), #build() still works in the same way and will throw exception when
2129             // there is no configured or default network.
2130             Network defaultOrConfiguredNetwork = mCallerConfiguredNetwork;
2131             if (mConnectivityManager != null && defaultOrConfiguredNetwork == null) {
2132                 defaultOrConfiguredNetwork = mConnectivityManager.getActiveNetwork();
2133                 if (defaultOrConfiguredNetwork == null) {
2134                     throw new IllegalArgumentException("Network not found");
2135                 }
2136             }
2137 
2138             if (mServerHostname == null
2139                     || mLocalIdentification == null
2140                     || mRemoteIdentification == null
2141                     || mLocalAuthConfig == null
2142                     || mRemoteAuthConfig == null) {
2143                 throw new IllegalArgumentException("Necessary parameter missing.");
2144             }
2145 
2146             if ((mIkeOptions & getOptionBitValue(IKE_OPTION_EAP_ONLY_AUTH)) != 0) {
2147                 if (!(mLocalAuthConfig instanceof IkeAuthEapConfig)) {
2148                     throw new IllegalArgumentException(
2149                             "If IKE_OPTION_EAP_ONLY_AUTH is set,"
2150                                     + " eap authentication needs to be configured.");
2151                 }
2152 
2153                 IkeAuthEapConfig ikeAuthEapConfig = (IkeAuthEapConfig) mLocalAuthConfig;
2154                 if (!ikeAuthEapConfig.getEapConfig().areAllMethodsEapOnlySafe()) {
2155                     throw new IllegalArgumentException(
2156                             "Only EAP-only safe method allowed" + " when using EAP-only option.");
2157                 }
2158             }
2159 
2160             // as of today, the device_identity feature is only implemented for EAP-AKA
2161             if ((mIke3gppExtension != null
2162                     && mIke3gppExtension.getIke3gppParams().getMobileDeviceIdentity() != null)) {
2163                 if (!(mLocalAuthConfig instanceof IkeAuthEapConfig)
2164                         || ((IkeAuthEapConfig) mLocalAuthConfig).getEapConfig().getEapAkaConfig()
2165                                 == null) {
2166                     throw new IllegalArgumentException(
2167                             "If device identity is set in Ike3gppParams, then EAP-KA MUST be"
2168                                     + " configured as an acceptable authentication method");
2169                 }
2170             }
2171 
2172             if (mLocalAuthConfig.mAuthMethod == IKE_AUTH_METHOD_PUB_KEY_SIGNATURE
2173                     && mLocalIdentification.idType == IkeIdentification.ID_TYPE_KEY_ID) {
2174                 throw new IllegalArgumentException(
2175                         "It is not allowed to use KEY_ID as local ID when local authentication"
2176                                 + " method is digital-signature-based");
2177             }
2178 
2179             if ((mIpVersion == ESP_IP_VERSION_IPV4 && mEncapType == ESP_ENCAP_TYPE_NONE)
2180                     || (mIpVersion == ESP_IP_VERSION_IPV6 && mEncapType == ESP_ENCAP_TYPE_UDP)) {
2181                 throw new UnsupportedOperationException("Sending packets with IPv4 ESP or IPv6 UDP"
2182                         + " are not supported");
2183             }
2184 
2185             return new IkeSessionParams(
2186                     mServerHostname,
2187                     defaultOrConfiguredNetwork,
2188                     mCallerConfiguredNetwork,
2189                     mSaProposalList.toArray(new IkeSaProposal[0]),
2190                     mLocalIdentification,
2191                     mRemoteIdentification,
2192                     mLocalAuthConfig,
2193                     mRemoteAuthConfig,
2194                     mConfigRequestList.toArray(new IkeConfigAttribute[0]),
2195                     mRetransTimeoutMsList,
2196                     mIke3gppExtension,
2197                     mIkeOptions,
2198                     mHardLifetimeSec,
2199                     mSoftLifetimeSec,
2200                     mDpdDelaySec,
2201                     mNattKeepaliveDelaySec,
2202                     mDscp,
2203                     mIpVersion,
2204                     mEncapType,
2205                     mIsIkeFragmentationSupported);
2206         }
2207 
2208         // TODO: add methods for supporting IKE fragmentation.
2209     }
2210 }
2211