1 /* 2 * Copyright (C) 2021 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.vcn.persistablebundleutils; 18 19 import static android.system.OsConstants.AF_INET; 20 import static android.system.OsConstants.AF_INET6; 21 22 import static com.android.internal.annotations.VisibleForTesting.Visibility; 23 24 import android.annotation.NonNull; 25 import android.annotation.Nullable; 26 import android.net.InetAddresses; 27 import android.net.eap.EapSessionConfig; 28 import android.net.ipsec.ike.IkeSaProposal; 29 import android.net.ipsec.ike.IkeSessionParams; 30 import android.net.ipsec.ike.IkeSessionParams.ConfigRequestIpv4PcscfServer; 31 import android.net.ipsec.ike.IkeSessionParams.ConfigRequestIpv6PcscfServer; 32 import android.net.ipsec.ike.IkeSessionParams.IkeAuthConfig; 33 import android.net.ipsec.ike.IkeSessionParams.IkeAuthDigitalSignLocalConfig; 34 import android.net.ipsec.ike.IkeSessionParams.IkeAuthDigitalSignRemoteConfig; 35 import android.net.ipsec.ike.IkeSessionParams.IkeAuthEapConfig; 36 import android.net.ipsec.ike.IkeSessionParams.IkeAuthPskConfig; 37 import android.net.ipsec.ike.IkeSessionParams.IkeConfigRequest; 38 import android.os.PersistableBundle; 39 import android.util.ArraySet; 40 import android.util.Log; 41 42 import com.android.internal.annotations.VisibleForTesting; 43 import com.android.server.vcn.util.PersistableBundleUtils; 44 45 import java.net.InetAddress; 46 import java.security.PrivateKey; 47 import java.security.cert.CertificateEncodingException; 48 import java.security.cert.X509Certificate; 49 import java.util.ArrayList; 50 import java.util.Arrays; 51 import java.util.List; 52 import java.util.Objects; 53 import java.util.Set; 54 55 /** 56 * Abstract utility class to convert IkeSessionParams to/from PersistableBundle. 57 * 58 * @hide 59 */ 60 @VisibleForTesting(visibility = Visibility.PRIVATE) 61 public final class IkeSessionParamsUtils { 62 private static final String TAG = IkeSessionParamsUtils.class.getSimpleName(); 63 64 private static final String SERVER_HOST_NAME_KEY = "SERVER_HOST_NAME_KEY"; 65 private static final String SA_PROPOSALS_KEY = "SA_PROPOSALS_KEY"; 66 private static final String LOCAL_ID_KEY = "LOCAL_ID_KEY"; 67 private static final String REMOTE_ID_KEY = "REMOTE_ID_KEY"; 68 private static final String LOCAL_AUTH_KEY = "LOCAL_AUTH_KEY"; 69 private static final String REMOTE_AUTH_KEY = "REMOTE_AUTH_KEY"; 70 private static final String CONFIG_REQUESTS_KEY = "CONFIG_REQUESTS_KEY"; 71 private static final String RETRANS_TIMEOUTS_KEY = "RETRANS_TIMEOUTS_KEY"; 72 private static final String HARD_LIFETIME_SEC_KEY = "HARD_LIFETIME_SEC_KEY"; 73 private static final String SOFT_LIFETIME_SEC_KEY = "SOFT_LIFETIME_SEC_KEY"; 74 private static final String DPD_DELAY_SEC_KEY = "DPD_DELAY_SEC_KEY"; 75 private static final String NATT_KEEPALIVE_DELAY_SEC_KEY = "NATT_KEEPALIVE_DELAY_SEC_KEY"; 76 private static final String IKE_OPTIONS_KEY = "IKE_OPTIONS_KEY"; 77 private static final String IP_VERSION_KEY = "IP_VERSION_KEY"; 78 private static final String ENCAP_TYPE_KEY = "ENCAP_TYPE_KEY"; 79 // TODO: add DSCP_KEY and IS_IKE_FRAGMENT_SUPPORTED_KEY. 80 81 // TODO: b/243181760 Use the IKE API when they are exposed 82 @VisibleForTesting(visibility = Visibility.PRIVATE) 83 public static final int IKE_OPTION_AUTOMATIC_ADDRESS_FAMILY_SELECTION = 6; 84 85 @VisibleForTesting(visibility = Visibility.PRIVATE) 86 public static final int IKE_OPTION_AUTOMATIC_NATT_KEEPALIVES = 7; 87 88 private static final Set<Integer> IKE_OPTIONS = new ArraySet<>(); 89 90 static { 91 IKE_OPTIONS.add(IkeSessionParams.IKE_OPTION_ACCEPT_ANY_REMOTE_ID); 92 IKE_OPTIONS.add(IkeSessionParams.IKE_OPTION_EAP_ONLY_AUTH); 93 IKE_OPTIONS.add(IkeSessionParams.IKE_OPTION_MOBIKE); 94 IKE_OPTIONS.add(IkeSessionParams.IKE_OPTION_FORCE_PORT_4500); 95 IKE_OPTIONS.add(IkeSessionParams.IKE_OPTION_INITIAL_CONTACT); 96 IKE_OPTIONS.add(IkeSessionParams.IKE_OPTION_REKEY_MOBILITY); 97 IKE_OPTIONS.add(IKE_OPTION_AUTOMATIC_ADDRESS_FAMILY_SELECTION); 98 IKE_OPTIONS.add(IKE_OPTION_AUTOMATIC_NATT_KEEPALIVES); 99 IKE_OPTIONS.add(IkeSessionParams.IKE_OPTION_AUTOMATIC_KEEPALIVE_ON_OFF); 100 } 101 102 /** 103 * Check if an IKE option is supported in the IPsec module installed on the device 104 * 105 * <p>This method ensures caller to safely access options that are added between dessert 106 * releases. 107 */ 108 @VisibleForTesting(visibility = Visibility.PRIVATE) isIkeOptionValid(int option)109 public static boolean isIkeOptionValid(int option) { 110 try { 111 new IkeSessionParams.Builder().addIkeOption(option); 112 return true; 113 } catch (IllegalArgumentException e) { 114 Log.d(TAG, "Option not supported; discarding: " + option); 115 return false; 116 } 117 } 118 119 /** Serializes an IkeSessionParams to a PersistableBundle. */ 120 @NonNull toPersistableBundle(@onNull IkeSessionParams params)121 public static PersistableBundle toPersistableBundle(@NonNull IkeSessionParams params) { 122 if (params.getNetwork() != null || params.getIke3gppExtension() != null) { 123 throw new IllegalStateException( 124 "Cannot convert a IkeSessionParams with a caller configured network or with" 125 + " 3GPP extension enabled"); 126 } 127 128 final PersistableBundle result = new PersistableBundle(); 129 130 result.putString(SERVER_HOST_NAME_KEY, params.getServerHostname()); 131 132 final PersistableBundle saProposalBundle = 133 PersistableBundleUtils.fromList( 134 params.getSaProposals(), IkeSaProposalUtils::toPersistableBundle); 135 result.putPersistableBundle(SA_PROPOSALS_KEY, saProposalBundle); 136 137 result.putPersistableBundle( 138 LOCAL_ID_KEY, 139 IkeIdentificationUtils.toPersistableBundle(params.getLocalIdentification())); 140 result.putPersistableBundle( 141 REMOTE_ID_KEY, 142 IkeIdentificationUtils.toPersistableBundle(params.getRemoteIdentification())); 143 144 result.putPersistableBundle( 145 LOCAL_AUTH_KEY, AuthConfigUtils.toPersistableBundle(params.getLocalAuthConfig())); 146 result.putPersistableBundle( 147 REMOTE_AUTH_KEY, AuthConfigUtils.toPersistableBundle(params.getRemoteAuthConfig())); 148 149 final List<ConfigRequest> reqList = new ArrayList<>(); 150 for (IkeConfigRequest req : params.getConfigurationRequests()) { 151 reqList.add(new ConfigRequest(req)); 152 } 153 final PersistableBundle configReqListBundle = 154 PersistableBundleUtils.fromList(reqList, ConfigRequest::toPersistableBundle); 155 result.putPersistableBundle(CONFIG_REQUESTS_KEY, configReqListBundle); 156 157 result.putIntArray(RETRANS_TIMEOUTS_KEY, params.getRetransmissionTimeoutsMillis()); 158 result.putInt(HARD_LIFETIME_SEC_KEY, params.getHardLifetimeSeconds()); 159 result.putInt(SOFT_LIFETIME_SEC_KEY, params.getSoftLifetimeSeconds()); 160 result.putInt(DPD_DELAY_SEC_KEY, params.getDpdDelaySeconds()); 161 result.putInt(NATT_KEEPALIVE_DELAY_SEC_KEY, params.getNattKeepAliveDelaySeconds()); 162 result.putInt(IP_VERSION_KEY, params.getIpVersion()); 163 result.putInt(ENCAP_TYPE_KEY, params.getEncapType()); 164 165 final List<Integer> enabledIkeOptions = new ArrayList<>(); 166 167 try { 168 // TODO: b/328844044: Ideally this code should gate the behavior by checking the 169 // com.android.ipsec.flags.enabled_ike_options_api flag but that flag is not accessible 170 // right now. We should either update the code when the flag is accessible or remove the 171 // legacy behavior after VIC SDK finalization 172 enabledIkeOptions.addAll(params.getIkeOptions()); 173 } catch (Exception e) { 174 // getIkeOptions throws. It means the API is not available 175 enabledIkeOptions.clear(); 176 for (int option : IKE_OPTIONS) { 177 if (isIkeOptionValid(option) && params.hasIkeOption(option)) { 178 enabledIkeOptions.add(option); 179 } 180 } 181 } 182 183 final int[] optionArray = enabledIkeOptions.stream().mapToInt(i -> i).toArray(); 184 result.putIntArray(IKE_OPTIONS_KEY, optionArray); 185 186 return result; 187 } 188 189 /** Constructs an IkeSessionParams by deserializing a PersistableBundle. */ 190 @NonNull fromPersistableBundle(@onNull PersistableBundle in)191 public static IkeSessionParams fromPersistableBundle(@NonNull PersistableBundle in) { 192 Objects.requireNonNull(in, "PersistableBundle is null"); 193 194 final IkeSessionParams.Builder builder = new IkeSessionParams.Builder(); 195 196 builder.setServerHostname(in.getString(SERVER_HOST_NAME_KEY)); 197 198 PersistableBundle proposalBundle = in.getPersistableBundle(SA_PROPOSALS_KEY); 199 Objects.requireNonNull(in, "SA Proposals was null"); 200 List<IkeSaProposal> saProposals = 201 PersistableBundleUtils.toList( 202 proposalBundle, IkeSaProposalUtils::fromPersistableBundle); 203 for (IkeSaProposal proposal : saProposals) { 204 builder.addSaProposal(proposal); 205 } 206 207 builder.setLocalIdentification( 208 IkeIdentificationUtils.fromPersistableBundle( 209 in.getPersistableBundle(LOCAL_ID_KEY))); 210 builder.setRemoteIdentification( 211 IkeIdentificationUtils.fromPersistableBundle( 212 in.getPersistableBundle(REMOTE_ID_KEY))); 213 214 AuthConfigUtils.setBuilderByReadingPersistableBundle( 215 in.getPersistableBundle(LOCAL_AUTH_KEY), 216 in.getPersistableBundle(REMOTE_AUTH_KEY), 217 builder); 218 219 builder.setRetransmissionTimeoutsMillis(in.getIntArray(RETRANS_TIMEOUTS_KEY)); 220 builder.setLifetimeSeconds( 221 in.getInt(HARD_LIFETIME_SEC_KEY), in.getInt(SOFT_LIFETIME_SEC_KEY)); 222 builder.setDpdDelaySeconds(in.getInt(DPD_DELAY_SEC_KEY)); 223 builder.setNattKeepAliveDelaySeconds(in.getInt(NATT_KEEPALIVE_DELAY_SEC_KEY)); 224 builder.setIpVersion(in.getInt(IP_VERSION_KEY)); 225 builder.setEncapType(in.getInt(ENCAP_TYPE_KEY)); 226 227 final PersistableBundle configReqListBundle = in.getPersistableBundle(CONFIG_REQUESTS_KEY); 228 Objects.requireNonNull(configReqListBundle, "Config request list was null"); 229 final List<ConfigRequest> reqList = 230 PersistableBundleUtils.toList(configReqListBundle, ConfigRequest::new); 231 for (ConfigRequest req : reqList) { 232 switch (req.type) { 233 case ConfigRequest.IPV4_P_CSCF_ADDRESS: 234 if (req.address == null) { 235 builder.addPcscfServerRequest(AF_INET); 236 } else { 237 builder.addPcscfServerRequest(req.address); 238 } 239 break; 240 case ConfigRequest.IPV6_P_CSCF_ADDRESS: 241 if (req.address == null) { 242 builder.addPcscfServerRequest(AF_INET6); 243 } else { 244 builder.addPcscfServerRequest(req.address); 245 } 246 break; 247 default: 248 throw new IllegalArgumentException( 249 "Unrecognized config request type: " + req.type); 250 } 251 } 252 253 // Clear IKE Options that are by default enabled 254 for (int option : IKE_OPTIONS) { 255 if (isIkeOptionValid(option)) { 256 builder.removeIkeOption(option); 257 } 258 } 259 260 final int[] optionArray = in.getIntArray(IKE_OPTIONS_KEY); 261 for (int option : optionArray) { 262 if (isIkeOptionValid(option)) { 263 builder.addIkeOption(option); 264 } 265 } 266 267 return builder.build(); 268 } 269 270 private static final class AuthConfigUtils { 271 private static final int IKE_AUTH_METHOD_PSK = 1; 272 private static final int IKE_AUTH_METHOD_PUB_KEY_SIGNATURE = 2; 273 private static final int IKE_AUTH_METHOD_EAP = 3; 274 275 private static final String AUTH_METHOD_KEY = "AUTH_METHOD_KEY"; 276 277 @NonNull toPersistableBundle(@onNull IkeAuthConfig authConfig)278 public static PersistableBundle toPersistableBundle(@NonNull IkeAuthConfig authConfig) { 279 if (authConfig instanceof IkeAuthPskConfig) { 280 IkeAuthPskConfig config = (IkeAuthPskConfig) authConfig; 281 return IkeAuthPskConfigUtils.toPersistableBundle( 282 config, createPersistableBundle(IKE_AUTH_METHOD_PSK)); 283 } else if (authConfig instanceof IkeAuthDigitalSignLocalConfig) { 284 IkeAuthDigitalSignLocalConfig config = (IkeAuthDigitalSignLocalConfig) authConfig; 285 return IkeAuthDigitalSignConfigUtils.toPersistableBundle( 286 config, createPersistableBundle(IKE_AUTH_METHOD_PUB_KEY_SIGNATURE)); 287 } else if (authConfig instanceof IkeAuthDigitalSignRemoteConfig) { 288 IkeAuthDigitalSignRemoteConfig config = (IkeAuthDigitalSignRemoteConfig) authConfig; 289 return IkeAuthDigitalSignConfigUtils.toPersistableBundle( 290 config, createPersistableBundle(IKE_AUTH_METHOD_PUB_KEY_SIGNATURE)); 291 } else if (authConfig instanceof IkeAuthEapConfig) { 292 IkeAuthEapConfig config = (IkeAuthEapConfig) authConfig; 293 return IkeAuthEapConfigUtils.toPersistableBundle( 294 config, createPersistableBundle(IKE_AUTH_METHOD_EAP)); 295 } else { 296 throw new IllegalStateException("Invalid IkeAuthConfig subclass"); 297 } 298 } 299 createPersistableBundle(int type)300 private static PersistableBundle createPersistableBundle(int type) { 301 final PersistableBundle result = new PersistableBundle(); 302 result.putInt(AUTH_METHOD_KEY, type); 303 return result; 304 } 305 setBuilderByReadingPersistableBundle( @onNull PersistableBundle localAuthBundle, @NonNull PersistableBundle remoteAuthBundle, @NonNull IkeSessionParams.Builder builder)306 public static void setBuilderByReadingPersistableBundle( 307 @NonNull PersistableBundle localAuthBundle, 308 @NonNull PersistableBundle remoteAuthBundle, 309 @NonNull IkeSessionParams.Builder builder) { 310 Objects.requireNonNull(localAuthBundle, "localAuthBundle was null"); 311 Objects.requireNonNull(remoteAuthBundle, "remoteAuthBundle was null"); 312 313 final int localMethodType = localAuthBundle.getInt(AUTH_METHOD_KEY); 314 final int remoteMethodType = remoteAuthBundle.getInt(AUTH_METHOD_KEY); 315 switch (localMethodType) { 316 case IKE_AUTH_METHOD_PSK: 317 if (remoteMethodType != IKE_AUTH_METHOD_PSK) { 318 throw new IllegalArgumentException( 319 "Expect remote auth method to be PSK based, but was " 320 + remoteMethodType); 321 } 322 IkeAuthPskConfigUtils.setBuilderByReadingPersistableBundle( 323 localAuthBundle, remoteAuthBundle, builder); 324 return; 325 case IKE_AUTH_METHOD_PUB_KEY_SIGNATURE: 326 if (remoteMethodType != IKE_AUTH_METHOD_PUB_KEY_SIGNATURE) { 327 throw new IllegalArgumentException( 328 "Expect remote auth method to be digital signature based, but was " 329 + remoteMethodType); 330 } 331 IkeAuthDigitalSignConfigUtils.setBuilderByReadingPersistableBundle( 332 localAuthBundle, remoteAuthBundle, builder); 333 return; 334 case IKE_AUTH_METHOD_EAP: 335 if (remoteMethodType != IKE_AUTH_METHOD_PUB_KEY_SIGNATURE) { 336 throw new IllegalArgumentException( 337 "When using EAP for local authentication, expect remote auth" 338 + " method to be digital signature based, but was " 339 + remoteMethodType); 340 } 341 IkeAuthEapConfigUtils.setBuilderByReadingPersistableBundle( 342 localAuthBundle, remoteAuthBundle, builder); 343 return; 344 default: 345 throw new IllegalArgumentException( 346 "Invalid EAP method type " + localMethodType); 347 } 348 } 349 } 350 351 private static final class IkeAuthPskConfigUtils { 352 private static final String PSK_KEY = "PSK_KEY"; 353 354 @NonNull toPersistableBundle( @onNull IkeAuthPskConfig config, @NonNull PersistableBundle result)355 public static PersistableBundle toPersistableBundle( 356 @NonNull IkeAuthPskConfig config, @NonNull PersistableBundle result) { 357 result.putPersistableBundle( 358 PSK_KEY, PersistableBundleUtils.fromByteArray(config.getPsk())); 359 return result; 360 } 361 setBuilderByReadingPersistableBundle( @onNull PersistableBundle localAuthBundle, @NonNull PersistableBundle remoteAuthBundle, @NonNull IkeSessionParams.Builder builder)362 public static void setBuilderByReadingPersistableBundle( 363 @NonNull PersistableBundle localAuthBundle, 364 @NonNull PersistableBundle remoteAuthBundle, 365 @NonNull IkeSessionParams.Builder builder) { 366 Objects.requireNonNull(localAuthBundle, "localAuthBundle was null"); 367 Objects.requireNonNull(remoteAuthBundle, "remoteAuthBundle was null"); 368 369 final PersistableBundle localPskBundle = localAuthBundle.getPersistableBundle(PSK_KEY); 370 final PersistableBundle remotePskBundle = 371 remoteAuthBundle.getPersistableBundle(PSK_KEY); 372 Objects.requireNonNull(localAuthBundle, "Local PSK was null"); 373 Objects.requireNonNull(remoteAuthBundle, "Remote PSK was null"); 374 375 final byte[] localPsk = PersistableBundleUtils.toByteArray(localPskBundle); 376 final byte[] remotePsk = PersistableBundleUtils.toByteArray(remotePskBundle); 377 if (!Arrays.equals(localPsk, remotePsk)) { 378 throw new IllegalArgumentException("Local PSK and remote PSK are different"); 379 } 380 builder.setAuthPsk(localPsk); 381 } 382 } 383 384 private static class IkeAuthDigitalSignConfigUtils { 385 private static final String END_CERT_KEY = "END_CERT_KEY"; 386 private static final String INTERMEDIATE_CERTS_KEY = "INTERMEDIATE_CERTS_KEY"; 387 private static final String PRIVATE_KEY_KEY = "PRIVATE_KEY_KEY"; 388 private static final String TRUST_CERT_KEY = "TRUST_CERT_KEY"; 389 390 @NonNull toPersistableBundle( @onNull IkeAuthDigitalSignLocalConfig config, @NonNull PersistableBundle result)391 public static PersistableBundle toPersistableBundle( 392 @NonNull IkeAuthDigitalSignLocalConfig config, @NonNull PersistableBundle result) { 393 try { 394 result.putPersistableBundle( 395 END_CERT_KEY, 396 PersistableBundleUtils.fromByteArray( 397 config.getClientEndCertificate().getEncoded())); 398 399 final List<X509Certificate> certList = config.getIntermediateCertificates(); 400 final List<byte[]> encodedCertList = new ArrayList<>(certList.size()); 401 for (X509Certificate cert : certList) { 402 encodedCertList.add(cert.getEncoded()); 403 } 404 405 final PersistableBundle certsBundle = 406 PersistableBundleUtils.fromList( 407 encodedCertList, PersistableBundleUtils::fromByteArray); 408 result.putPersistableBundle(INTERMEDIATE_CERTS_KEY, certsBundle); 409 } catch (CertificateEncodingException e) { 410 throw new IllegalArgumentException("Fail to encode certificate"); 411 } 412 413 // TODO: b/170670506 Consider putting PrivateKey in Android KeyStore 414 result.putPersistableBundle( 415 PRIVATE_KEY_KEY, 416 PersistableBundleUtils.fromByteArray(config.getPrivateKey().getEncoded())); 417 return result; 418 } 419 420 @NonNull toPersistableBundle( @onNull IkeAuthDigitalSignRemoteConfig config, @NonNull PersistableBundle result)421 public static PersistableBundle toPersistableBundle( 422 @NonNull IkeAuthDigitalSignRemoteConfig config, @NonNull PersistableBundle result) { 423 try { 424 X509Certificate caCert = config.getRemoteCaCert(); 425 if (caCert != null) { 426 result.putPersistableBundle( 427 TRUST_CERT_KEY, 428 PersistableBundleUtils.fromByteArray(caCert.getEncoded())); 429 } 430 } catch (CertificateEncodingException e) { 431 throw new IllegalArgumentException("Fail to encode the certificate"); 432 } 433 434 return result; 435 } 436 setBuilderByReadingPersistableBundle( @onNull PersistableBundle localAuthBundle, @NonNull PersistableBundle remoteAuthBundle, @NonNull IkeSessionParams.Builder builder)437 public static void setBuilderByReadingPersistableBundle( 438 @NonNull PersistableBundle localAuthBundle, 439 @NonNull PersistableBundle remoteAuthBundle, 440 @NonNull IkeSessionParams.Builder builder) { 441 Objects.requireNonNull(localAuthBundle, "localAuthBundle was null"); 442 Objects.requireNonNull(remoteAuthBundle, "remoteAuthBundle was null"); 443 444 // Deserialize localAuth 445 final PersistableBundle endCertBundle = 446 localAuthBundle.getPersistableBundle(END_CERT_KEY); 447 Objects.requireNonNull(endCertBundle, "End cert was null"); 448 final byte[] encodedCert = PersistableBundleUtils.toByteArray(endCertBundle); 449 final X509Certificate endCert = CertUtils.certificateFromByteArray(encodedCert); 450 451 final PersistableBundle certsBundle = 452 localAuthBundle.getPersistableBundle(INTERMEDIATE_CERTS_KEY); 453 Objects.requireNonNull(certsBundle, "Intermediate certs was null"); 454 final List<byte[]> encodedCertList = 455 PersistableBundleUtils.toList(certsBundle, PersistableBundleUtils::toByteArray); 456 final List<X509Certificate> certList = new ArrayList<>(encodedCertList.size()); 457 for (byte[] encoded : encodedCertList) { 458 certList.add(CertUtils.certificateFromByteArray(encoded)); 459 } 460 461 final PersistableBundle privateKeyBundle = 462 localAuthBundle.getPersistableBundle(PRIVATE_KEY_KEY); 463 Objects.requireNonNull(privateKeyBundle, "PrivateKey bundle was null"); 464 final PrivateKey privateKey = 465 CertUtils.privateKeyFromByteArray( 466 PersistableBundleUtils.toByteArray(privateKeyBundle)); 467 468 // Deserialize remoteAuth 469 final PersistableBundle trustCertBundle = 470 remoteAuthBundle.getPersistableBundle(TRUST_CERT_KEY); 471 472 X509Certificate caCert = null; 473 if (trustCertBundle != null) { 474 final byte[] encodedCaCert = PersistableBundleUtils.toByteArray(trustCertBundle); 475 caCert = CertUtils.certificateFromByteArray(encodedCaCert); 476 } 477 478 builder.setAuthDigitalSignature(caCert, endCert, certList, privateKey); 479 } 480 } 481 482 private static final class IkeAuthEapConfigUtils { 483 private static final String EAP_CONFIG_KEY = "EAP_CONFIG_KEY"; 484 485 @NonNull toPersistableBundle( @onNull IkeAuthEapConfig config, @NonNull PersistableBundle result)486 public static PersistableBundle toPersistableBundle( 487 @NonNull IkeAuthEapConfig config, @NonNull PersistableBundle result) { 488 result.putPersistableBundle( 489 EAP_CONFIG_KEY, 490 EapSessionConfigUtils.toPersistableBundle(config.getEapConfig())); 491 return result; 492 } 493 setBuilderByReadingPersistableBundle( @onNull PersistableBundle localAuthBundle, @NonNull PersistableBundle remoteAuthBundle, @NonNull IkeSessionParams.Builder builder)494 public static void setBuilderByReadingPersistableBundle( 495 @NonNull PersistableBundle localAuthBundle, 496 @NonNull PersistableBundle remoteAuthBundle, 497 @NonNull IkeSessionParams.Builder builder) { 498 // Deserialize localAuth 499 final PersistableBundle eapBundle = 500 localAuthBundle.getPersistableBundle(EAP_CONFIG_KEY); 501 Objects.requireNonNull(eapBundle, "EAP Config was null"); 502 final EapSessionConfig eapConfig = 503 EapSessionConfigUtils.fromPersistableBundle(eapBundle); 504 505 // Deserialize remoteAuth 506 final PersistableBundle trustCertBundle = 507 remoteAuthBundle.getPersistableBundle( 508 IkeAuthDigitalSignConfigUtils.TRUST_CERT_KEY); 509 510 X509Certificate serverCaCert = null; 511 if (trustCertBundle != null) { 512 final byte[] encodedCaCert = PersistableBundleUtils.toByteArray(trustCertBundle); 513 serverCaCert = CertUtils.certificateFromByteArray(encodedCaCert); 514 } 515 builder.setAuthEap(serverCaCert, eapConfig); 516 } 517 } 518 519 private static final class ConfigRequest { 520 private static final int IPV4_P_CSCF_ADDRESS = 1; 521 private static final int IPV6_P_CSCF_ADDRESS = 2; 522 523 private static final String TYPE_KEY = "type"; 524 private static final String ADDRESS_KEY = "address"; 525 526 public final int type; 527 528 // Null when it is an empty request 529 @Nullable public final InetAddress address; 530 ConfigRequest(IkeConfigRequest config)531 ConfigRequest(IkeConfigRequest config) { 532 if (config instanceof ConfigRequestIpv4PcscfServer) { 533 type = IPV4_P_CSCF_ADDRESS; 534 address = ((ConfigRequestIpv4PcscfServer) config).getAddress(); 535 } else if (config instanceof ConfigRequestIpv6PcscfServer) { 536 type = IPV6_P_CSCF_ADDRESS; 537 address = ((ConfigRequestIpv6PcscfServer) config).getAddress(); 538 } else { 539 throw new IllegalStateException("Unknown TunnelModeChildConfigRequest"); 540 } 541 } 542 ConfigRequest(PersistableBundle in)543 ConfigRequest(PersistableBundle in) { 544 Objects.requireNonNull(in, "PersistableBundle was null"); 545 546 type = in.getInt(TYPE_KEY); 547 548 String addressStr = in.getString(ADDRESS_KEY); 549 if (addressStr == null) { 550 address = null; 551 } else { 552 address = InetAddresses.parseNumericAddress(addressStr); 553 } 554 } 555 556 @NonNull toPersistableBundle()557 public PersistableBundle toPersistableBundle() { 558 final PersistableBundle result = new PersistableBundle(); 559 560 result.putInt(TYPE_KEY, type); 561 if (address != null) { 562 result.putString(ADDRESS_KEY, address.getHostAddress()); 563 } 564 565 return result; 566 } 567 } 568 } 569