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