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 import static android.net.ipsec.ike.ike3gpp.Ike3gppBackoffTimer.isValidErrorNotifyCause; 20 21 import static com.android.internal.net.ipsec.ike.ike3gpp.Ike3gppExtensionExchange.NOTIFY_TYPE_BACKOFF_TIMER; 22 import static com.android.internal.net.ipsec.ike.ike3gpp.Ike3gppExtensionExchange.NOTIFY_TYPE_DEVICE_IDENTITY; 23 import static com.android.internal.net.ipsec.ike.ike3gpp.Ike3gppExtensionExchange.NOTIFY_TYPE_N1_MODE_INFORMATION; 24 25 import android.annotation.NonNull; 26 import android.net.ipsec.ike.exceptions.InvalidSyntaxException; 27 import android.net.ipsec.ike.ike3gpp.Ike3gppBackoffTimer; 28 import android.net.ipsec.ike.ike3gpp.Ike3gppData; 29 import android.net.ipsec.ike.ike3gpp.Ike3gppExtension; 30 import android.net.ipsec.ike.ike3gpp.Ike3gppN1ModeInformation; 31 import android.util.ArraySet; 32 33 import com.android.internal.net.ipsec.ike.message.IkeNotifyPayload; 34 import com.android.internal.net.ipsec.ike.message.IkePayload; 35 36 import java.util.ArrayList; 37 import java.util.List; 38 import java.util.Set; 39 import java.util.concurrent.Executor; 40 41 /** 42 * Ike3gppIkeAuth contains the implementation for IKE_AUTH 3GPP-specific functionality in IKEv2. 43 * 44 * <p>This class is package-private. 45 */ 46 class Ike3gppIkeAuth extends Ike3gppExchangeBase { 47 private static final String TAG = Ike3gppIkeAuth.class.getSimpleName(); 48 private static final Set<Integer> SUPPORTED_RESPONSE_NOTIFY_TYPES = new ArraySet<>(); 49 private boolean mIsDeviceIdentityRequestedByNetwork; 50 51 static { 52 SUPPORTED_RESPONSE_NOTIFY_TYPES.add(NOTIFY_TYPE_N1_MODE_INFORMATION); 53 SUPPORTED_RESPONSE_NOTIFY_TYPES.add(NOTIFY_TYPE_BACKOFF_TIMER); 54 SUPPORTED_RESPONSE_NOTIFY_TYPES.add(NOTIFY_TYPE_DEVICE_IDENTITY); 55 } 56 57 /** Initializes an Ike3gppIkeAuth. */ Ike3gppIkeAuth(@onNull Ike3gppExtension ike3gppExtension, @NonNull Executor userCbExecutor)58 Ike3gppIkeAuth(@NonNull Ike3gppExtension ike3gppExtension, @NonNull Executor userCbExecutor) { 59 super(ike3gppExtension, userCbExecutor); 60 } 61 62 /** Provides a list of 3GPP payloads to add in the outbound EAP AUTH REQ. */ getRequestPayloadsInEap(boolean serverAuthenticated)63 List<IkePayload> getRequestPayloadsInEap(boolean serverAuthenticated) { 64 List<IkePayload> ike3gppPayloads = new ArrayList<>(); 65 66 if (mIsDeviceIdentityRequestedByNetwork && serverAuthenticated) { 67 String deviceIdentity = mIke3gppExtension.getIke3gppParams().getMobileDeviceIdentity(); 68 if (deviceIdentity != null) { 69 ike3gppPayloads.add( 70 Ike3gppDeviceIdentityUtils.generateDeviceIdentityPayload(deviceIdentity)); 71 } 72 } 73 return ike3gppPayloads; 74 } 75 getRequestPayloads()76 List<IkePayload> getRequestPayloads() { 77 List<IkePayload> ike3gppPayloads = new ArrayList<>(); 78 if (mIke3gppExtension.getIke3gppParams().hasPduSessionId()) { 79 ike3gppPayloads.add( 80 Ike3gppN1ModeUtils.generateN1ModeCapabilityPayload( 81 mIke3gppExtension.getIke3gppParams().getPduSessionId())); 82 } 83 84 return ike3gppPayloads; 85 } 86 extract3gppResponsePayloads(List<IkePayload> payloads)87 List<IkePayload> extract3gppResponsePayloads(List<IkePayload> payloads) { 88 List<IkePayload> ike3gppPayloads = new ArrayList<>(); 89 90 for (IkePayload payload : payloads) { 91 switch (payload.payloadType) { 92 case IkePayload.PAYLOAD_TYPE_NOTIFY: 93 IkeNotifyPayload notifyPayload = (IkeNotifyPayload) payload; 94 if (SUPPORTED_RESPONSE_NOTIFY_TYPES.contains(notifyPayload.notifyType) 95 || isValidErrorNotifyCause(notifyPayload)) { 96 ike3gppPayloads.add(notifyPayload); 97 } 98 break; 99 default: 100 // not a 3GPP-specific payload 101 break; 102 } 103 } 104 105 return ike3gppPayloads; 106 } 107 handleAuthResp(List<IkePayload> ike3gppPayloads)108 void handleAuthResp(List<IkePayload> ike3gppPayloads) throws InvalidSyntaxException { 109 List<Ike3gppData> ike3gppDataList = new ArrayList<>(); 110 List<IkeNotifyPayload> notifyPayloads = 111 IkePayload.getPayloadListForTypeInProvidedList( 112 IkePayload.PAYLOAD_TYPE_NOTIFY, IkeNotifyPayload.class, ike3gppPayloads); 113 114 IkeNotifyPayload backoffTimerPayload = null; 115 IkeNotifyPayload backoffTimerCause = null; 116 for (IkeNotifyPayload notifyPayload : notifyPayloads) { 117 switch (notifyPayload.notifyType) { 118 case NOTIFY_TYPE_N1_MODE_INFORMATION: 119 // N1_MODE_CAPABILITY must be configured for the client to be notified 120 if (!mIke3gppExtension.getIke3gppParams().hasPduSessionId()) { 121 logw("Received N1_MODE_INFORMATION when N1 Mode is not enabled"); 122 continue; 123 } 124 125 byte[] snssai = 126 Ike3gppN1ModeUtils.getSnssaiFromNotifyData(notifyPayload.notifyData); 127 ike3gppDataList.add(new Ike3gppN1ModeInformation(snssai)); 128 break; 129 case NOTIFY_TYPE_BACKOFF_TIMER: 130 backoffTimerPayload = notifyPayload; 131 break; 132 case NOTIFY_TYPE_DEVICE_IDENTITY: 133 mIsDeviceIdentityRequestedByNetwork = true; 134 break; 135 default: 136 if (isValidErrorNotifyCause(notifyPayload)) { 137 if (backoffTimerCause == null) { 138 backoffTimerCause = notifyPayload; 139 } 140 } else { 141 // non-3GPP payload. Can be ignored. 142 logd( 143 "Non-3GPP payload processed as 3GPP: " 144 + notifyPayload.getTypeString()); 145 } 146 break; 147 } 148 } 149 150 if (backoffTimerPayload != null && backoffTimerCause != null) { 151 byte backoffTimer = 152 Ike3gppBackoffTimerUtils.getBackoffTimerfromNotifyData( 153 backoffTimerPayload.notifyData); 154 ike3gppDataList.add( 155 new Ike3gppBackoffTimer(backoffTimer, backoffTimerCause.notifyType)); 156 } else if (backoffTimerPayload != null) { 157 logw("Received BACKOFF_TIMER payload without an Error-Notify"); 158 } 159 160 maybeInvokeUserCallback(ike3gppDataList); 161 } 162 logd(String msg)163 private void logd(String msg) { 164 getIkeLog().d(TAG, msg); 165 } 166 logw(String msg)167 private void logw(String msg) { 168 getIkeLog().w(TAG, msg); 169 } 170 } 171