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