1 /* 2 * Copyright (C) 2020 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 package com.android.internal.net.ipsec.ike.ike3gpp; 17 18 import static android.net.ipsec.ike.IkeManager.getIkeLog; 19 20 import static com.android.internal.net.ipsec.ike.message.IkeMessage.IKE_EXCHANGE_SUBTYPE_GENERIC_INFO; 21 import static com.android.internal.net.ipsec.ike.message.IkeMessage.IKE_EXCHANGE_SUBTYPE_IKE_AUTH; 22 23 import android.annotation.NonNull; 24 import android.annotation.Nullable; 25 import android.net.ipsec.ike.exceptions.InvalidSyntaxException; 26 import android.net.ipsec.ike.ike3gpp.Ike3gppExtension; 27 import android.net.ipsec.ike.ike3gpp.Ike3gppExtension.Ike3gppDataListener; 28 import android.util.ArraySet; 29 30 import com.android.internal.net.ipsec.ike.message.IkeMessage; 31 import com.android.internal.net.ipsec.ike.message.IkePayload; 32 33 import java.util.Collections; 34 import java.util.List; 35 import java.util.Objects; 36 import java.util.Set; 37 import java.util.concurrent.Executor; 38 39 /** 40 * Ike3gppExtensionExchange contains the implementation for 3GPP-specific functionality in IKEv2. 41 */ 42 public class Ike3gppExtensionExchange implements AutoCloseable { 43 private static final String TAG = Ike3gppExtensionExchange.class.getSimpleName(); 44 45 private static final Set<Ike3gppDataListener> REGISTERED_LISTENERS = 46 Collections.synchronizedSet(new ArraySet<>()); 47 48 /** 49 * Indicates that the caller must wait the specified time before attempting to open an IKE 50 * Session with the peer. 51 * 52 * <p>Note that this is not an IANA-specified value. 53 * 54 * <p>Must be accompanied by an Error-Notify(ERROR_TYPE_NO_APN_SUBSCRIPTION) or 55 * Error-Notify(ERROR_TYPE_NETWORK_FAILURE); otherwise, the payload will be logged and ignored. 56 */ 57 public static final int NOTIFY_TYPE_BACKOFF_TIMER = 41041; 58 59 /** 60 * Indicates that the UE supports N1 Mode during 5G SA ePDG tunnel setup. 61 * 62 * <p>Note that this is not an IANA-specified value. 63 * 64 * <p>A PDU session ID will be included to indicate the PDU session associated with the IKEv2 65 * SA. 66 * 67 * <p>See TS 124 302 - Universal Mobile Telecommunications System (UMTS); LTE; 5G; Access to the 68 * 3GPP Evolved Packet Core (EPC) via non-3GPP access networks (Section 8.2.9.15) for more 69 * details. 70 */ 71 public static final int NOTIFY_TYPE_N1_MODE_CAPABILITY = 51015; 72 73 /** 74 * Used for reporting the S-NSSAI from the server to the UE for the reported PDU Session ID. 75 * 76 * <p>Note that this is not an IANA-specified value. 77 * 78 * <p>This Payload will only be sent from the server to the user device after {@link 79 * NOTIFY_TYPE_N1_MODE_CAPABILITY} is sent during the IKE_AUTH exchange. 80 * 81 * <p>See TS 124 302 - Universal Mobile Telecommunications System (UMTS); LTE; 5G; Access to the 82 * 3GPP Evolved Packet Core (EPC) via non-3GPP access networks (Section 8.2.9.16) for more 83 * details. 84 */ 85 public static final int NOTIFY_TYPE_N1_MODE_INFORMATION = 51115; 86 87 /** 88 * Used to share the device idenity (IMEI/IMEISV) with the carrier network. 89 * 90 * <p>Note that this is not an IANA-specified value. 91 * 92 * <p>See TS 124 302 - Universal Mobile Telecommunications System (UMTS); LTE; 5G; Access to the 93 * 3GPP Evolved Packet Core (EPC) via non-3GPP access networks (Section 8.2.9.2) for more 94 * details. 95 */ 96 public static final int NOTIFY_TYPE_DEVICE_IDENTITY = 41101; 97 98 @Nullable private final Ike3gppExtension mIke3gppExtension; 99 @NonNull private final Executor mUserCbExecutor; 100 @Nullable private final Ike3gppIkeAuth mIke3gppIkeAuth; 101 @Nullable private final Ike3gppIkeInfo mIke3gppIkeInfo; 102 103 /** 104 * Initializes an Ike3gppExtensionExchange. 105 * 106 * <p>If ike3gppExtension is null, no 3GPP functionality will be enabled. 107 */ Ike3gppExtensionExchange( @ullable Ike3gppExtension ike3gppExtension, @NonNull Executor userCbExecutor)108 public Ike3gppExtensionExchange( 109 @Nullable Ike3gppExtension ike3gppExtension, @NonNull Executor userCbExecutor) { 110 mIke3gppExtension = ike3gppExtension; 111 mUserCbExecutor = Objects.requireNonNull(userCbExecutor, "userCbExecutor must not be null"); 112 113 if (mIke3gppExtension != null) { 114 mIke3gppIkeAuth = new Ike3gppIkeAuth(mIke3gppExtension, mUserCbExecutor); 115 mIke3gppIkeInfo = new Ike3gppIkeInfo(mIke3gppExtension, mUserCbExecutor); 116 117 if (!REGISTERED_LISTENERS.add(ike3gppExtension.getIke3gppDataListener())) { 118 throw new IllegalArgumentException( 119 "Ike3gppDataListener must be unique for each IkeSession"); 120 } 121 122 logd("IKE 3GPP Extension enabled: " + mIke3gppExtension.getIke3gppParams()); 123 } else { 124 mIke3gppIkeAuth = null; 125 mIke3gppIkeInfo = null; 126 } 127 } 128 129 @Override close()130 public void close() { 131 if (mIke3gppExtension == null) return; 132 133 REGISTERED_LISTENERS.remove(mIke3gppExtension.getIke3gppDataListener()); 134 } 135 136 /** 137 * Gets the 3GPP-specific Information Response IkePayloads for the specified exchangeSubtype. 138 */ getResponsePayloads( int exchangeSubtype, List<IkePayload> ike3gppRequestPayloads)139 public List<IkePayload> getResponsePayloads( 140 int exchangeSubtype, List<IkePayload> ike3gppRequestPayloads) { 141 if (mIke3gppExtension == null) return Collections.EMPTY_LIST; 142 143 switch (exchangeSubtype) { 144 case IKE_EXCHANGE_SUBTYPE_GENERIC_INFO: 145 return mIke3gppIkeInfo.getResponsePayloads(ike3gppRequestPayloads); 146 default: 147 // No 3GPP-specific behavior for this exchange subtype 148 return Collections.EMPTY_LIST; 149 } 150 } 151 152 /** Gets the 3GPP-specific Request IkePayloads for the specified exchangeSubtype. */ getRequestPayloads(int exchangeSubtype)153 public List<IkePayload> getRequestPayloads(int exchangeSubtype) { 154 if (mIke3gppExtension == null) return Collections.EMPTY_LIST; 155 156 switch (exchangeSubtype) { 157 case IKE_EXCHANGE_SUBTYPE_IKE_AUTH: 158 return mIke3gppIkeAuth.getRequestPayloads(); 159 default: 160 // No 3GPP-specific behavior for this exchange subtype 161 String exchangeSubtypeString = 162 IkeMessage.getIkeExchangeSubTypeString(exchangeSubtype); 163 logw("No 3GPP request payloads added for: " + exchangeSubtypeString); 164 return Collections.EMPTY_LIST; 165 } 166 } 167 168 /** 169 * Provides a list of 3GPP payloads to add in an outbound AUTH req based on peer authentication 170 * status. 171 */ getRequestPayloadsInEap(boolean serverAuthenticated)172 public List<IkePayload> getRequestPayloadsInEap(boolean serverAuthenticated) { 173 if (mIke3gppExtension == null) return Collections.EMPTY_LIST; 174 return mIke3gppIkeAuth.getRequestPayloadsInEap(serverAuthenticated); 175 } 176 177 /** 178 * Returns a list of 3GPP-specific Response Payloads from the given list that are valid for the 179 * specified exchangeSubtype. 180 */ extract3gppResponsePayloads( int exchangeSubtype, List<IkePayload> payloads)181 public List<IkePayload> extract3gppResponsePayloads( 182 int exchangeSubtype, List<IkePayload> payloads) { 183 if (mIke3gppExtension == null) return Collections.EMPTY_LIST; 184 185 switch (exchangeSubtype) { 186 case IKE_EXCHANGE_SUBTYPE_IKE_AUTH: 187 return mIke3gppIkeAuth.extract3gppResponsePayloads(payloads); 188 default: 189 // No 3GPP-specific behavior for this exchange subtype 190 String exchangeSubtypeString = 191 IkeMessage.getIkeExchangeSubTypeString(exchangeSubtype); 192 logw("No 3GPP response payloads expected for: " + exchangeSubtypeString); 193 return Collections.EMPTY_LIST; 194 } 195 } 196 197 /** 198 * Handles the provided Response IkePayloads for the specified exchangeSubtype. 199 * 200 * <p>If the caller needs to be notified of received Ike3gppData, the configured 201 * Ike3gppDataListener will be invoked. 202 */ handle3gppResponsePayloads(int exchangeSubtype, List<IkePayload> ike3gppPayloads)203 public void handle3gppResponsePayloads(int exchangeSubtype, List<IkePayload> ike3gppPayloads) 204 throws InvalidSyntaxException { 205 if (mIke3gppExtension == null || ike3gppPayloads.isEmpty()) return; 206 207 switch (exchangeSubtype) { 208 case IKE_EXCHANGE_SUBTYPE_IKE_AUTH: 209 mIke3gppIkeAuth.handleAuthResp(ike3gppPayloads); 210 break; 211 default: 212 // No 3GPP-specific behavior for this exchange subtype 213 String exchangeSubtypeString = 214 IkeMessage.getIkeExchangeSubTypeString(exchangeSubtype); 215 logw("Received unexpected 3GPP payloads in: " + exchangeSubtypeString); 216 } 217 } 218 logw(String msg)219 private void logw(String msg) { 220 getIkeLog().w(TAG, msg); 221 } 222 logd(String msg)223 private void logd(String msg) { 224 getIkeLog().d(TAG, msg); 225 } 226 } 227