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 20 import static com.android.internal.annotations.VisibleForTesting.Visibility; 21 22 import android.annotation.NonNull; 23 import android.net.eap.EapSessionConfig; 24 import android.net.eap.EapSessionConfig.EapAkaConfig; 25 import android.net.eap.EapSessionConfig.EapAkaPrimeConfig; 26 import android.net.eap.EapSessionConfig.EapMethodConfig; 27 import android.net.eap.EapSessionConfig.EapMsChapV2Config; 28 import android.net.eap.EapSessionConfig.EapSimConfig; 29 import android.net.eap.EapSessionConfig.EapTtlsConfig; 30 import android.net.eap.EapSessionConfig.EapUiccConfig; 31 import android.os.PersistableBundle; 32 33 import com.android.internal.annotations.VisibleForTesting; 34 import com.android.server.vcn.util.PersistableBundleUtils; 35 36 import java.security.cert.CertificateEncodingException; 37 import java.security.cert.X509Certificate; 38 import java.util.Objects; 39 40 /** 41 * Provides utility methods to convert EapSessionConfig to/from PersistableBundle. 42 * 43 * @hide 44 */ 45 @VisibleForTesting(visibility = Visibility.PRIVATE) 46 public final class EapSessionConfigUtils { 47 private static final String EAP_ID_KEY = "EAP_ID_KEY"; 48 private static final String EAP_SIM_CONFIG_KEY = "EAP_SIM_CONFIG_KEY"; 49 private static final String EAP_TTLS_CONFIG_KEY = "EAP_TTLS_CONFIG_KEY"; 50 private static final String EAP_AKA_CONFIG_KEY = "EAP_AKA_CONFIG_KEY"; 51 private static final String EAP_MSCHAP_V2_CONFIG_KEY = "EAP_MSCHAP_V2_CONFIG_KEY"; 52 private static final String EAP_AKA_PRIME_CONFIG_KEY = "EAP_AKA_PRIME_CONFIG_KEY"; 53 54 /** Serializes an EapSessionConfig to a PersistableBundle. */ 55 @NonNull toPersistableBundle(@onNull EapSessionConfig config)56 public static PersistableBundle toPersistableBundle(@NonNull EapSessionConfig config) { 57 final PersistableBundle result = new PersistableBundle(); 58 59 result.putPersistableBundle( 60 EAP_ID_KEY, PersistableBundleUtils.fromByteArray(config.getEapIdentity())); 61 62 if (config.getEapSimConfig() != null) { 63 result.putPersistableBundle( 64 EAP_SIM_CONFIG_KEY, 65 EapSimConfigUtils.toPersistableBundle(config.getEapSimConfig())); 66 } 67 68 if (config.getEapTtlsConfig() != null) { 69 result.putPersistableBundle( 70 EAP_TTLS_CONFIG_KEY, 71 EapTtlsConfigUtils.toPersistableBundle(config.getEapTtlsConfig())); 72 } 73 74 if (config.getEapAkaConfig() != null) { 75 result.putPersistableBundle( 76 EAP_AKA_CONFIG_KEY, 77 EapAkaConfigUtils.toPersistableBundle(config.getEapAkaConfig())); 78 } 79 80 if (config.getEapMsChapV2Config() != null) { 81 result.putPersistableBundle( 82 EAP_MSCHAP_V2_CONFIG_KEY, 83 EapMsChapV2ConfigUtils.toPersistableBundle(config.getEapMsChapV2Config())); 84 } 85 86 if (config.getEapAkaPrimeConfig() != null) { 87 result.putPersistableBundle( 88 EAP_AKA_PRIME_CONFIG_KEY, 89 EapAkaPrimeConfigUtils.toPersistableBundle(config.getEapAkaPrimeConfig())); 90 } 91 92 return result; 93 } 94 95 /** Constructs an EapSessionConfig by deserializing a PersistableBundle. */ 96 @NonNull fromPersistableBundle(@onNull PersistableBundle in)97 public static EapSessionConfig fromPersistableBundle(@NonNull PersistableBundle in) { 98 Objects.requireNonNull(in, "PersistableBundle was null"); 99 100 final EapSessionConfig.Builder builder = new EapSessionConfig.Builder(); 101 102 final PersistableBundle eapIdBundle = in.getPersistableBundle(EAP_ID_KEY); 103 Objects.requireNonNull(eapIdBundle, "EAP ID was null"); 104 builder.setEapIdentity(PersistableBundleUtils.toByteArray(eapIdBundle)); 105 106 final PersistableBundle simBundle = in.getPersistableBundle(EAP_SIM_CONFIG_KEY); 107 if (simBundle != null) { 108 EapSimConfigUtils.setBuilderByReadingPersistableBundle(simBundle, builder); 109 } 110 111 final PersistableBundle ttlsBundle = in.getPersistableBundle(EAP_TTLS_CONFIG_KEY); 112 if (ttlsBundle != null) { 113 EapTtlsConfigUtils.setBuilderByReadingPersistableBundle(ttlsBundle, builder); 114 } 115 116 final PersistableBundle akaBundle = in.getPersistableBundle(EAP_AKA_CONFIG_KEY); 117 if (akaBundle != null) { 118 EapAkaConfigUtils.setBuilderByReadingPersistableBundle(akaBundle, builder); 119 } 120 121 final PersistableBundle msChapV2Bundle = in.getPersistableBundle(EAP_MSCHAP_V2_CONFIG_KEY); 122 if (msChapV2Bundle != null) { 123 EapMsChapV2ConfigUtils.setBuilderByReadingPersistableBundle(msChapV2Bundle, builder); 124 } 125 126 final PersistableBundle akaPrimeBundle = in.getPersistableBundle(EAP_AKA_PRIME_CONFIG_KEY); 127 if (akaPrimeBundle != null) { 128 EapAkaPrimeConfigUtils.setBuilderByReadingPersistableBundle(akaPrimeBundle, builder); 129 } 130 131 return builder.build(); 132 } 133 134 private static class EapMethodConfigUtils { 135 private static final String METHOD_TYPE = "METHOD_TYPE"; 136 137 /** Serializes an EapMethodConfig to a PersistableBundle. */ 138 @NonNull toPersistableBundle(@onNull EapMethodConfig config)139 public static PersistableBundle toPersistableBundle(@NonNull EapMethodConfig config) { 140 final PersistableBundle result = new PersistableBundle(); 141 result.putInt(METHOD_TYPE, config.getMethodType()); 142 return result; 143 } 144 } 145 146 private static class EapUiccConfigUtils extends EapMethodConfigUtils { 147 static final String SUB_ID_KEY = "SUB_ID_KEY"; 148 static final String APP_TYPE_KEY = "APP_TYPE_KEY"; 149 150 @NonNull toPersistableBundle(@onNull EapUiccConfig config)151 protected static PersistableBundle toPersistableBundle(@NonNull EapUiccConfig config) { 152 final PersistableBundle result = EapMethodConfigUtils.toPersistableBundle(config); 153 result.putInt(SUB_ID_KEY, config.getSubId()); 154 result.putInt(APP_TYPE_KEY, config.getAppType()); 155 156 return result; 157 } 158 } 159 160 private static final class EapSimConfigUtils extends EapUiccConfigUtils { 161 @NonNull toPersistableBundle(EapSimConfig config)162 public static PersistableBundle toPersistableBundle(EapSimConfig config) { 163 return EapUiccConfigUtils.toPersistableBundle(config); 164 } 165 setBuilderByReadingPersistableBundle( @onNull PersistableBundle in, @NonNull EapSessionConfig.Builder builder)166 public static void setBuilderByReadingPersistableBundle( 167 @NonNull PersistableBundle in, @NonNull EapSessionConfig.Builder builder) { 168 Objects.requireNonNull(in, "PersistableBundle was null"); 169 builder.setEapSimConfig(in.getInt(SUB_ID_KEY), in.getInt(APP_TYPE_KEY)); 170 } 171 } 172 173 private static class EapAkaConfigUtils extends EapUiccConfigUtils { 174 @NonNull toPersistableBundle(@onNull EapAkaConfig config)175 public static PersistableBundle toPersistableBundle(@NonNull EapAkaConfig config) { 176 return EapUiccConfigUtils.toPersistableBundle(config); 177 } 178 setBuilderByReadingPersistableBundle( @onNull PersistableBundle in, @NonNull EapSessionConfig.Builder builder)179 public static void setBuilderByReadingPersistableBundle( 180 @NonNull PersistableBundle in, @NonNull EapSessionConfig.Builder builder) { 181 Objects.requireNonNull(in, "PersistableBundle was null"); 182 builder.setEapAkaConfig(in.getInt(SUB_ID_KEY), in.getInt(APP_TYPE_KEY)); 183 } 184 } 185 186 private static final class EapAkaPrimeConfigUtils extends EapAkaConfigUtils { 187 private static final String NETWORK_NAME_KEY = "NETWORK_NAME_KEY"; 188 private static final String ALL_MISMATCHED_NETWORK_KEY = "ALL_MISMATCHED_NETWORK_KEY"; 189 190 @NonNull toPersistableBundle(@onNull EapAkaPrimeConfig config)191 public static PersistableBundle toPersistableBundle(@NonNull EapAkaPrimeConfig config) { 192 final PersistableBundle result = EapUiccConfigUtils.toPersistableBundle(config); 193 result.putString(NETWORK_NAME_KEY, config.getNetworkName()); 194 result.putBoolean(ALL_MISMATCHED_NETWORK_KEY, config.allowsMismatchedNetworkNames()); 195 196 return result; 197 } 198 setBuilderByReadingPersistableBundle( @onNull PersistableBundle in, @NonNull EapSessionConfig.Builder builder)199 public static void setBuilderByReadingPersistableBundle( 200 @NonNull PersistableBundle in, @NonNull EapSessionConfig.Builder builder) { 201 Objects.requireNonNull(in, "PersistableBundle was null"); 202 builder.setEapAkaPrimeConfig( 203 in.getInt(SUB_ID_KEY), 204 in.getInt(APP_TYPE_KEY), 205 in.getString(NETWORK_NAME_KEY), 206 in.getBoolean(ALL_MISMATCHED_NETWORK_KEY)); 207 } 208 } 209 210 private static final class EapMsChapV2ConfigUtils extends EapMethodConfigUtils { 211 private static final String USERNAME_KEY = "USERNAME_KEY"; 212 private static final String PASSWORD_KEY = "PASSWORD_KEY"; 213 214 @NonNull toPersistableBundle(@onNull EapMsChapV2Config config)215 public static PersistableBundle toPersistableBundle(@NonNull EapMsChapV2Config config) { 216 final PersistableBundle result = EapMethodConfigUtils.toPersistableBundle(config); 217 result.putString(USERNAME_KEY, config.getUsername()); 218 result.putString(PASSWORD_KEY, config.getPassword()); 219 220 return result; 221 } 222 setBuilderByReadingPersistableBundle( @onNull PersistableBundle in, @NonNull EapSessionConfig.Builder builder)223 public static void setBuilderByReadingPersistableBundle( 224 @NonNull PersistableBundle in, @NonNull EapSessionConfig.Builder builder) { 225 Objects.requireNonNull(in, "PersistableBundle was null"); 226 builder.setEapMsChapV2Config(in.getString(USERNAME_KEY), in.getString(PASSWORD_KEY)); 227 } 228 } 229 230 private static final class EapTtlsConfigUtils extends EapMethodConfigUtils { 231 private static final String TRUST_CERT_KEY = "TRUST_CERT_KEY"; 232 private static final String EAP_SESSION_CONFIG_KEY = "EAP_SESSION_CONFIG_KEY"; 233 234 @NonNull toPersistableBundle(@onNull EapTtlsConfig config)235 public static PersistableBundle toPersistableBundle(@NonNull EapTtlsConfig config) { 236 final PersistableBundle result = EapMethodConfigUtils.toPersistableBundle(config); 237 try { 238 if (config.getServerCaCert() != null) { 239 final PersistableBundle caBundle = 240 PersistableBundleUtils.fromByteArray( 241 config.getServerCaCert().getEncoded()); 242 result.putPersistableBundle(TRUST_CERT_KEY, caBundle); 243 } 244 } catch (CertificateEncodingException e) { 245 throw new IllegalStateException("Fail to encode the certificate"); 246 } 247 248 result.putPersistableBundle( 249 EAP_SESSION_CONFIG_KEY, 250 EapSessionConfigUtils.toPersistableBundle(config.getInnerEapSessionConfig())); 251 252 return result; 253 } 254 setBuilderByReadingPersistableBundle( @onNull PersistableBundle in, @NonNull EapSessionConfig.Builder builder)255 public static void setBuilderByReadingPersistableBundle( 256 @NonNull PersistableBundle in, @NonNull EapSessionConfig.Builder builder) { 257 Objects.requireNonNull(in, "PersistableBundle was null"); 258 259 final PersistableBundle caBundle = in.getPersistableBundle(TRUST_CERT_KEY); 260 X509Certificate caCert = null; 261 if (caBundle != null) { 262 caCert = 263 CertUtils.certificateFromByteArray( 264 PersistableBundleUtils.toByteArray(caBundle)); 265 } 266 267 final PersistableBundle eapSessionConfigBundle = 268 in.getPersistableBundle(EAP_SESSION_CONFIG_KEY); 269 Objects.requireNonNull(eapSessionConfigBundle, "Inner EAP Session Config was null"); 270 final EapSessionConfig eapSessionConfig = 271 EapSessionConfigUtils.fromPersistableBundle(eapSessionConfigBundle); 272 273 builder.setEapTtlsConfig(caCert, eapSessionConfig); 274 } 275 } 276 } 277