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 // TODO: b/185941731 Make sure IkeSessionParamsUtils is automatically updated when a new 166 // IKE_OPTION is defined in IKE module and added in the IkeSessionParams 167 final List<Integer> enabledIkeOptions = new ArrayList<>(); 168 for (int option : IKE_OPTIONS) { 169 if (isIkeOptionValid(option) && params.hasIkeOption(option)) { 170 enabledIkeOptions.add(option); 171 } 172 } 173 174 final int[] optionArray = enabledIkeOptions.stream().mapToInt(i -> i).toArray(); 175 result.putIntArray(IKE_OPTIONS_KEY, optionArray); 176 177 return result; 178 } 179 180 /** Constructs an IkeSessionParams by deserializing a PersistableBundle. */ 181 @NonNull fromPersistableBundle(@onNull PersistableBundle in)182 public static IkeSessionParams fromPersistableBundle(@NonNull PersistableBundle in) { 183 Objects.requireNonNull(in, "PersistableBundle is null"); 184 185 final IkeSessionParams.Builder builder = new IkeSessionParams.Builder(); 186 187 builder.setServerHostname(in.getString(SERVER_HOST_NAME_KEY)); 188 189 PersistableBundle proposalBundle = in.getPersistableBundle(SA_PROPOSALS_KEY); 190 Objects.requireNonNull(in, "SA Proposals was null"); 191 List<IkeSaProposal> saProposals = 192 PersistableBundleUtils.toList( 193 proposalBundle, IkeSaProposalUtils::fromPersistableBundle); 194 for (IkeSaProposal proposal : saProposals) { 195 builder.addSaProposal(proposal); 196 } 197 198 builder.setLocalIdentification( 199 IkeIdentificationUtils.fromPersistableBundle( 200 in.getPersistableBundle(LOCAL_ID_KEY))); 201 builder.setRemoteIdentification( 202 IkeIdentificationUtils.fromPersistableBundle( 203 in.getPersistableBundle(REMOTE_ID_KEY))); 204 205 AuthConfigUtils.setBuilderByReadingPersistableBundle( 206 in.getPersistableBundle(LOCAL_AUTH_KEY), 207 in.getPersistableBundle(REMOTE_AUTH_KEY), 208 builder); 209 210 builder.setRetransmissionTimeoutsMillis(in.getIntArray(RETRANS_TIMEOUTS_KEY)); 211 builder.setLifetimeSeconds( 212 in.getInt(HARD_LIFETIME_SEC_KEY), in.getInt(SOFT_LIFETIME_SEC_KEY)); 213 builder.setDpdDelaySeconds(in.getInt(DPD_DELAY_SEC_KEY)); 214 builder.setNattKeepAliveDelaySeconds(in.getInt(NATT_KEEPALIVE_DELAY_SEC_KEY)); 215 builder.setIpVersion(in.getInt(IP_VERSION_KEY)); 216 builder.setEncapType(in.getInt(ENCAP_TYPE_KEY)); 217 218 final PersistableBundle configReqListBundle = in.getPersistableBundle(CONFIG_REQUESTS_KEY); 219 Objects.requireNonNull(configReqListBundle, "Config request list was null"); 220 final List<ConfigRequest> reqList = 221 PersistableBundleUtils.toList(configReqListBundle, ConfigRequest::new); 222 for (ConfigRequest req : reqList) { 223 switch (req.type) { 224 case ConfigRequest.IPV4_P_CSCF_ADDRESS: 225 if (req.address == null) { 226 builder.addPcscfServerRequest(AF_INET); 227 } else { 228 builder.addPcscfServerRequest(req.address); 229 } 230 break; 231 case ConfigRequest.IPV6_P_CSCF_ADDRESS: 232 if (req.address == null) { 233 builder.addPcscfServerRequest(AF_INET6); 234 } else { 235 builder.addPcscfServerRequest(req.address); 236 } 237 break; 238 default: 239 throw new IllegalArgumentException( 240 "Unrecognized config request type: " + req.type); 241 } 242 } 243 244 // Clear IKE Options that are by default enabled 245 for (int option : IKE_OPTIONS) { 246 if (isIkeOptionValid(option)) { 247 builder.removeIkeOption(option); 248 } 249 } 250 251 final int[] optionArray = in.getIntArray(IKE_OPTIONS_KEY); 252 for (int option : optionArray) { 253 if (isIkeOptionValid(option)) { 254 builder.addIkeOption(option); 255 } 256 } 257 258 return builder.build(); 259 } 260 261 private static final class AuthConfigUtils { 262 private static final int IKE_AUTH_METHOD_PSK = 1; 263 private static final int IKE_AUTH_METHOD_PUB_KEY_SIGNATURE = 2; 264 private static final int IKE_AUTH_METHOD_EAP = 3; 265 266 private static final String AUTH_METHOD_KEY = "AUTH_METHOD_KEY"; 267 268 @NonNull toPersistableBundle(@onNull IkeAuthConfig authConfig)269 public static PersistableBundle toPersistableBundle(@NonNull IkeAuthConfig authConfig) { 270 if (authConfig instanceof IkeAuthPskConfig) { 271 IkeAuthPskConfig config = (IkeAuthPskConfig) authConfig; 272 return IkeAuthPskConfigUtils.toPersistableBundle( 273 config, createPersistableBundle(IKE_AUTH_METHOD_PSK)); 274 } else if (authConfig instanceof IkeAuthDigitalSignLocalConfig) { 275 IkeAuthDigitalSignLocalConfig config = (IkeAuthDigitalSignLocalConfig) authConfig; 276 return IkeAuthDigitalSignConfigUtils.toPersistableBundle( 277 config, createPersistableBundle(IKE_AUTH_METHOD_PUB_KEY_SIGNATURE)); 278 } else if (authConfig instanceof IkeAuthDigitalSignRemoteConfig) { 279 IkeAuthDigitalSignRemoteConfig config = (IkeAuthDigitalSignRemoteConfig) authConfig; 280 return IkeAuthDigitalSignConfigUtils.toPersistableBundle( 281 config, createPersistableBundle(IKE_AUTH_METHOD_PUB_KEY_SIGNATURE)); 282 } else if (authConfig instanceof IkeAuthEapConfig) { 283 IkeAuthEapConfig config = (IkeAuthEapConfig) authConfig; 284 return IkeAuthEapConfigUtils.toPersistableBundle( 285 config, createPersistableBundle(IKE_AUTH_METHOD_EAP)); 286 } else { 287 throw new IllegalStateException("Invalid IkeAuthConfig subclass"); 288 } 289 } 290 createPersistableBundle(int type)291 private static PersistableBundle createPersistableBundle(int type) { 292 final PersistableBundle result = new PersistableBundle(); 293 result.putInt(AUTH_METHOD_KEY, type); 294 return result; 295 } 296 setBuilderByReadingPersistableBundle( @onNull PersistableBundle localAuthBundle, @NonNull PersistableBundle remoteAuthBundle, @NonNull IkeSessionParams.Builder builder)297 public static void setBuilderByReadingPersistableBundle( 298 @NonNull PersistableBundle localAuthBundle, 299 @NonNull PersistableBundle remoteAuthBundle, 300 @NonNull IkeSessionParams.Builder builder) { 301 Objects.requireNonNull(localAuthBundle, "localAuthBundle was null"); 302 Objects.requireNonNull(remoteAuthBundle, "remoteAuthBundle was null"); 303 304 final int localMethodType = localAuthBundle.getInt(AUTH_METHOD_KEY); 305 final int remoteMethodType = remoteAuthBundle.getInt(AUTH_METHOD_KEY); 306 switch (localMethodType) { 307 case IKE_AUTH_METHOD_PSK: 308 if (remoteMethodType != IKE_AUTH_METHOD_PSK) { 309 throw new IllegalArgumentException( 310 "Expect remote auth method to be PSK based, but was " 311 + remoteMethodType); 312 } 313 IkeAuthPskConfigUtils.setBuilderByReadingPersistableBundle( 314 localAuthBundle, remoteAuthBundle, builder); 315 return; 316 case IKE_AUTH_METHOD_PUB_KEY_SIGNATURE: 317 if (remoteMethodType != IKE_AUTH_METHOD_PUB_KEY_SIGNATURE) { 318 throw new IllegalArgumentException( 319 "Expect remote auth method to be digital signature based, but was " 320 + remoteMethodType); 321 } 322 IkeAuthDigitalSignConfigUtils.setBuilderByReadingPersistableBundle( 323 localAuthBundle, remoteAuthBundle, builder); 324 return; 325 case IKE_AUTH_METHOD_EAP: 326 if (remoteMethodType != IKE_AUTH_METHOD_PUB_KEY_SIGNATURE) { 327 throw new IllegalArgumentException( 328 "When using EAP for local authentication, expect remote auth" 329 + " method to be digital signature based, but was " 330 + remoteMethodType); 331 } 332 IkeAuthEapConfigUtils.setBuilderByReadingPersistableBundle( 333 localAuthBundle, remoteAuthBundle, builder); 334 return; 335 default: 336 throw new IllegalArgumentException( 337 "Invalid EAP method type " + localMethodType); 338 } 339 } 340 } 341 342 private static final class IkeAuthPskConfigUtils { 343 private static final String PSK_KEY = "PSK_KEY"; 344 345 @NonNull toPersistableBundle( @onNull IkeAuthPskConfig config, @NonNull PersistableBundle result)346 public static PersistableBundle toPersistableBundle( 347 @NonNull IkeAuthPskConfig config, @NonNull PersistableBundle result) { 348 result.putPersistableBundle( 349 PSK_KEY, PersistableBundleUtils.fromByteArray(config.getPsk())); 350 return result; 351 } 352 setBuilderByReadingPersistableBundle( @onNull PersistableBundle localAuthBundle, @NonNull PersistableBundle remoteAuthBundle, @NonNull IkeSessionParams.Builder builder)353 public static void setBuilderByReadingPersistableBundle( 354 @NonNull PersistableBundle localAuthBundle, 355 @NonNull PersistableBundle remoteAuthBundle, 356 @NonNull IkeSessionParams.Builder builder) { 357 Objects.requireNonNull(localAuthBundle, "localAuthBundle was null"); 358 Objects.requireNonNull(remoteAuthBundle, "remoteAuthBundle was null"); 359 360 final PersistableBundle localPskBundle = localAuthBundle.getPersistableBundle(PSK_KEY); 361 final PersistableBundle remotePskBundle = 362 remoteAuthBundle.getPersistableBundle(PSK_KEY); 363 Objects.requireNonNull(localAuthBundle, "Local PSK was null"); 364 Objects.requireNonNull(remoteAuthBundle, "Remote PSK was null"); 365 366 final byte[] localPsk = PersistableBundleUtils.toByteArray(localPskBundle); 367 final byte[] remotePsk = PersistableBundleUtils.toByteArray(remotePskBundle); 368 if (!Arrays.equals(localPsk, remotePsk)) { 369 throw new IllegalArgumentException("Local PSK and remote PSK are different"); 370 } 371 builder.setAuthPsk(localPsk); 372 } 373 } 374 375 private static class IkeAuthDigitalSignConfigUtils { 376 private static final String END_CERT_KEY = "END_CERT_KEY"; 377 private static final String INTERMEDIATE_CERTS_KEY = "INTERMEDIATE_CERTS_KEY"; 378 private static final String PRIVATE_KEY_KEY = "PRIVATE_KEY_KEY"; 379 private static final String TRUST_CERT_KEY = "TRUST_CERT_KEY"; 380 381 @NonNull toPersistableBundle( @onNull IkeAuthDigitalSignLocalConfig config, @NonNull PersistableBundle result)382 public static PersistableBundle toPersistableBundle( 383 @NonNull IkeAuthDigitalSignLocalConfig config, @NonNull PersistableBundle result) { 384 try { 385 result.putPersistableBundle( 386 END_CERT_KEY, 387 PersistableBundleUtils.fromByteArray( 388 config.getClientEndCertificate().getEncoded())); 389 390 final List<X509Certificate> certList = config.getIntermediateCertificates(); 391 final List<byte[]> encodedCertList = new ArrayList<>(certList.size()); 392 for (X509Certificate cert : certList) { 393 encodedCertList.add(cert.getEncoded()); 394 } 395 396 final PersistableBundle certsBundle = 397 PersistableBundleUtils.fromList( 398 encodedCertList, PersistableBundleUtils::fromByteArray); 399 result.putPersistableBundle(INTERMEDIATE_CERTS_KEY, certsBundle); 400 } catch (CertificateEncodingException e) { 401 throw new IllegalArgumentException("Fail to encode certificate"); 402 } 403 404 // TODO: b/170670506 Consider putting PrivateKey in Android KeyStore 405 result.putPersistableBundle( 406 PRIVATE_KEY_KEY, 407 PersistableBundleUtils.fromByteArray(config.getPrivateKey().getEncoded())); 408 return result; 409 } 410 411 @NonNull toPersistableBundle( @onNull IkeAuthDigitalSignRemoteConfig config, @NonNull PersistableBundle result)412 public static PersistableBundle toPersistableBundle( 413 @NonNull IkeAuthDigitalSignRemoteConfig config, @NonNull PersistableBundle result) { 414 try { 415 X509Certificate caCert = config.getRemoteCaCert(); 416 if (caCert != null) { 417 result.putPersistableBundle( 418 TRUST_CERT_KEY, 419 PersistableBundleUtils.fromByteArray(caCert.getEncoded())); 420 } 421 } catch (CertificateEncodingException e) { 422 throw new IllegalArgumentException("Fail to encode the certificate"); 423 } 424 425 return result; 426 } 427 setBuilderByReadingPersistableBundle( @onNull PersistableBundle localAuthBundle, @NonNull PersistableBundle remoteAuthBundle, @NonNull IkeSessionParams.Builder builder)428 public static void setBuilderByReadingPersistableBundle( 429 @NonNull PersistableBundle localAuthBundle, 430 @NonNull PersistableBundle remoteAuthBundle, 431 @NonNull IkeSessionParams.Builder builder) { 432 Objects.requireNonNull(localAuthBundle, "localAuthBundle was null"); 433 Objects.requireNonNull(remoteAuthBundle, "remoteAuthBundle was null"); 434 435 // Deserialize localAuth 436 final PersistableBundle endCertBundle = 437 localAuthBundle.getPersistableBundle(END_CERT_KEY); 438 Objects.requireNonNull(endCertBundle, "End cert was null"); 439 final byte[] encodedCert = PersistableBundleUtils.toByteArray(endCertBundle); 440 final X509Certificate endCert = CertUtils.certificateFromByteArray(encodedCert); 441 442 final PersistableBundle certsBundle = 443 localAuthBundle.getPersistableBundle(INTERMEDIATE_CERTS_KEY); 444 Objects.requireNonNull(certsBundle, "Intermediate certs was null"); 445 final List<byte[]> encodedCertList = 446 PersistableBundleUtils.toList(certsBundle, PersistableBundleUtils::toByteArray); 447 final List<X509Certificate> certList = new ArrayList<>(encodedCertList.size()); 448 for (byte[] encoded : encodedCertList) { 449 certList.add(CertUtils.certificateFromByteArray(encoded)); 450 } 451 452 final PersistableBundle privateKeyBundle = 453 localAuthBundle.getPersistableBundle(PRIVATE_KEY_KEY); 454 Objects.requireNonNull(privateKeyBundle, "PrivateKey bundle was null"); 455 final PrivateKey privateKey = 456 CertUtils.privateKeyFromByteArray( 457 PersistableBundleUtils.toByteArray(privateKeyBundle)); 458 459 // Deserialize remoteAuth 460 final PersistableBundle trustCertBundle = 461 remoteAuthBundle.getPersistableBundle(TRUST_CERT_KEY); 462 463 X509Certificate caCert = null; 464 if (trustCertBundle != null) { 465 final byte[] encodedCaCert = PersistableBundleUtils.toByteArray(trustCertBundle); 466 caCert = CertUtils.certificateFromByteArray(encodedCaCert); 467 } 468 469 builder.setAuthDigitalSignature(caCert, endCert, certList, privateKey); 470 } 471 } 472 473 private static final class IkeAuthEapConfigUtils { 474 private static final String EAP_CONFIG_KEY = "EAP_CONFIG_KEY"; 475 476 @NonNull toPersistableBundle( @onNull IkeAuthEapConfig config, @NonNull PersistableBundle result)477 public static PersistableBundle toPersistableBundle( 478 @NonNull IkeAuthEapConfig config, @NonNull PersistableBundle result) { 479 result.putPersistableBundle( 480 EAP_CONFIG_KEY, 481 EapSessionConfigUtils.toPersistableBundle(config.getEapConfig())); 482 return result; 483 } 484 setBuilderByReadingPersistableBundle( @onNull PersistableBundle localAuthBundle, @NonNull PersistableBundle remoteAuthBundle, @NonNull IkeSessionParams.Builder builder)485 public static void setBuilderByReadingPersistableBundle( 486 @NonNull PersistableBundle localAuthBundle, 487 @NonNull PersistableBundle remoteAuthBundle, 488 @NonNull IkeSessionParams.Builder builder) { 489 // Deserialize localAuth 490 final PersistableBundle eapBundle = 491 localAuthBundle.getPersistableBundle(EAP_CONFIG_KEY); 492 Objects.requireNonNull(eapBundle, "EAP Config was null"); 493 final EapSessionConfig eapConfig = 494 EapSessionConfigUtils.fromPersistableBundle(eapBundle); 495 496 // Deserialize remoteAuth 497 final PersistableBundle trustCertBundle = 498 remoteAuthBundle.getPersistableBundle( 499 IkeAuthDigitalSignConfigUtils.TRUST_CERT_KEY); 500 501 X509Certificate serverCaCert = null; 502 if (trustCertBundle != null) { 503 final byte[] encodedCaCert = PersistableBundleUtils.toByteArray(trustCertBundle); 504 serverCaCert = CertUtils.certificateFromByteArray(encodedCaCert); 505 } 506 builder.setAuthEap(serverCaCert, eapConfig); 507 } 508 } 509 510 private static final class ConfigRequest { 511 private static final int IPV4_P_CSCF_ADDRESS = 1; 512 private static final int IPV6_P_CSCF_ADDRESS = 2; 513 514 private static final String TYPE_KEY = "type"; 515 private static final String ADDRESS_KEY = "address"; 516 517 public final int type; 518 519 // Null when it is an empty request 520 @Nullable public final InetAddress address; 521 ConfigRequest(IkeConfigRequest config)522 ConfigRequest(IkeConfigRequest config) { 523 if (config instanceof ConfigRequestIpv4PcscfServer) { 524 type = IPV4_P_CSCF_ADDRESS; 525 address = ((ConfigRequestIpv4PcscfServer) config).getAddress(); 526 } else if (config instanceof ConfigRequestIpv6PcscfServer) { 527 type = IPV6_P_CSCF_ADDRESS; 528 address = ((ConfigRequestIpv6PcscfServer) config).getAddress(); 529 } else { 530 throw new IllegalStateException("Unknown TunnelModeChildConfigRequest"); 531 } 532 } 533 ConfigRequest(PersistableBundle in)534 ConfigRequest(PersistableBundle in) { 535 Objects.requireNonNull(in, "PersistableBundle was null"); 536 537 type = in.getInt(TYPE_KEY); 538 539 String addressStr = in.getString(ADDRESS_KEY); 540 if (addressStr == null) { 541 address = null; 542 } else { 543 address = InetAddresses.parseNumericAddress(addressStr); 544 } 545 } 546 547 @NonNull toPersistableBundle()548 public PersistableBundle toPersistableBundle() { 549 final PersistableBundle result = new PersistableBundle(); 550 551 result.putInt(TYPE_KEY, type); 552 if (address != null) { 553 result.putString(ADDRESS_KEY, address.getHostAddress()); 554 } 555 556 return result; 557 } 558 } 559 } 560