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