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; 18 19 import static android.net.IpSecAlgorithm.AUTH_AES_CMAC; 20 import static android.net.IpSecAlgorithm.AUTH_AES_XCBC; 21 import static android.net.IpSecAlgorithm.AUTH_CRYPT_AES_GCM; 22 import static android.net.IpSecAlgorithm.AUTH_CRYPT_CHACHA20_POLY1305; 23 import static android.net.IpSecAlgorithm.AUTH_HMAC_SHA256; 24 import static android.net.IpSecAlgorithm.AUTH_HMAC_SHA384; 25 import static android.net.IpSecAlgorithm.AUTH_HMAC_SHA512; 26 import static android.net.IpSecAlgorithm.CRYPT_AES_CBC; 27 import static android.net.IpSecAlgorithm.CRYPT_AES_CTR; 28 29 import static com.android.internal.annotations.VisibleForTesting.Visibility; 30 import static com.android.internal.util.Preconditions.checkStringNotEmpty; 31 import static com.android.net.module.util.NetworkStackConstants.IPV6_MIN_MTU; 32 33 import android.annotation.NonNull; 34 import android.annotation.Nullable; 35 import android.annotation.RequiresFeature; 36 import android.content.pm.PackageManager; 37 import android.net.ipsec.ike.IkeDerAsn1DnIdentification; 38 import android.net.ipsec.ike.IkeFqdnIdentification; 39 import android.net.ipsec.ike.IkeIdentification; 40 import android.net.ipsec.ike.IkeIpv4AddrIdentification; 41 import android.net.ipsec.ike.IkeIpv6AddrIdentification; 42 import android.net.ipsec.ike.IkeKeyIdIdentification; 43 import android.net.ipsec.ike.IkeRfc822AddrIdentification; 44 import android.net.ipsec.ike.IkeSessionParams; 45 import android.net.ipsec.ike.IkeTunnelConnectionParams; 46 import android.security.Credentials; 47 import android.util.Log; 48 49 import com.android.internal.annotations.VisibleForTesting; 50 import com.android.internal.net.VpnProfile; 51 52 import java.io.IOException; 53 import java.nio.charset.StandardCharsets; 54 import java.security.GeneralSecurityException; 55 import java.security.Key; 56 import java.security.KeyFactory; 57 import java.security.KeyStore; 58 import java.security.NoSuchAlgorithmException; 59 import java.security.PrivateKey; 60 import java.security.cert.CertificateEncodingException; 61 import java.security.cert.CertificateException; 62 import java.security.cert.X509Certificate; 63 import java.security.spec.InvalidKeySpecException; 64 import java.security.spec.PKCS8EncodedKeySpec; 65 import java.util.ArrayList; 66 import java.util.Arrays; 67 import java.util.Base64; 68 import java.util.Collections; 69 import java.util.List; 70 import java.util.Objects; 71 72 /** 73 * The Ikev2VpnProfile is a configuration for the platform setup of IKEv2/IPsec VPNs. 74 * 75 * <p>Together with VpnManager, this allows apps to provision IKEv2/IPsec VPNs that do not require 76 * the VPN app to constantly run in the background. 77 * 78 * @see VpnManager 79 * @see <a href="https://tools.ietf.org/html/rfc7296#section-3.3.2">RFC 7296 - Internet Key 80 * Exchange, Version 2 (IKEv2)</a> 81 */ 82 public final class Ikev2VpnProfile extends PlatformVpnProfile { 83 private static final String TAG = Ikev2VpnProfile.class.getSimpleName(); 84 /** Prefix for when a Private Key is an alias to look for in KeyStore @hide */ 85 public static final String PREFIX_KEYSTORE_ALIAS = "KEYSTORE_ALIAS:"; 86 /** Prefix for when a Private Key is stored directly in the profile @hide */ 87 public static final String PREFIX_INLINE = "INLINE:"; 88 89 private static final String ANDROID_KEYSTORE_PROVIDER = "AndroidKeyStore"; 90 private static final String MISSING_PARAM_MSG_TMPL = "Required parameter was not provided: %s"; 91 private static final String EMPTY_CERT = ""; 92 93 /** @hide */ 94 public static final List<String> DEFAULT_ALGORITHMS; 95 addAlgorithmIfSupported(List<String> algorithms, String ipSecAlgoName)96 private static void addAlgorithmIfSupported(List<String> algorithms, String ipSecAlgoName) { 97 if (IpSecAlgorithm.getSupportedAlgorithms().contains(ipSecAlgoName)) { 98 algorithms.add(ipSecAlgoName); 99 } 100 } 101 102 static { 103 final List<String> algorithms = new ArrayList<>(); addAlgorithmIfSupported(algorithms, CRYPT_AES_CBC)104 addAlgorithmIfSupported(algorithms, CRYPT_AES_CBC); addAlgorithmIfSupported(algorithms, CRYPT_AES_CTR)105 addAlgorithmIfSupported(algorithms, CRYPT_AES_CTR); addAlgorithmIfSupported(algorithms, AUTH_HMAC_SHA256)106 addAlgorithmIfSupported(algorithms, AUTH_HMAC_SHA256); addAlgorithmIfSupported(algorithms, AUTH_HMAC_SHA384)107 addAlgorithmIfSupported(algorithms, AUTH_HMAC_SHA384); addAlgorithmIfSupported(algorithms, AUTH_HMAC_SHA512)108 addAlgorithmIfSupported(algorithms, AUTH_HMAC_SHA512); addAlgorithmIfSupported(algorithms, AUTH_AES_XCBC)109 addAlgorithmIfSupported(algorithms, AUTH_AES_XCBC); addAlgorithmIfSupported(algorithms, AUTH_AES_CMAC)110 addAlgorithmIfSupported(algorithms, AUTH_AES_CMAC); addAlgorithmIfSupported(algorithms, AUTH_CRYPT_AES_GCM)111 addAlgorithmIfSupported(algorithms, AUTH_CRYPT_AES_GCM); addAlgorithmIfSupported(algorithms, AUTH_CRYPT_CHACHA20_POLY1305)112 addAlgorithmIfSupported(algorithms, AUTH_CRYPT_CHACHA20_POLY1305); 113 114 DEFAULT_ALGORITHMS = Collections.unmodifiableList(algorithms); 115 } 116 117 @Nullable private final String mServerAddr; 118 @Nullable private final String mUserIdentity; 119 120 // PSK authentication 121 @Nullable private final byte[] mPresharedKey; 122 123 // Username/Password, RSA authentication 124 @Nullable private final X509Certificate mServerRootCaCert; 125 126 // Username/Password authentication 127 @Nullable private final String mUsername; 128 @Nullable private final String mPassword; 129 130 // RSA Certificate authentication 131 @Nullable private final PrivateKey mRsaPrivateKey; 132 @Nullable private final X509Certificate mUserCert; 133 134 @Nullable private final ProxyInfo mProxyInfo; 135 @NonNull private final List<String> mAllowedAlgorithms; 136 private final boolean mIsBypassable; // Defaults in builder 137 private final boolean mIsMetered; // Defaults in builder 138 private final int mMaxMtu; // Defaults in builder 139 private final boolean mIsRestrictedToTestNetworks; 140 @Nullable private final IkeTunnelConnectionParams mIkeTunConnParams; 141 private final boolean mAutomaticNattKeepaliveTimerEnabled; 142 private final boolean mAutomaticIpVersionSelectionEnabled; 143 Ikev2VpnProfile( int type, @Nullable String serverAddr, @Nullable String userIdentity, @Nullable byte[] presharedKey, @Nullable X509Certificate serverRootCaCert, @Nullable String username, @Nullable String password, @Nullable PrivateKey rsaPrivateKey, @Nullable X509Certificate userCert, @Nullable ProxyInfo proxyInfo, @NonNull List<String> allowedAlgorithms, boolean isBypassable, boolean isMetered, int maxMtu, boolean restrictToTestNetworks, boolean excludeLocalRoutes, boolean requiresInternetValidation, @Nullable IkeTunnelConnectionParams ikeTunConnParams, boolean automaticNattKeepaliveTimerEnabled, boolean automaticIpVersionSelectionEnabled)144 private Ikev2VpnProfile( 145 int type, 146 @Nullable String serverAddr, 147 @Nullable String userIdentity, 148 @Nullable byte[] presharedKey, 149 @Nullable X509Certificate serverRootCaCert, 150 @Nullable String username, 151 @Nullable String password, 152 @Nullable PrivateKey rsaPrivateKey, 153 @Nullable X509Certificate userCert, 154 @Nullable ProxyInfo proxyInfo, 155 @NonNull List<String> allowedAlgorithms, 156 boolean isBypassable, 157 boolean isMetered, 158 int maxMtu, 159 boolean restrictToTestNetworks, 160 boolean excludeLocalRoutes, 161 boolean requiresInternetValidation, 162 @Nullable IkeTunnelConnectionParams ikeTunConnParams, 163 boolean automaticNattKeepaliveTimerEnabled, 164 boolean automaticIpVersionSelectionEnabled) { 165 super(type, excludeLocalRoutes, requiresInternetValidation); 166 167 checkNotNull(allowedAlgorithms, MISSING_PARAM_MSG_TMPL, "Allowed Algorithms"); 168 169 mServerAddr = serverAddr; 170 mUserIdentity = userIdentity; 171 mPresharedKey = 172 presharedKey == null ? null : Arrays.copyOf(presharedKey, presharedKey.length); 173 mServerRootCaCert = serverRootCaCert; 174 mUsername = username; 175 mPassword = password; 176 mRsaPrivateKey = rsaPrivateKey; 177 mUserCert = userCert; 178 mProxyInfo = (proxyInfo == null) ? null : new ProxyInfo(proxyInfo); 179 180 // UnmodifiableList doesn't make a defensive copy by default. 181 mAllowedAlgorithms = Collections.unmodifiableList(new ArrayList<>(allowedAlgorithms)); 182 if (excludeLocalRoutes && !isBypassable) { 183 throw new IllegalArgumentException( 184 "Vpn must be bypassable if excludeLocalRoutes is set"); 185 } 186 187 mIsBypassable = isBypassable; 188 mIsMetered = isMetered; 189 mMaxMtu = maxMtu; 190 mIsRestrictedToTestNetworks = restrictToTestNetworks; 191 mIkeTunConnParams = ikeTunConnParams; 192 mAutomaticNattKeepaliveTimerEnabled = automaticNattKeepaliveTimerEnabled; 193 mAutomaticIpVersionSelectionEnabled = automaticIpVersionSelectionEnabled; 194 195 validate(); 196 } 197 validate()198 private void validate() { 199 // IPv6 MTU is greater; since profiles may be started by the system on IPv4 and IPv6 200 // networks, the VPN must provide a link fulfilling the stricter of the two conditions 201 // (at least that of the IPv6 MTU). 202 if (mMaxMtu < IPV6_MIN_MTU) { 203 throw new IllegalArgumentException("Max MTU must be at least" + IPV6_MIN_MTU); 204 } 205 206 // Skip validating the other fields if mIkeTunConnParams is set because the required 207 // information should all come from the mIkeTunConnParams. 208 if (mIkeTunConnParams != null) return; 209 210 // Server Address not validated except to check an address was provided. This allows for 211 // dual-stack servers and hostname based addresses. 212 checkStringNotEmpty(mServerAddr, MISSING_PARAM_MSG_TMPL, "Server Address"); 213 checkStringNotEmpty(mUserIdentity, MISSING_PARAM_MSG_TMPL, "User Identity"); 214 215 switch (mType) { 216 case TYPE_IKEV2_IPSEC_USER_PASS: 217 checkNotNull(mUsername, MISSING_PARAM_MSG_TMPL, "Username"); 218 checkNotNull(mPassword, MISSING_PARAM_MSG_TMPL, "Password"); 219 220 if (mServerRootCaCert != null) checkCert(mServerRootCaCert); 221 222 break; 223 case TYPE_IKEV2_IPSEC_PSK: 224 checkNotNull(mPresharedKey, MISSING_PARAM_MSG_TMPL, "Preshared Key"); 225 break; 226 case TYPE_IKEV2_IPSEC_RSA: 227 checkNotNull(mUserCert, MISSING_PARAM_MSG_TMPL, "User cert"); 228 checkNotNull(mRsaPrivateKey, MISSING_PARAM_MSG_TMPL, "RSA Private key"); 229 230 checkCert(mUserCert); 231 if (mServerRootCaCert != null) checkCert(mServerRootCaCert); 232 233 break; 234 default: 235 throw new IllegalArgumentException("Invalid auth method set"); 236 } 237 238 validateAllowedAlgorithms(mAllowedAlgorithms); 239 } 240 241 /** 242 * Validates that the allowed algorithms are a valid set for IPsec purposes 243 * 244 * <p>In order for the algorithm list to be a valid set, it must contain at least one algorithm 245 * that provides Authentication, and one that provides Encryption. Authenticated Encryption with 246 * Associated Data (AEAD) algorithms are counted as providing Authentication and Encryption. 247 * 248 * @param algorithmNames The list to be validated 249 */ validateAllowedAlgorithms(@onNull List<String> algorithmNames)250 private static void validateAllowedAlgorithms(@NonNull List<String> algorithmNames) { 251 // First, make sure no insecure algorithms were proposed. 252 if (algorithmNames.contains(IpSecAlgorithm.AUTH_HMAC_MD5) 253 || algorithmNames.contains(IpSecAlgorithm.AUTH_HMAC_SHA1)) { 254 throw new IllegalArgumentException("Algorithm not supported for IKEv2 VPN profiles"); 255 } 256 257 // Validate that some valid combination (AEAD or AUTH + CRYPT) is present 258 if (hasAeadAlgorithms(algorithmNames) || hasNormalModeAlgorithms(algorithmNames)) { 259 return; 260 } 261 262 throw new IllegalArgumentException("Algorithm set missing support for Auth, Crypt or both"); 263 } 264 265 /** 266 * Checks if the provided list has AEAD algorithms 267 * 268 * @hide 269 */ hasAeadAlgorithms(@onNull List<String> algorithmNames)270 public static boolean hasAeadAlgorithms(@NonNull List<String> algorithmNames) { 271 return algorithmNames.contains(IpSecAlgorithm.AUTH_CRYPT_AES_GCM); 272 } 273 274 /** 275 * Checks the provided list has acceptable (non-AEAD) authentication and encryption algorithms 276 * 277 * @hide 278 */ hasNormalModeAlgorithms(@onNull List<String> algorithmNames)279 public static boolean hasNormalModeAlgorithms(@NonNull List<String> algorithmNames) { 280 final boolean hasCrypt = algorithmNames.contains(IpSecAlgorithm.CRYPT_AES_CBC); 281 final boolean hasAuth = algorithmNames.contains(IpSecAlgorithm.AUTH_HMAC_SHA256) 282 || algorithmNames.contains(IpSecAlgorithm.AUTH_HMAC_SHA384) 283 || algorithmNames.contains(IpSecAlgorithm.AUTH_HMAC_SHA512); 284 285 return hasCrypt && hasAuth; 286 } 287 288 /** Retrieves the server address string. */ 289 @NonNull getServerAddr()290 public String getServerAddr() { 291 if (mIkeTunConnParams == null) return mServerAddr; 292 293 final IkeSessionParams ikeSessionParams = mIkeTunConnParams.getIkeSessionParams(); 294 return ikeSessionParams.getServerHostname(); 295 } 296 297 /** Retrieves the user identity. */ 298 @NonNull getUserIdentity()299 public String getUserIdentity() { 300 if (mIkeTunConnParams == null) return mUserIdentity; 301 302 final IkeSessionParams ikeSessionParams = mIkeTunConnParams.getIkeSessionParams(); 303 return getUserIdentityFromIkeSession(ikeSessionParams); 304 } 305 306 /** 307 * Retrieves the pre-shared key. 308 * 309 * <p>May be null if the profile is not using Pre-shared key authentication, or the profile is 310 * built from an {@link IkeTunnelConnectionParams}. 311 */ 312 @Nullable getPresharedKey()313 public byte[] getPresharedKey() { 314 if (mIkeTunConnParams != null) return null; 315 316 return mPresharedKey == null ? null : Arrays.copyOf(mPresharedKey, mPresharedKey.length); 317 } 318 319 /** 320 * Retrieves the certificate for the server's root CA. 321 * 322 * <p>May be null if the profile is not using RSA Digital Signature Authentication or 323 * Username/Password authentication, or the profile is built from an 324 * {@link IkeTunnelConnectionParams}. 325 */ 326 @Nullable getServerRootCaCert()327 public X509Certificate getServerRootCaCert() { 328 if (mIkeTunConnParams != null) return null; 329 330 return mServerRootCaCert; 331 } 332 /** 333 * Retrieves the username. 334 * 335 * <p>May be null if the profile is not using Username/Password authentication, or the profile 336 * is built from an {@link IkeTunnelConnectionParams}. 337 */ 338 @Nullable getUsername()339 public String getUsername() { 340 if (mIkeTunConnParams != null) return null; 341 342 return mUsername; 343 } 344 345 /** 346 * Retrieves the password. 347 * 348 * <p>May be null if the profile is not using Username/Password authentication, or the profile 349 * is built from an {@link IkeTunnelConnectionParams}. 350 */ 351 @Nullable getPassword()352 public String getPassword() { 353 if (mIkeTunConnParams != null) return null; 354 355 return mPassword; 356 } 357 358 /** 359 * Retrieves the RSA private key. 360 * 361 * <p>May be null if the profile is not using RSA Digital Signature authentication, or the 362 * profile is built from an {@link IkeTunnelConnectionParams}. 363 */ 364 @Nullable getRsaPrivateKey()365 public PrivateKey getRsaPrivateKey() { 366 if (mIkeTunConnParams != null) return null; 367 368 return mRsaPrivateKey; 369 } 370 371 /** Retrieves the user certificate, if any was set. 372 * 373 * <p>May be null if the profile is built from an {@link IkeTunnelConnectionParams}. 374 */ 375 @Nullable getUserCert()376 public X509Certificate getUserCert() { 377 if (mIkeTunConnParams != null) return null; 378 379 return mUserCert; 380 } 381 382 /** Retrieves the proxy information if any was set */ 383 @Nullable getProxyInfo()384 public ProxyInfo getProxyInfo() { 385 return mProxyInfo; 386 } 387 388 /** Returns all the algorithms allowed by this VPN profile. 389 * 390 * <p>May be an empty list if the profile is built from an {@link IkeTunnelConnectionParams}. 391 */ 392 @NonNull getAllowedAlgorithms()393 public List<String> getAllowedAlgorithms() { 394 if (mIkeTunConnParams != null) return new ArrayList<>(); 395 396 return mAllowedAlgorithms; 397 } 398 399 /** Returns whether or not the VPN profile should be bypassable. */ isBypassable()400 public boolean isBypassable() { 401 return mIsBypassable; 402 } 403 404 /** Returns whether or not the VPN profile should be always considered metered. */ isMetered()405 public boolean isMetered() { 406 return mIsMetered; 407 } 408 409 /** Retrieves the maximum MTU set for this VPN profile. */ getMaxMtu()410 public int getMaxMtu() { 411 return mMaxMtu; 412 } 413 414 /** Retrieves the ikeTunnelConnectionParams contains IKEv2 configurations, if any was set. */ 415 @Nullable getIkeTunnelConnectionParams()416 public IkeTunnelConnectionParams getIkeTunnelConnectionParams() { 417 return mIkeTunConnParams; 418 } 419 420 /** 421 * Returns whether or not this VPN profile is restricted to test networks. 422 * 423 * @hide 424 */ isRestrictedToTestNetworks()425 public boolean isRestrictedToTestNetworks() { 426 return mIsRestrictedToTestNetworks; 427 } 428 429 /** Returns whether automatic NAT-T keepalive timers are enabled. */ isAutomaticNattKeepaliveTimerEnabled()430 public boolean isAutomaticNattKeepaliveTimerEnabled() { 431 return mAutomaticNattKeepaliveTimerEnabled; 432 } 433 434 /** Returns whether automatic IP version selection is enabled. */ isAutomaticIpVersionSelectionEnabled()435 public boolean isAutomaticIpVersionSelectionEnabled() { 436 return mAutomaticIpVersionSelectionEnabled; 437 } 438 439 @Override hashCode()440 public int hashCode() { 441 return Objects.hash( 442 mType, 443 mServerAddr, 444 mUserIdentity, 445 Arrays.hashCode(mPresharedKey), 446 mServerRootCaCert, 447 mUsername, 448 mPassword, 449 mRsaPrivateKey, 450 mUserCert, 451 mProxyInfo, 452 mAllowedAlgorithms, 453 mIsBypassable, 454 mIsMetered, 455 mMaxMtu, 456 mIsRestrictedToTestNetworks, 457 mExcludeLocalRoutes, 458 mRequiresInternetValidation, 459 mIkeTunConnParams, 460 mAutomaticNattKeepaliveTimerEnabled, 461 mAutomaticIpVersionSelectionEnabled); 462 } 463 464 @Override equals(@ullable Object obj)465 public boolean equals(@Nullable Object obj) { 466 if (!(obj instanceof Ikev2VpnProfile)) { 467 return false; 468 } 469 470 final Ikev2VpnProfile other = (Ikev2VpnProfile) obj; 471 return mType == other.mType 472 && Objects.equals(mServerAddr, other.mServerAddr) 473 && Objects.equals(mUserIdentity, other.mUserIdentity) 474 && Arrays.equals(mPresharedKey, other.mPresharedKey) 475 && Objects.equals(mServerRootCaCert, other.mServerRootCaCert) 476 && Objects.equals(mUsername, other.mUsername) 477 && Objects.equals(mPassword, other.mPassword) 478 && Objects.equals(mRsaPrivateKey, other.mRsaPrivateKey) 479 && Objects.equals(mUserCert, other.mUserCert) 480 && Objects.equals(mProxyInfo, other.mProxyInfo) 481 && Objects.equals(mAllowedAlgorithms, other.mAllowedAlgorithms) 482 && mIsBypassable == other.mIsBypassable 483 && mIsMetered == other.mIsMetered 484 && mMaxMtu == other.mMaxMtu 485 && mIsRestrictedToTestNetworks == other.mIsRestrictedToTestNetworks 486 && mExcludeLocalRoutes == other.mExcludeLocalRoutes 487 && mRequiresInternetValidation == other.mRequiresInternetValidation 488 && Objects.equals(mIkeTunConnParams, other.mIkeTunConnParams) 489 && mAutomaticNattKeepaliveTimerEnabled == other.mAutomaticNattKeepaliveTimerEnabled 490 && mAutomaticIpVersionSelectionEnabled == other.mAutomaticIpVersionSelectionEnabled; 491 } 492 493 /** 494 * Builds a VpnProfile instance for internal use, based on the stored IKEv2/IPsec parameters. 495 * 496 * <p>Redundant authentication information (from previous calls to other setAuth* methods) will 497 * be discarded. 498 * 499 * @hide 500 */ 501 @NonNull toVpnProfile()502 public VpnProfile toVpnProfile() throws IOException, GeneralSecurityException { 503 final VpnProfile profile = new VpnProfile("" /* Key; value unused by IKEv2VpnProfile(s) */, 504 mIsRestrictedToTestNetworks, mExcludeLocalRoutes, mRequiresInternetValidation, 505 mIkeTunConnParams, mAutomaticNattKeepaliveTimerEnabled, 506 mAutomaticIpVersionSelectionEnabled); 507 profile.proxy = mProxyInfo; 508 profile.isBypassable = mIsBypassable; 509 profile.isMetered = mIsMetered; 510 profile.maxMtu = mMaxMtu; 511 profile.areAuthParamsInline = true; 512 profile.saveLogin = true; 513 // The other fields should come from mIkeTunConnParams if it's available. 514 if (mIkeTunConnParams != null) { 515 profile.type = VpnProfile.TYPE_IKEV2_FROM_IKE_TUN_CONN_PARAMS; 516 return profile; 517 } 518 519 profile.type = mType; 520 profile.server = getServerAddr(); 521 profile.ipsecIdentifier = getUserIdentity(); 522 profile.setAllowedAlgorithms(mAllowedAlgorithms); 523 switch (mType) { 524 case TYPE_IKEV2_IPSEC_USER_PASS: 525 profile.username = mUsername; 526 profile.password = mPassword; 527 profile.ipsecCaCert = 528 mServerRootCaCert == null ? "" : certificateToPemString(mServerRootCaCert); 529 break; 530 case TYPE_IKEV2_IPSEC_PSK: 531 profile.ipsecSecret = encodeForIpsecSecret(mPresharedKey); 532 break; 533 case TYPE_IKEV2_IPSEC_RSA: 534 profile.ipsecUserCert = certificateToPemString(mUserCert); 535 profile.ipsecSecret = 536 PREFIX_INLINE + encodeForIpsecSecret(mRsaPrivateKey.getEncoded()); 537 profile.ipsecCaCert = 538 mServerRootCaCert == null ? "" : certificateToPemString(mServerRootCaCert); 539 break; 540 default: 541 throw new IllegalArgumentException("Invalid auth method set"); 542 } 543 544 return profile; 545 } 546 getPrivateKeyFromAndroidKeystore(String alias)547 private static PrivateKey getPrivateKeyFromAndroidKeystore(String alias) { 548 try { 549 final KeyStore keystore = KeyStore.getInstance(ANDROID_KEYSTORE_PROVIDER); 550 keystore.load(null); 551 final Key key = keystore.getKey(alias, null); 552 if (!(key instanceof PrivateKey)) { 553 throw new IllegalStateException( 554 "Unexpected key type returned from android keystore."); 555 } 556 return (PrivateKey) key; 557 } catch (Exception e) { 558 throw new IllegalStateException("Failed to load key from android keystore.", e); 559 } 560 } 561 562 /** 563 * Builds the Ikev2VpnProfile from the given profile. 564 * 565 * @param profile the source VpnProfile to build from 566 * @return The IKEv2/IPsec VPN profile 567 * @hide 568 */ 569 @NonNull fromVpnProfile(@onNull VpnProfile profile)570 public static Ikev2VpnProfile fromVpnProfile(@NonNull VpnProfile profile) 571 throws GeneralSecurityException { 572 final Builder builder; 573 if (profile.ikeTunConnParams == null) { 574 builder = new Builder(profile.server, profile.ipsecIdentifier); 575 builder.setAllowedAlgorithms(profile.getAllowedAlgorithms()); 576 577 switch (profile.type) { 578 case TYPE_IKEV2_IPSEC_USER_PASS: 579 builder.setAuthUsernamePassword( 580 profile.username, 581 profile.password, 582 certificateFromPemString(profile.ipsecCaCert)); 583 break; 584 case TYPE_IKEV2_IPSEC_PSK: 585 builder.setAuthPsk(decodeFromIpsecSecret(profile.ipsecSecret)); 586 break; 587 case TYPE_IKEV2_IPSEC_RSA: 588 final PrivateKey key; 589 if (profile.ipsecSecret.startsWith(PREFIX_KEYSTORE_ALIAS)) { 590 final String alias = 591 profile.ipsecSecret.substring(PREFIX_KEYSTORE_ALIAS.length()); 592 key = getPrivateKeyFromAndroidKeystore(alias); 593 } else if (profile.ipsecSecret.startsWith(PREFIX_INLINE)) { 594 key = getPrivateKey(profile.ipsecSecret.substring(PREFIX_INLINE.length())); 595 } else { 596 throw new IllegalArgumentException("Invalid RSA private key prefix"); 597 } 598 599 final X509Certificate userCert = 600 certificateFromPemString(profile.ipsecUserCert); 601 final X509Certificate serverRootCa = 602 certificateFromPemString(profile.ipsecCaCert); 603 builder.setAuthDigitalSignature(userCert, key, serverRootCa); 604 break; 605 default: 606 throw new IllegalArgumentException("Invalid auth method set"); 607 } 608 } else { 609 builder = new Builder(profile.ikeTunConnParams); 610 } 611 612 builder.setProxy(profile.proxy); 613 builder.setBypassable(profile.isBypassable); 614 builder.setMetered(profile.isMetered); 615 builder.setMaxMtu(profile.maxMtu); 616 if (profile.isRestrictedToTestNetworks) { 617 builder.restrictToTestNetworks(); 618 } 619 620 if (profile.excludeLocalRoutes && !profile.isBypassable) { 621 Log.w(TAG, "ExcludeLocalRoutes should only be set in the bypassable VPN"); 622 } 623 624 builder.setLocalRoutesExcluded(profile.excludeLocalRoutes && profile.isBypassable); 625 builder.setRequiresInternetValidation(profile.requiresInternetValidation); 626 627 builder.setAutomaticNattKeepaliveTimerEnabled(profile.automaticNattKeepaliveTimerEnabled); 628 builder.setAutomaticIpVersionSelectionEnabled(profile.automaticIpVersionSelectionEnabled); 629 630 return builder.build(); 631 } 632 633 /** 634 * Validates that the VpnProfile is acceptable for the purposes of an Ikev2VpnProfile. 635 * 636 * @hide 637 */ isValidVpnProfile(@onNull VpnProfile profile)638 public static boolean isValidVpnProfile(@NonNull VpnProfile profile) { 639 if (profile.server.isEmpty() || profile.ipsecIdentifier.isEmpty()) { 640 return false; 641 } 642 643 switch (profile.type) { 644 case TYPE_IKEV2_IPSEC_USER_PASS: 645 if (profile.username.isEmpty() || profile.password.isEmpty()) { 646 return false; 647 } 648 break; 649 case TYPE_IKEV2_IPSEC_PSK: 650 if (profile.ipsecSecret.isEmpty()) { 651 return false; 652 } 653 break; 654 case TYPE_IKEV2_IPSEC_RSA: 655 if (profile.ipsecSecret.isEmpty() || profile.ipsecUserCert.isEmpty()) { 656 return false; 657 } 658 break; 659 default: 660 return false; 661 } 662 663 return true; 664 } 665 666 /** 667 * Converts a X509 Certificate to a PEM-formatted string. 668 * 669 * <p>Must be public due to runtime-package restrictions. 670 * 671 * @hide 672 */ 673 @NonNull 674 @VisibleForTesting(visibility = Visibility.PRIVATE) certificateToPemString(@ullable X509Certificate cert)675 public static String certificateToPemString(@Nullable X509Certificate cert) 676 throws IOException, CertificateEncodingException { 677 if (cert == null) { 678 return EMPTY_CERT; 679 } 680 681 // Credentials.convertToPem outputs ASCII bytes. 682 return new String(Credentials.convertToPem(cert), StandardCharsets.US_ASCII); 683 } 684 685 /** 686 * Decodes the provided Certificate(s). 687 * 688 * <p>Will use the first one if the certStr encodes more than one certificate. 689 */ 690 @Nullable certificateFromPemString(@ullable String certStr)691 private static X509Certificate certificateFromPemString(@Nullable String certStr) 692 throws CertificateException { 693 if (certStr == null || EMPTY_CERT.equals(certStr)) { 694 return null; 695 } 696 697 try { 698 final List<X509Certificate> certs = 699 Credentials.convertFromPem(certStr.getBytes(StandardCharsets.US_ASCII)); 700 return certs.isEmpty() ? null : certs.get(0); 701 } catch (IOException e) { 702 throw new CertificateException(e); 703 } 704 } 705 706 /** @hide */ 707 @NonNull encodeForIpsecSecret(@onNull byte[] secret)708 public static String encodeForIpsecSecret(@NonNull byte[] secret) { 709 checkNotNull(secret, MISSING_PARAM_MSG_TMPL, "secret"); 710 711 return Base64.getEncoder().encodeToString(secret); 712 } 713 714 @NonNull decodeFromIpsecSecret(@onNull String encoded)715 private static byte[] decodeFromIpsecSecret(@NonNull String encoded) { 716 checkNotNull(encoded, MISSING_PARAM_MSG_TMPL, "encoded"); 717 718 return Base64.getDecoder().decode(encoded); 719 } 720 721 @NonNull getPrivateKey(@onNull String keyStr)722 private static PrivateKey getPrivateKey(@NonNull String keyStr) 723 throws InvalidKeySpecException, NoSuchAlgorithmException { 724 final PKCS8EncodedKeySpec privateKeySpec = 725 new PKCS8EncodedKeySpec(decodeFromIpsecSecret(keyStr)); 726 final KeyFactory keyFactory = KeyFactory.getInstance("RSA"); 727 return keyFactory.generatePrivate(privateKeySpec); 728 } 729 checkCert(@onNull X509Certificate cert)730 private static void checkCert(@NonNull X509Certificate cert) { 731 try { 732 certificateToPemString(cert); 733 } catch (GeneralSecurityException | IOException e) { 734 throw new IllegalArgumentException("Certificate could not be encoded"); 735 } 736 } 737 checkNotNull( final T reference, final String messageTemplate, final Object... messageArgs)738 private static @NonNull <T> T checkNotNull( 739 final T reference, final String messageTemplate, final Object... messageArgs) { 740 return Objects.requireNonNull(reference, String.format(messageTemplate, messageArgs)); 741 } 742 checkBuilderSetter(boolean constructedFromIkeTunConParams, @NonNull String field)743 private static void checkBuilderSetter(boolean constructedFromIkeTunConParams, 744 @NonNull String field) { 745 if (constructedFromIkeTunConParams) { 746 throw new IllegalArgumentException( 747 field + " can't be set with IkeTunnelConnectionParams builder"); 748 } 749 } 750 751 @NonNull getUserIdentityFromIkeSession(@onNull IkeSessionParams params)752 private static String getUserIdentityFromIkeSession(@NonNull IkeSessionParams params) { 753 final IkeIdentification ident = params.getLocalIdentification(); 754 // Refer to VpnIkev2Utils.parseIkeIdentification(). 755 if (ident instanceof IkeKeyIdIdentification) { 756 return "@#" + new String(((IkeKeyIdIdentification) ident).keyId); 757 } else if (ident instanceof IkeRfc822AddrIdentification) { 758 return "@@" + ((IkeRfc822AddrIdentification) ident).rfc822Name; 759 } else if (ident instanceof IkeFqdnIdentification) { 760 return "@" + ((IkeFqdnIdentification) ident).fqdn; 761 } else if (ident instanceof IkeIpv4AddrIdentification) { 762 return ((IkeIpv4AddrIdentification) ident).ipv4Address.getHostAddress(); 763 } else if (ident instanceof IkeIpv6AddrIdentification) { 764 return ((IkeIpv6AddrIdentification) ident).ipv6Address.getHostAddress(); 765 } else if (ident instanceof IkeDerAsn1DnIdentification) { 766 throw new IllegalArgumentException("Unspported ASN.1 encoded identities"); 767 } else { 768 throw new IllegalArgumentException("Unknown IkeIdentification to get user identity"); 769 } 770 } 771 772 @Override toString()773 public String toString() { 774 final StringBuilder sb = new StringBuilder("IkeV2VpnProfile ["); 775 sb.append(" MaxMtu=" + mMaxMtu); 776 if (mIsBypassable) sb.append(" Bypassable"); 777 if (mRequiresInternetValidation) sb.append(" RequiresInternetValidation"); 778 if (mIsRestrictedToTestNetworks) sb.append(" RestrictedToTestNetworks"); 779 if (mAutomaticNattKeepaliveTimerEnabled) sb.append(" AutomaticNattKeepaliveTimerEnabled"); 780 if (mAutomaticIpVersionSelectionEnabled) sb.append(" AutomaticIpVersionSelectionEnabled"); 781 sb.append("]"); 782 return sb.toString(); 783 } 784 785 /** A incremental builder for IKEv2 VPN profiles */ 786 public static final class Builder { 787 private int mType = -1; 788 @Nullable private final String mServerAddr; 789 @Nullable private final String mUserIdentity; 790 791 // PSK authentication 792 @Nullable private byte[] mPresharedKey; 793 794 // Username/Password, RSA authentication 795 @Nullable private X509Certificate mServerRootCaCert; 796 797 // Username/Password authentication 798 @Nullable private String mUsername; 799 @Nullable private String mPassword; 800 801 // RSA Certificate authentication 802 @Nullable private PrivateKey mRsaPrivateKey; 803 @Nullable private X509Certificate mUserCert; 804 805 @Nullable private ProxyInfo mProxyInfo; 806 @NonNull private List<String> mAllowedAlgorithms = DEFAULT_ALGORITHMS; 807 private boolean mRequiresInternetValidation = false; 808 private boolean mIsBypassable = false; 809 private boolean mIsMetered = true; 810 private int mMaxMtu = PlatformVpnProfile.MAX_MTU_DEFAULT; 811 private boolean mIsRestrictedToTestNetworks = false; 812 private boolean mExcludeLocalRoutes = false; 813 private boolean mAutomaticNattKeepaliveTimerEnabled = false; 814 private boolean mAutomaticIpVersionSelectionEnabled = false; 815 @Nullable private final IkeTunnelConnectionParams mIkeTunConnParams; 816 817 /** 818 * Creates a new builder with the basic parameters of an IKEv2/IPsec VPN. 819 * 820 * @param serverAddr the server that the VPN should connect to 821 * @param identity the identity string to be used for IKEv2 authentication 822 */ 823 @RequiresFeature(PackageManager.FEATURE_IPSEC_TUNNELS) Builder(@onNull String serverAddr, @NonNull String identity)824 public Builder(@NonNull String serverAddr, @NonNull String identity) { 825 checkNotNull(serverAddr, MISSING_PARAM_MSG_TMPL, "serverAddr"); 826 checkNotNull(identity, MISSING_PARAM_MSG_TMPL, "identity"); 827 828 mServerAddr = serverAddr; 829 mUserIdentity = identity; 830 831 mIkeTunConnParams = null; 832 } 833 834 /** 835 * Creates a new builder from a {@link IkeTunnelConnectionParams} 836 * 837 * @param ikeTunConnParams the {@link IkeTunnelConnectionParams} contains IKEv2 838 * configurations 839 */ 840 @RequiresFeature(PackageManager.FEATURE_IPSEC_TUNNELS) Builder(@onNull IkeTunnelConnectionParams ikeTunConnParams)841 public Builder(@NonNull IkeTunnelConnectionParams ikeTunConnParams) { 842 checkNotNull(ikeTunConnParams, MISSING_PARAM_MSG_TMPL, "ikeTunConnParams"); 843 844 mIkeTunConnParams = ikeTunConnParams; 845 mServerAddr = null; 846 mUserIdentity = null; 847 } 848 resetAuthParams()849 private void resetAuthParams() { 850 mPresharedKey = null; 851 mServerRootCaCert = null; 852 mUsername = null; 853 mPassword = null; 854 mRsaPrivateKey = null; 855 mUserCert = null; 856 } 857 858 /** 859 * Set the IKEv2 authentication to use the provided username/password. 860 * 861 * <p>Setting this will configure IKEv2 authentication using EAP-MSCHAPv2. Only one 862 * authentication method may be set. This method will overwrite any previously set 863 * authentication method. 864 * 865 * <p>If this {@link Builder} is constructed with an {@link IkeTunnelConnectionParams}, 866 * authentication details should be configured there, and calling this method will result 867 * in an exception being thrown. 868 * 869 * @param user the username to be used for EAP-MSCHAPv2 authentication 870 * @param pass the password to be used for EAP-MSCHAPv2 authentication 871 * @param serverRootCa the root certificate to be used for verifying the identity of the 872 * server 873 * @return this {@link Builder} object to facilitate chaining of method calls 874 * @throws IllegalArgumentException if any of the certificates were invalid or of an 875 * unrecognized format 876 */ 877 @NonNull 878 @RequiresFeature(PackageManager.FEATURE_IPSEC_TUNNELS) setAuthUsernamePassword( @onNull String user, @NonNull String pass, @Nullable X509Certificate serverRootCa)879 public Builder setAuthUsernamePassword( 880 @NonNull String user, 881 @NonNull String pass, 882 @Nullable X509Certificate serverRootCa) { 883 checkNotNull(user, MISSING_PARAM_MSG_TMPL, "user"); 884 checkNotNull(pass, MISSING_PARAM_MSG_TMPL, "pass"); 885 checkBuilderSetter(mIkeTunConnParams != null, "authUsernamePassword"); 886 887 // Test to make sure all auth params can be encoded safely. 888 if (serverRootCa != null) checkCert(serverRootCa); 889 890 resetAuthParams(); 891 mUsername = user; 892 mPassword = pass; 893 mServerRootCaCert = serverRootCa; 894 mType = VpnProfile.TYPE_IKEV2_IPSEC_USER_PASS; 895 return this; 896 } 897 898 /** 899 * Set the IKEv2 authentication to use Digital Signature Authentication with the given key. 900 * 901 * <p>Setting this will configure IKEv2 authentication using a Digital Signature scheme. 902 * Only one authentication method may be set. This method will overwrite any previously set 903 * authentication method. 904 * 905 * <p>If this {@link Builder} is constructed with an {@link IkeTunnelConnectionParams}, 906 * authentication details should be configured there, and calling this method will result in 907 * an exception being thrown. 908 * 909 * @param userCert the username to be used for RSA Digital signiture authentication 910 * @param key the PrivateKey instance associated with the user ceritificate, used for 911 * constructing the signature 912 * @param serverRootCa the root certificate to be used for verifying the identity of the 913 * server 914 * @return this {@link Builder} object to facilitate chaining of method calls 915 * @throws IllegalArgumentException if any of the certificates were invalid or of an 916 * unrecognized format 917 */ 918 @NonNull 919 @RequiresFeature(PackageManager.FEATURE_IPSEC_TUNNELS) setAuthDigitalSignature( @onNull X509Certificate userCert, @NonNull PrivateKey key, @Nullable X509Certificate serverRootCa)920 public Builder setAuthDigitalSignature( 921 @NonNull X509Certificate userCert, 922 @NonNull PrivateKey key, 923 @Nullable X509Certificate serverRootCa) { 924 checkNotNull(userCert, MISSING_PARAM_MSG_TMPL, "userCert"); 925 checkNotNull(key, MISSING_PARAM_MSG_TMPL, "key"); 926 checkBuilderSetter(mIkeTunConnParams != null, "authDigitalSignature"); 927 928 // Test to make sure all auth params can be encoded safely. 929 checkCert(userCert); 930 if (serverRootCa != null) checkCert(serverRootCa); 931 932 resetAuthParams(); 933 mUserCert = userCert; 934 mRsaPrivateKey = key; 935 mServerRootCaCert = serverRootCa; 936 mType = VpnProfile.TYPE_IKEV2_IPSEC_RSA; 937 return this; 938 } 939 940 /** 941 * Set the IKEv2 authentication to use Preshared keys. 942 * 943 * <p>Setting this will configure IKEv2 authentication using a Preshared Key. Only one 944 * authentication method may be set. This method will overwrite any previously set 945 * authentication method. 946 * 947 * <p>If this {@link Builder} is constructed with an {@link IkeTunnelConnectionParams}, 948 * authentication details should be configured there, and calling this method will result in 949 * an exception being thrown. 950 * 951 * @param psk the key to be used for Pre-Shared Key authentication 952 * @return this {@link Builder} object to facilitate chaining of method calls 953 */ 954 @NonNull 955 @RequiresFeature(PackageManager.FEATURE_IPSEC_TUNNELS) setAuthPsk(@onNull byte[] psk)956 public Builder setAuthPsk(@NonNull byte[] psk) { 957 checkNotNull(psk, MISSING_PARAM_MSG_TMPL, "psk"); 958 checkBuilderSetter(mIkeTunConnParams != null, "authPsk"); 959 960 resetAuthParams(); 961 mPresharedKey = psk; 962 mType = VpnProfile.TYPE_IKEV2_IPSEC_PSK; 963 return this; 964 } 965 966 /** 967 * Sets whether apps can bypass this VPN connection. 968 * 969 * <p>By default, all traffic from apps are forwarded through the VPN interface and it is 970 * not possible for unprivileged apps to side-step the VPN. If a VPN is set to bypassable, 971 * apps may use methods such as {@link Network#getSocketFactory} or {@link 972 * Network#openConnection} to instead send/receive directly over the underlying network or 973 * any other network they have permissions for. 974 * 975 * @param isBypassable Whether or not the VPN should be considered bypassable. Defaults to 976 * {@code false}. 977 * @return this {@link Builder} object to facilitate chaining of method calls 978 */ 979 @NonNull 980 @RequiresFeature(PackageManager.FEATURE_IPSEC_TUNNELS) setBypassable(boolean isBypassable)981 public Builder setBypassable(boolean isBypassable) { 982 mIsBypassable = isBypassable; 983 return this; 984 } 985 986 /** 987 * Sets a proxy for the VPN network. 988 * 989 * <p>Note that this proxy is only a recommendation and it may be ignored by apps. 990 * 991 * @param proxy the ProxyInfo to be set for the VPN network 992 * @return this {@link Builder} object to facilitate chaining of method calls 993 */ 994 @NonNull 995 @RequiresFeature(PackageManager.FEATURE_IPSEC_TUNNELS) setProxy(@ullable ProxyInfo proxy)996 public Builder setProxy(@Nullable ProxyInfo proxy) { 997 mProxyInfo = proxy; 998 return this; 999 } 1000 1001 /** 1002 * Set the upper bound of the maximum transmission unit (MTU) of the VPN interface. 1003 * 1004 * <p>If it is not set, a safe value will be used. Additionally, the actual link MTU will be 1005 * dynamically calculated/updated based on the underlying link's mtu. 1006 * 1007 * @param mtu the MTU (in bytes) of the VPN interface 1008 * @return this {@link Builder} object to facilitate chaining of method calls 1009 * @throws IllegalArgumentException if the value is not at least the minimum IPv6 MTU (1280) 1010 */ 1011 @NonNull 1012 @RequiresFeature(PackageManager.FEATURE_IPSEC_TUNNELS) setMaxMtu(int mtu)1013 public Builder setMaxMtu(int mtu) { 1014 // IPv6 MTU is greater; since profiles may be started by the system on IPv4 and IPv6 1015 // networks, the VPN must provide a link fulfilling the stricter of the two conditions 1016 // (at least that of the IPv6 MTU). 1017 if (mtu < IPV6_MIN_MTU) { 1018 throw new IllegalArgumentException("Max MTU must be at least " + IPV6_MIN_MTU); 1019 } 1020 mMaxMtu = mtu; 1021 return this; 1022 } 1023 1024 /** 1025 * Request that this VPN undergoes Internet validation. 1026 * 1027 * If this is true, the platform will perform basic validation checks for Internet 1028 * connectivity over this VPN. If and when they succeed, the VPN network capabilities will 1029 * reflect this by gaining the {@link NetworkCapabilities#NET_CAPABILITY_VALIDATED} 1030 * capability. 1031 * 1032 * If this is false, the platform assumes the VPN either is always capable of reaching the 1033 * Internet or intends not to. In this case, the VPN network capabilities will 1034 * always gain the {@link NetworkCapabilities#NET_CAPABILITY_VALIDATED} capability 1035 * immediately after it connects, whether it can reach public Internet destinations or not. 1036 * 1037 * @param requiresInternetValidation {@code true} if the framework should attempt to 1038 * validate this VPN for Internet connectivity. Defaults 1039 * to {@code false}. 1040 */ 1041 @NonNull 1042 @RequiresFeature(PackageManager.FEATURE_IPSEC_TUNNELS) setRequiresInternetValidation(boolean requiresInternetValidation)1043 public Builder setRequiresInternetValidation(boolean requiresInternetValidation) { 1044 mRequiresInternetValidation = requiresInternetValidation; 1045 return this; 1046 } 1047 1048 /** 1049 * Marks the VPN network as metered. 1050 * 1051 * <p>A VPN network is classified as metered when the user is sensitive to heavy data usage 1052 * due to monetary costs and/or data limitations. In such cases, you should set this to 1053 * {@code true} so that apps on the system can avoid doing large data transfers. Otherwise, 1054 * set this to {@code false}. Doing so would cause VPN network to inherit its meteredness 1055 * from the underlying network. 1056 * 1057 * @param isMetered {@code true} if the VPN network should be treated as metered regardless 1058 * of underlying network meteredness. Defaults to {@code true}. 1059 * @return this {@link Builder} object to facilitate chaining of method calls 1060 * @see NetworkCapabilities#NET_CAPABILITY_NOT_METERED 1061 */ 1062 @NonNull 1063 @RequiresFeature(PackageManager.FEATURE_IPSEC_TUNNELS) setMetered(boolean isMetered)1064 public Builder setMetered(boolean isMetered) { 1065 mIsMetered = isMetered; 1066 return this; 1067 } 1068 1069 /** 1070 * Sets the allowable set of IPsec algorithms 1071 * 1072 * <p>If set, this will constrain the set of algorithms that the IPsec tunnel will use for 1073 * integrity verification and encryption to the provided list. 1074 * 1075 * <p>The set of allowed IPsec algorithms is defined in {@link IpSecAlgorithm}. Adding of 1076 * algorithms that are considered insecure (such as AUTH_HMAC_MD5 and AUTH_HMAC_SHA1) is not 1077 * permitted, and will result in an IllegalArgumentException being thrown. 1078 * 1079 * <p>The provided algorithm list must contain at least one algorithm that provides 1080 * Authentication, and one that provides Encryption. Authenticated Encryption with 1081 * Associated Data (AEAD) algorithms provide both Authentication and Encryption. 1082 * 1083 * <p>If this {@link Builder} is constructed with an {@link IkeTunnelConnectionParams}, 1084 * authentication details should be configured there, and calling this method will result in 1085 * an exception being thrown. 1086 * 1087 * <p>By default, this profile will use any algorithm defined in {@link IpSecAlgorithm}, 1088 * with the exception of those considered insecure (as described above). 1089 * 1090 * @param algorithmNames the list of supported IPsec algorithms 1091 * @return this {@link Builder} object to facilitate chaining of method calls 1092 * @see IpSecAlgorithm 1093 */ 1094 @NonNull 1095 @RequiresFeature(PackageManager.FEATURE_IPSEC_TUNNELS) setAllowedAlgorithms(@onNull List<String> algorithmNames)1096 public Builder setAllowedAlgorithms(@NonNull List<String> algorithmNames) { 1097 checkNotNull(algorithmNames, MISSING_PARAM_MSG_TMPL, "algorithmNames"); 1098 checkBuilderSetter(mIkeTunConnParams != null, "algorithmNames"); 1099 validateAllowedAlgorithms(algorithmNames); 1100 1101 mAllowedAlgorithms = algorithmNames; 1102 return this; 1103 } 1104 1105 /** 1106 * Restricts this profile to use test networks (only). 1107 * 1108 * <p>This method is for testing only, and must not be used by apps. Calling 1109 * provisionVpnProfile() with a profile where test-network usage is enabled will require the 1110 * MANAGE_TEST_NETWORKS permission. 1111 * 1112 * @hide 1113 */ 1114 @NonNull 1115 @RequiresFeature(PackageManager.FEATURE_IPSEC_TUNNELS) restrictToTestNetworks()1116 public Builder restrictToTestNetworks() { 1117 mIsRestrictedToTestNetworks = true; 1118 return this; 1119 } 1120 1121 /** 1122 * Sets the enabled state of the automatic NAT-T keepalive timers 1123 * 1124 * Note that if this builder was constructed with a {@link IkeTunnelConnectionParams}, 1125 * but this is called with {@code true}, the framework will automatically choose the 1126 * appropriate keepalive timer and ignore the settings in the session params embedded 1127 * in the connection params. 1128 * 1129 * @param isEnabled {@code true} to enable automatic keepalive timers, based on internal 1130 * platform signals. Defaults to {@code false}. 1131 * @return this {@link Builder} object to facilitate chaining of method calls 1132 */ 1133 @NonNull 1134 @RequiresFeature(PackageManager.FEATURE_IPSEC_TUNNELS) setAutomaticNattKeepaliveTimerEnabled(boolean isEnabled)1135 public Builder setAutomaticNattKeepaliveTimerEnabled(boolean isEnabled) { 1136 mAutomaticNattKeepaliveTimerEnabled = isEnabled; 1137 return this; 1138 } 1139 1140 /** 1141 * Sets the enabled state of the automatic IP version selection 1142 * 1143 * @param isEnabled {@code true} to enable automatic IP version selection, based on internal 1144 * platform signals. Defaults to {@code false}. 1145 * @return this {@link Builder} object to facilitate chaining of method calls 1146 */ 1147 @NonNull 1148 @RequiresFeature(PackageManager.FEATURE_IPSEC_TUNNELS) setAutomaticIpVersionSelectionEnabled(boolean isEnabled)1149 public Builder setAutomaticIpVersionSelectionEnabled(boolean isEnabled) { 1150 mAutomaticIpVersionSelectionEnabled = isEnabled; 1151 return this; 1152 } 1153 1154 /** 1155 * Sets whether the local traffic is exempted from the VPN. 1156 * 1157 * When this is set, the system will not use the VPN network when an app 1158 * tries to send traffic for an IP address that is on a local network. 1159 * 1160 * Note that there are important security implications. In particular, the 1161 * networks that the device connects to typically decides what IP addresses 1162 * are part of the local network. This means that for VPNs setting this 1163 * flag, it is possible for anybody to set up a public network in such a 1164 * way that traffic to arbitrary IP addresses will bypass the VPN, including 1165 * traffic to services like DNS. When using this API, please consider the 1166 * security implications for your particular case. 1167 * 1168 * Note that because the local traffic will always bypass the VPN, 1169 * it is not possible to set this flag on a non-bypassable VPN. 1170 */ 1171 @NonNull 1172 @RequiresFeature(PackageManager.FEATURE_IPSEC_TUNNELS) setLocalRoutesExcluded(boolean excludeLocalRoutes)1173 public Builder setLocalRoutesExcluded(boolean excludeLocalRoutes) { 1174 mExcludeLocalRoutes = excludeLocalRoutes; 1175 return this; 1176 } 1177 1178 /** 1179 * Validates, builds and provisions the VpnProfile. 1180 * 1181 * @throws IllegalArgumentException if any of the required keys or values were invalid 1182 */ 1183 @NonNull 1184 @RequiresFeature(PackageManager.FEATURE_IPSEC_TUNNELS) build()1185 public Ikev2VpnProfile build() { 1186 return new Ikev2VpnProfile( 1187 mType, 1188 mServerAddr, 1189 mUserIdentity, 1190 mPresharedKey, 1191 mServerRootCaCert, 1192 mUsername, 1193 mPassword, 1194 mRsaPrivateKey, 1195 mUserCert, 1196 mProxyInfo, 1197 mAllowedAlgorithms, 1198 mIsBypassable, 1199 mIsMetered, 1200 mMaxMtu, 1201 mIsRestrictedToTestNetworks, 1202 mExcludeLocalRoutes, 1203 mRequiresInternetValidation, 1204 mIkeTunConnParams, 1205 mAutomaticNattKeepaliveTimerEnabled, 1206 mAutomaticIpVersionSelectionEnabled); 1207 } 1208 } 1209 } 1210