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