1 /* 2 * Copyright (C) 2019 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 com.android.internal.net.ipsec.test.ike; 18 19 import static android.net.ipsec.ike.IkeSessionConfiguration.EXTENSION_TYPE_MOBIKE; 20 import static android.net.ipsec.test.ike.IkeSessionConfiguration.EXTENSION_TYPE_FRAGMENTATION; 21 import static android.net.ipsec.test.ike.IkeSessionParams.IKE_OPTION_EAP_ONLY_AUTH; 22 import static android.net.ipsec.test.ike.IkeSessionParams.IKE_OPTION_FORCE_PORT_4500; 23 import static android.net.ipsec.test.ike.IkeSessionParams.IKE_OPTION_MOBIKE; 24 import static android.net.ipsec.test.ike.IkeSessionParams.IKE_OPTION_REKEY_MOBILITY; 25 import static android.net.ipsec.test.ike.exceptions.IkeProtocolException.ERROR_TYPE_AUTHENTICATION_FAILED; 26 import static android.net.ipsec.test.ike.exceptions.IkeProtocolException.ERROR_TYPE_CHILD_SA_NOT_FOUND; 27 import static android.net.ipsec.test.ike.exceptions.IkeProtocolException.ERROR_TYPE_INTERNAL_ADDRESS_FAILURE; 28 import static android.net.ipsec.test.ike.exceptions.IkeProtocolException.ERROR_TYPE_INVALID_KE_PAYLOAD; 29 import static android.net.ipsec.test.ike.exceptions.IkeProtocolException.ERROR_TYPE_INVALID_SYNTAX; 30 import static android.net.ipsec.test.ike.exceptions.IkeProtocolException.ERROR_TYPE_NO_ADDITIONAL_SAS; 31 import static android.net.ipsec.test.ike.exceptions.IkeProtocolException.ERROR_TYPE_NO_PROPOSAL_CHOSEN; 32 import static android.net.ipsec.test.ike.exceptions.IkeProtocolException.ERROR_TYPE_TEMPORARY_FAILURE; 33 import static android.net.ipsec.test.ike.exceptions.IkeProtocolException.ERROR_TYPE_UNSUPPORTED_CRITICAL_PAYLOAD; 34 import static android.net.ipsec.test.ike.ike3gpp.Ike3gppBackoffTimer.ERROR_TYPE_NETWORK_FAILURE; 35 import static android.net.ipsec.test.ike.ike3gpp.Ike3gppBackoffTimer.ERROR_TYPE_NO_APN_SUBSCRIPTION; 36 import static android.system.OsConstants.AF_INET; 37 import static android.system.OsConstants.AF_INET6; 38 39 import static com.android.internal.net.TestUtils.createMockRandomFactory; 40 import static com.android.internal.net.eap.test.EapResult.EapResponse.RESPONSE_FLAG_EAP_AKA_SERVER_AUTHENTICATED; 41 import static com.android.internal.net.ipsec.test.ike.AbstractSessionStateMachine.RETRY_INTERVAL_MS; 42 import static com.android.internal.net.ipsec.test.ike.IkeSessionStateMachine.CMD_ALARM_FIRED; 43 import static com.android.internal.net.ipsec.test.ike.IkeSessionStateMachine.CMD_FORCE_TRANSITION; 44 import static com.android.internal.net.ipsec.test.ike.IkeSessionStateMachine.CMD_RECEIVE_IKE_PACKET; 45 import static com.android.internal.net.ipsec.test.ike.IkeSessionStateMachine.CMD_SEND_KEEPALIVE; 46 import static com.android.internal.net.ipsec.test.ike.IkeSessionStateMachine.IkeAuthData; 47 import static com.android.internal.net.ipsec.test.ike.IkeSessionStateMachine.IkeInitData; 48 import static com.android.internal.net.ipsec.test.ike.IkeSessionStateMachine.InitialSetupData; 49 import static com.android.internal.net.ipsec.test.ike.IkeSessionStateMachine.RETRY_INTERVAL_MS; 50 import static com.android.internal.net.ipsec.test.ike.IkeSessionStateMachine.TEMP_FAILURE_RETRY_TIMEOUT_MS; 51 import static com.android.internal.net.ipsec.test.ike.ike3gpp.Ike3gppExtensionExchange.NOTIFY_TYPE_BACKOFF_TIMER; 52 import static com.android.internal.net.ipsec.test.ike.ike3gpp.Ike3gppExtensionExchange.NOTIFY_TYPE_DEVICE_IDENTITY; 53 import static com.android.internal.net.ipsec.test.ike.ike3gpp.Ike3gppExtensionExchange.NOTIFY_TYPE_N1_MODE_CAPABILITY; 54 import static com.android.internal.net.ipsec.test.ike.ike3gpp.Ike3gppExtensionExchange.NOTIFY_TYPE_N1_MODE_INFORMATION; 55 import static com.android.internal.net.ipsec.test.ike.message.IkeConfigPayload.CONFIG_ATTR_APPLICATION_VERSION; 56 import static com.android.internal.net.ipsec.test.ike.message.IkeConfigPayload.CONFIG_ATTR_INTERNAL_IP4_ADDRESS; 57 import static com.android.internal.net.ipsec.test.ike.message.IkeConfigPayload.CONFIG_ATTR_INTERNAL_IP4_NETMASK; 58 import static com.android.internal.net.ipsec.test.ike.message.IkeConfigPayload.CONFIG_ATTR_INTERNAL_IP6_ADDRESS; 59 import static com.android.internal.net.ipsec.test.ike.message.IkeConfigPayload.CONFIG_ATTR_IP4_PCSCF; 60 import static com.android.internal.net.ipsec.test.ike.message.IkeConfigPayload.CONFIG_ATTR_IP6_PCSCF; 61 import static com.android.internal.net.ipsec.test.ike.message.IkeHeader.EXCHANGE_TYPE_CREATE_CHILD_SA; 62 import static com.android.internal.net.ipsec.test.ike.message.IkeHeader.EXCHANGE_TYPE_INFORMATIONAL; 63 import static com.android.internal.net.ipsec.test.ike.message.IkeMessage.IKE_EXCHANGE_SUBTYPE_DELETE_CHILD; 64 import static com.android.internal.net.ipsec.test.ike.message.IkeMessage.IKE_EXCHANGE_SUBTYPE_REKEY_CHILD; 65 import static com.android.internal.net.ipsec.test.ike.message.IkeNotifyPayload.NOTIFY_TYPE_COOKIE; 66 import static com.android.internal.net.ipsec.test.ike.message.IkeNotifyPayload.NOTIFY_TYPE_COOKIE2; 67 import static com.android.internal.net.ipsec.test.ike.message.IkeNotifyPayload.NOTIFY_TYPE_EAP_ONLY_AUTHENTICATION; 68 import static com.android.internal.net.ipsec.test.ike.message.IkeNotifyPayload.NOTIFY_TYPE_IKEV2_FRAGMENTATION_SUPPORTED; 69 import static com.android.internal.net.ipsec.test.ike.message.IkeNotifyPayload.NOTIFY_TYPE_INITIAL_CONTACT; 70 import static com.android.internal.net.ipsec.test.ike.message.IkeNotifyPayload.NOTIFY_TYPE_MOBIKE_SUPPORTED; 71 import static com.android.internal.net.ipsec.test.ike.message.IkeNotifyPayload.NOTIFY_TYPE_NAT_DETECTION_DESTINATION_IP; 72 import static com.android.internal.net.ipsec.test.ike.message.IkeNotifyPayload.NOTIFY_TYPE_NAT_DETECTION_SOURCE_IP; 73 import static com.android.internal.net.ipsec.test.ike.message.IkeNotifyPayload.NOTIFY_TYPE_SIGNATURE_HASH_ALGORITHMS; 74 import static com.android.internal.net.ipsec.test.ike.message.IkeNotifyPayload.NOTIFY_TYPE_UPDATE_SA_ADDRESSES; 75 import static com.android.internal.net.ipsec.test.ike.message.IkePayload.PAYLOAD_TYPE_AUTH; 76 import static com.android.internal.net.ipsec.test.ike.message.IkePayload.PAYLOAD_TYPE_KE; 77 import static com.android.internal.net.ipsec.test.ike.message.IkePayload.PAYLOAD_TYPE_NONCE; 78 import static com.android.internal.net.ipsec.test.ike.message.IkePayload.PAYLOAD_TYPE_NOTIFY; 79 import static com.android.internal.net.ipsec.test.ike.message.IkePayload.PAYLOAD_TYPE_SA; 80 import static com.android.internal.net.ipsec.test.ike.net.IkeConnectionController.NAT_DETECTED; 81 import static com.android.internal.net.ipsec.test.ike.net.IkeConnectionController.NAT_TRAVERSAL_SUPPORT_NOT_CHECKED; 82 import static com.android.internal.net.ipsec.test.ike.net.IkeConnectionController.NAT_TRAVERSAL_UNSUPPORTED; 83 84 import static org.junit.Assert.assertArrayEquals; 85 import static org.junit.Assert.assertEquals; 86 import static org.junit.Assert.assertFalse; 87 import static org.junit.Assert.assertNotEquals; 88 import static org.junit.Assert.assertNotNull; 89 import static org.junit.Assert.assertNull; 90 import static org.junit.Assert.assertSame; 91 import static org.junit.Assert.assertTrue; 92 import static org.junit.Assert.fail; 93 import static org.mockito.Matchers.any; 94 import static org.mockito.Matchers.anyBoolean; 95 import static org.mockito.Matchers.anyInt; 96 import static org.mockito.Matchers.anyLong; 97 import static org.mockito.Matchers.anyObject; 98 import static org.mockito.Matchers.anyString; 99 import static org.mockito.Matchers.argThat; 100 import static org.mockito.Matchers.eq; 101 import static org.mockito.Mockito.atLeast; 102 import static org.mockito.Mockito.atLeastOnce; 103 import static org.mockito.Mockito.doAnswer; 104 import static org.mockito.Mockito.doNothing; 105 import static org.mockito.Mockito.doReturn; 106 import static org.mockito.Mockito.doThrow; 107 import static org.mockito.Mockito.mock; 108 import static org.mockito.Mockito.never; 109 import static org.mockito.Mockito.reset; 110 import static org.mockito.Mockito.spy; 111 import static org.mockito.Mockito.times; 112 import static org.mockito.Mockito.verify; 113 import static org.mockito.Mockito.when; 114 115 import android.annotation.Nullable; 116 import android.net.LinkAddress; 117 import android.net.LinkProperties; 118 import android.net.Network; 119 import android.net.NetworkCapabilities; 120 import android.net.eap.test.EapAkaInfo; 121 import android.net.eap.test.EapSessionConfig; 122 import android.net.ipsec.test.ike.ChildSaProposal; 123 import android.net.ipsec.test.ike.ChildSessionCallback; 124 import android.net.ipsec.test.ike.ChildSessionParams; 125 import android.net.ipsec.test.ike.IkeFqdnIdentification; 126 import android.net.ipsec.test.ike.IkeIdentification; 127 import android.net.ipsec.test.ike.IkeIpv4AddrIdentification; 128 import android.net.ipsec.test.ike.IkeManager; 129 import android.net.ipsec.test.ike.IkeSaProposal; 130 import android.net.ipsec.test.ike.IkeSessionCallback; 131 import android.net.ipsec.test.ike.IkeSessionConfiguration; 132 import android.net.ipsec.test.ike.IkeSessionConnectionInfo; 133 import android.net.ipsec.test.ike.IkeSessionParams; 134 import android.net.ipsec.test.ike.SaProposal; 135 import android.net.ipsec.test.ike.TransportModeChildSessionParams; 136 import android.net.ipsec.test.ike.TunnelModeChildSessionParams; 137 import android.net.ipsec.test.ike.exceptions.AuthenticationFailedException; 138 import android.net.ipsec.test.ike.exceptions.IkeException; 139 import android.net.ipsec.test.ike.exceptions.IkeIOException; 140 import android.net.ipsec.test.ike.exceptions.IkeInternalException; 141 import android.net.ipsec.test.ike.exceptions.IkeNetworkLostException; 142 import android.net.ipsec.test.ike.exceptions.IkeProtocolException; 143 import android.net.ipsec.test.ike.exceptions.IkeTimeoutException; 144 import android.net.ipsec.test.ike.exceptions.InvalidSyntaxException; 145 import android.net.ipsec.test.ike.exceptions.NoValidProposalChosenException; 146 import android.net.ipsec.test.ike.exceptions.UnrecognizedIkeProtocolException; 147 import android.net.ipsec.test.ike.exceptions.UnsupportedCriticalPayloadException; 148 import android.net.ipsec.test.ike.ike3gpp.Ike3gppBackoffTimer; 149 import android.net.ipsec.test.ike.ike3gpp.Ike3gppData; 150 import android.net.ipsec.test.ike.ike3gpp.Ike3gppExtension; 151 import android.net.ipsec.test.ike.ike3gpp.Ike3gppExtension.Ike3gppDataListener; 152 import android.net.ipsec.test.ike.ike3gpp.Ike3gppN1ModeInformation; 153 import android.net.ipsec.test.ike.ike3gpp.Ike3gppParams; 154 import android.os.test.TestLooper; 155 import android.telephony.TelephonyManager; 156 157 import androidx.test.filters.SdkSuppress; 158 159 import com.android.internal.net.TestUtils; 160 import com.android.internal.net.eap.test.EapAuthenticator; 161 import com.android.internal.net.eap.test.IEapCallback; 162 import com.android.internal.net.ipsec.test.ike.ChildSessionStateMachine.IChildSessionSmCallback; 163 import com.android.internal.net.ipsec.test.ike.IkeLocalRequestScheduler.ChildLocalRequest; 164 import com.android.internal.net.ipsec.test.ike.IkeLocalRequestScheduler.IkeLocalRequest; 165 import com.android.internal.net.ipsec.test.ike.IkeLocalRequestScheduler.LocalRequestFactory; 166 import com.android.internal.net.ipsec.test.ike.IkeSessionStateMachine.CreateIkeLocalIkeAuth; 167 import com.android.internal.net.ipsec.test.ike.IkeSessionStateMachine.CreateIkeLocalIkeAuthInEap; 168 import com.android.internal.net.ipsec.test.ike.IkeSessionStateMachine.ReceivedIkePacket; 169 import com.android.internal.net.ipsec.test.ike.SaRecord.ISaRecordHelper; 170 import com.android.internal.net.ipsec.test.ike.SaRecord.IkeSaRecord; 171 import com.android.internal.net.ipsec.test.ike.SaRecord.IkeSaRecordConfig; 172 import com.android.internal.net.ipsec.test.ike.SaRecord.SaLifetimeAlarmScheduler; 173 import com.android.internal.net.ipsec.test.ike.SaRecord.SaRecordHelper; 174 import com.android.internal.net.ipsec.test.ike.crypto.IkeCipher; 175 import com.android.internal.net.ipsec.test.ike.crypto.IkeMacIntegrity; 176 import com.android.internal.net.ipsec.test.ike.crypto.IkeMacPrf; 177 import com.android.internal.net.ipsec.test.ike.keepalive.IkeNattKeepalive; 178 import com.android.internal.net.ipsec.test.ike.message.IkeAuthDigitalSignPayload; 179 import com.android.internal.net.ipsec.test.ike.message.IkeAuthPayload; 180 import com.android.internal.net.ipsec.test.ike.message.IkeAuthPskPayload; 181 import com.android.internal.net.ipsec.test.ike.message.IkeCertX509CertPayload; 182 import com.android.internal.net.ipsec.test.ike.message.IkeConfigPayload; 183 import com.android.internal.net.ipsec.test.ike.message.IkeDeletePayload; 184 import com.android.internal.net.ipsec.test.ike.message.IkeEapPayload; 185 import com.android.internal.net.ipsec.test.ike.message.IkeHeader; 186 import com.android.internal.net.ipsec.test.ike.message.IkeIdPayload; 187 import com.android.internal.net.ipsec.test.ike.message.IkeInformationalPayload; 188 import com.android.internal.net.ipsec.test.ike.message.IkeKePayload; 189 import com.android.internal.net.ipsec.test.ike.message.IkeMessage; 190 import com.android.internal.net.ipsec.test.ike.message.IkeMessage.DecodeResult; 191 import com.android.internal.net.ipsec.test.ike.message.IkeMessage.DecodeResultOk; 192 import com.android.internal.net.ipsec.test.ike.message.IkeMessage.DecodeResultPartial; 193 import com.android.internal.net.ipsec.test.ike.message.IkeMessage.DecodeResultProtectedError; 194 import com.android.internal.net.ipsec.test.ike.message.IkeMessage.DecodeResultUnprotectedError; 195 import com.android.internal.net.ipsec.test.ike.message.IkeMessage.IIkeMessageHelper; 196 import com.android.internal.net.ipsec.test.ike.message.IkeMessage.IkeMessageHelper; 197 import com.android.internal.net.ipsec.test.ike.message.IkeNoncePayload; 198 import com.android.internal.net.ipsec.test.ike.message.IkeNotifyPayload; 199 import com.android.internal.net.ipsec.test.ike.message.IkePayload; 200 import com.android.internal.net.ipsec.test.ike.message.IkeSaPayload; 201 import com.android.internal.net.ipsec.test.ike.message.IkeSaPayload.DhGroupTransform; 202 import com.android.internal.net.ipsec.test.ike.message.IkeSaPayload.EncryptionTransform; 203 import com.android.internal.net.ipsec.test.ike.message.IkeSaPayload.IntegrityTransform; 204 import com.android.internal.net.ipsec.test.ike.message.IkeSaPayload.PrfTransform; 205 import com.android.internal.net.ipsec.test.ike.message.IkeSkfPayload; 206 import com.android.internal.net.ipsec.test.ike.message.IkeTestUtils; 207 import com.android.internal.net.ipsec.test.ike.message.IkeTsPayload; 208 import com.android.internal.net.ipsec.test.ike.net.IkeConnectionController; 209 import com.android.internal.net.ipsec.test.ike.net.IkeDefaultNetworkCallback; 210 import com.android.internal.net.ipsec.test.ike.net.IkeNetworkCallbackBase; 211 import com.android.internal.net.ipsec.test.ike.net.IkeSpecificNetworkCallback; 212 import com.android.internal.net.ipsec.test.ike.testmode.DeterministicSecureRandom; 213 import com.android.internal.net.ipsec.test.ike.testutils.CertUtils; 214 import com.android.internal.net.ipsec.test.ike.utils.IkeAlarm.IkeAlarmConfig; 215 import com.android.internal.net.ipsec.test.ike.utils.IkeSecurityParameterIndex; 216 import com.android.internal.net.ipsec.test.ike.utils.IkeSpiGenerator; 217 import com.android.internal.net.ipsec.test.ike.utils.RandomnessFactory; 218 import com.android.internal.net.ipsec.test.ike.utils.State; 219 import com.android.internal.net.utils.test.Log; 220 import com.android.internal.util.HexDump; 221 import com.android.modules.utils.build.SdkLevel; 222 223 import org.junit.After; 224 import org.junit.Before; 225 import org.junit.Ignore; 226 import org.junit.Test; 227 import org.mockito.ArgumentCaptor; 228 import org.mockito.invocation.InvocationOnMock; 229 import org.mockito.stubbing.Answer; 230 231 import java.io.IOException; 232 import java.net.Inet4Address; 233 import java.net.InetAddress; 234 import java.net.UnknownHostException; 235 import java.nio.ByteBuffer; 236 import java.nio.charset.StandardCharsets; 237 import java.security.GeneralSecurityException; 238 import java.security.PrivateKey; 239 import java.security.SecureRandom; 240 import java.security.cert.X509Certificate; 241 import java.util.ArrayList; 242 import java.util.Arrays; 243 import java.util.Collections; 244 import java.util.HashMap; 245 import java.util.HashSet; 246 import java.util.List; 247 import java.util.Map; 248 import java.util.Random; 249 import java.util.Set; 250 import java.util.concurrent.Executor; 251 import java.util.concurrent.TimeUnit; 252 253 public final class IkeSessionStateMachineTest extends IkeSessionTestBase { 254 private static final String TAG = "IkeSessionStateMachineTest"; 255 256 private static final String IKE_INIT_RESP_HEX_STRING = 257 "5f54bf6d8b48e6e1909232b3d1edcb5c21202220000000000000014c220000300000" 258 + "002c010100040300000c0100000c800e008003000008030000020300000802000002" 259 + "00000008040000022800008800020000fe014fefed55a4229928bfa3dad1ea6ffaca" 260 + "abfb5f5bdd71790e99a192530e3f849d3a3d96dc6e0a7a10ff6f72a6162103ac573c" 261 + "acd41d08b7a034cad8f5eab09c14ced5a9e4af5692dff028f21c1119dd75226b6af6" 262 + "b2f009245369c9892cc5742e5c94a254ebff052470771fb2cb4f29a35d8953e18a1a" 263 + "6c6fbc56acc188a5290000249756112ca539f5c25abacc7ee92b73091942a9c06950" 264 + "f98848f1af1694c4ddff2900001c00004004c53f054b976a25d75fde72dbf1c7b6c8" 265 + "c9aa9ca12900001c00004005b16d79b21c1bc89ca7350f42de805be0227e2ed62b00" 266 + "00080000401400000014882fe56d6fd20dbc2251613b2ebe5beb"; 267 private static final String IKE_SA_PAYLOAD_HEX_STRING = 268 "220000300000002c010100040300000c0100000c800e00800300000803000002030" 269 + "00008020000020000000804000002"; 270 private static final String IKE_REKEY_SA_PAYLOAD_HEX_STRING = 271 "22000038000000340101080400000000000000FF0300000c0100000c800e0080030" 272 + "000080300000203000008020000020000000804000002"; 273 private static final String IKE_REKEY_UNACCEPTABLE_SA_PAYLOAD_HEX_STRING = 274 "22000038000000340101080400000000000000FF0300000c0100000c800e0080030" 275 + "00008030000020300000802000002000000080400000e"; 276 private static final int IKE_REKEY_SA_INITIATOR_SPI = 0xff; 277 private static final String KE_PAYLOAD_HEX_STRING = 278 "2800008800020000b4a2faf4bb54878ae21d638512ece55d9236fc50" 279 + "46ab6cef82220f421f3ce6361faf36564ecb6d28798a94aa" 280 + "d7b2b4b603ddeaaa5630adb9ece8ac37534036040610ebdd" 281 + "92f46bef84f0be7db860351843858f8acf87056e272377f7" 282 + "0c9f2d81e29c7b0ce4f291a3a72476bb0b278fd4b7b0a4c2" 283 + "6bbeb08214c7071376079587"; 284 private static final String INVALID_KE_PAYLOAD_HEX_STRING = "0000000a00000011000e"; 285 private static final String NONCE_INIT_PAYLOAD_HEX_STRING = 286 "29000024c39b7f368f4681b89fa9b7be6465abd7c5f68b6ed5d3b4c72cb4240eb5c46412"; 287 private static final String NONCE_RESP_PAYLOAD_HEX_STRING = 288 "290000249756112ca539f5c25abacc7ee92b73091942a9c06950f98848f1af1694c4ddff"; 289 private static final String NONCE_INIT_HEX_STRING = 290 "c39b7f368f4681b89fa9b7be6465abd7c5f68b6ed5d3b4c72cb4240eb5c46412"; 291 private static final String NONCE_RESP_HEX_STRING = 292 "9756112ca539f5c25abacc7ee92b73091942a9c06950f98848f1af1694c4ddff"; 293 private static final String NAT_DETECTION_SOURCE_PAYLOAD_HEX_STRING = 294 "2900001c00004004e54f73b7d83f6beb881eab2051d8663f421d10b0"; 295 private static final String NAT_DETECTION_DESTINATION_PAYLOAD_HEX_STRING = 296 "2900001c00004005d915368ca036004cb578ae3e3fb268509aeab190"; 297 private static final String FRAGMENTATION_SUPPORTED_PAYLOAD_HEX_STRING = "290000080000402e"; 298 private static final String SIGNATURE_HASH_SUPPORTED_PAYLOAD_HEX_STRING = 299 "2b0000100000402f0001000200030004"; 300 private static final String DELETE_IKE_PAYLOAD_HEX_STRING = "0000000801000000"; 301 private static final String NOTIFY_REKEY_IKE_PAYLOAD_HEX_STRING = "2100000800004009"; 302 private static final String ID_PAYLOAD_INITIATOR_HEX_STRING = 303 "290000180200000031313233343536373839414243444546"; 304 private static final String ID_PAYLOAD_RESPONDER_HEX_STRING = "2700000c010000007f000001"; 305 private static final String ID_PAYLOAD_RESPONDER_FQDN_HEX_STRING = 306 "2700001702000000696B652E616E64726F69642E6E6574"; 307 private static final String PSK_AUTH_RESP_PAYLOAD_HEX_STRING = 308 "2100001c0200000058f36412e9b7b38df817a9f7779b7a008dacdd25"; 309 private static final String GENERIC_DIGITAL_SIGN_AUTH_RESP_HEX_STRING = 310 "300000580e0000000f300d06092a864886f70d01010b05006f76af4150d653c5d413" 311 + "6b9f69d905849bf075c563e6d14ccda42361ec3e7d12c72e2dece5711ea1d952f7b8e" 312 + "12c5d982aa4efdaeac36a02b222aa96242cc424"; 313 private static final String CHILD_SA_PAYLOAD_HEX_STRING = 314 "2c00002c0000002801030403cae7019f0300000c0100000c800e008003000008030" 315 + "000020000000805000000"; 316 private static final String TS_INIT_PAYLOAD_HEX_STRING = 317 "2d00001801000000070000100000ffff00000000ffffffff"; 318 private static final String TS_RESP_PAYLOAD_HEX_STRING = 319 "2900001801000000070000100000ffff000000000fffffff"; 320 private static final String VENDOR_ID_PAYLOAD_HEX_STRING = 321 "0000001852656d6f74652056656e646f72204944204f6e65"; 322 323 private static final String PSK_HEX_STRING = "6A756E69706572313233"; 324 325 private static final String PRF_KEY_INIT_HEX_STRING = 326 "094787780EE466E2CB049FA327B43908BC57E485"; 327 private static final String PRF_KEY_RESP_HEX_STRING = 328 "A30E6B08BE56C0E6BFF4744143C75219299E1BEB"; 329 330 private static final String CP_PAYLOAD_HEX_STRING = 331 "210000810200000000080011260010111067a17d000000000a" 332 + "f68e8640000a0010200148880067ff000643000d000000000" 333 + "00a0010200148880066ff000645000d0000000000150010200" 334 + "148880006713a00f10104000000050015001020014888000671" 335 + "3a00f101040000008900150010200148880005713a00e00104000000c9"; 336 private static final String PCSCF_IPV6_ADDRESS1 = "2001:4888:6:713a:f1:104:0:5"; 337 private static final String PCSCF_IPV6_ADDRESS2 = "2001:4888:6:713a:f1:104:0:89"; 338 private static final String PCSCF_IPV6_ADDRESS3 = "2001:4888:5:713a:e0:104:0:c9"; 339 340 private static final byte[] EAP_DUMMY_MSG = "EAP Message".getBytes(); 341 private static final int EAP_RESPONSE_FLAG_MASK_WITH_EAP_AKA_SERVER_AUTHENTICATED = 342 (1 << RESPONSE_FLAG_EAP_AKA_SERVER_AUTHENTICATED); 343 private static final int EAP_RESPONSE_FLAGS_NOT_SET = 0; 344 private static final byte[] REMOTE_VENDOR_ID_ONE = "Remote Vendor ID One".getBytes(); 345 private static final byte[] REMOTE_VENDOR_ID_TWO = "Remote Vendor ID Two".getBytes(); 346 347 private static final IkeIdentification LOCAL_ID_IPV4 = 348 new IkeIpv4AddrIdentification((Inet4Address) LOCAL_ADDRESS); 349 private static final IkeIdentification REMOTE_ID_FQDN = 350 new IkeFqdnIdentification("server.test.android.net"); 351 private static final IkeIdentification REMOTE_ID_IPV4 = 352 new IkeIpv4AddrIdentification((Inet4Address) REMOTE_ADDRESS); 353 354 private static final byte PDU_SESSION_ID = (byte) 0x7B; 355 private static final String N1_MODE_CAPABILITY_PAYLOAD_DATA = "017B"; 356 private static final byte[] SNSSAI = {(byte) 456}; 357 358 private static final byte BACKOFF_TIMER = (byte) 0xAF; 359 private static final byte[] BACKOFF_TIMER_DATA = {0x01, BACKOFF_TIMER}; 360 361 private static final int KEY_LEN_IKE_INTE = 20; 362 private static final int KEY_LEN_IKE_ENCR = 16; 363 private static final int KEY_LEN_IKE_PRF = 20; 364 private static final int KEY_LEN_IKE_SKD = KEY_LEN_IKE_PRF; 365 366 private static final int CHILD_SPI_LOCAL = 0x2ad4c0a2; 367 private static final int CHILD_SPI_REMOTE = 0xcae7019f; 368 369 private static final int EAP_SIM_SUB_ID = 1; 370 371 private static final int PAYLOAD_TYPE_UNSUPPORTED = 127; 372 373 private static final int COOKIE_DATA_LEN = 64; 374 private static final int COOKIE2_DATA_LEN = 64; 375 376 private static final byte[] COOKIE_DATA = new byte[COOKIE_DATA_LEN]; 377 private static final byte[] COOKIE2_DATA = new byte[COOKIE2_DATA_LEN]; 378 379 private static final int FAKE_SESSION_ID = 0; 380 381 private static final int NATT_KEEPALIVE_DELAY = 20; 382 383 private static final String DEVICE_IDENTITY_IMEI = "123456789123456"; 384 private static final byte[] DEVICE_IDENTITY_PAYLOAD_IMEI = 385 HexDump.hexStringToByteArray("00090121436587193254F6"); 386 387 static { 388 new Random().nextBytes(COOKIE_DATA); 389 new Random().nextBytes(COOKIE2_DATA); 390 } 391 392 private static final long RETRANSMIT_BACKOFF_TIMEOUT_MS = 5000L; 393 394 private static final IkeSpiGenerator IKE_SPI_GENERATOR = 395 new IkeSpiGenerator(createMockRandomFactory()); 396 397 private static final Ike3gppParams IKE_3GPP_PARAMS = 398 new Ike3gppParams.Builder().setPduSessionId(PDU_SESSION_ID).build(); 399 400 private static final byte[] REAUTH_ID_BYTES = 401 "4OLUpQCqFyhm1/UgD56anTzYTqJDckibqjU6PlS4sZaiuLc=".getBytes(StandardCharsets.UTF_8); 402 403 private IkeUdpEncapSocket mMockIkeUdpEncapSocket; 404 private IkeUdp6WithEncapPortSocket mMockIkeUdp6WithEncapPortSocket; 405 private IkeUdp4Socket mMockIkeUdp4Socket; 406 private IkeUdp6Socket mMockIkeUdp6Socket; 407 private IkeSocket mMockCurrentIkeSocket; 408 409 private IkeNattKeepalive mMockIkeNattKeepalive; 410 411 private TestLooper mLooper; 412 private IkeSessionStateMachine mIkeSessionStateMachine; 413 414 private byte[] mPsk; 415 416 private ChildSessionParams mChildSessionParams; 417 418 private Executor mSpyUserCbExecutor; 419 private IkeSessionCallback mMockIkeSessionCallback; 420 private ChildSessionCallback mMockChildSessionCallback; 421 422 private EncryptionTransform mIkeEncryptionTransform; 423 private IntegrityTransform mIkeIntegrityTransform; 424 private PrfTransform mIkePrfTransform; 425 private DhGroupTransform mIkeDhGroupTransform; 426 427 private IIkeMessageHelper mMockIkeMessageHelper; 428 private ISaRecordHelper mMockSaRecordHelper; 429 430 private ChildSessionStateMachine mMockChildSessionStateMachine; 431 private IChildSessionSmCallback mDummyChildSmCallback; 432 433 private IkeSaRecord mSpyCurrentIkeSaRecord; 434 private IkeSaRecord mSpyLocalInitIkeSaRecord; 435 private IkeSaRecord mSpyRemoteInitIkeSaRecord; 436 437 private Log mSpyIkeLog; 438 439 private int mExpectedCurrentSaLocalReqMsgId; 440 private int mExpectedCurrentSaRemoteReqMsgId; 441 442 private IkeSessionStateMachine.Dependencies mSpyDeps; 443 444 private EapSessionConfig mEapSessionConfig; 445 private EapSessionConfig mEapSessionConfigEapAka; 446 private EapAuthenticator mMockEapAuthenticator; 447 448 private IkeConnectionController mSpyIkeConnectionCtrl; 449 450 private Ike3gppDataListener mMockIke3gppDataListener; 451 private Ike3gppExtension mIke3gppExtension; 452 453 private X509Certificate mRootCertificate; 454 private X509Certificate mServerEndCertificate; 455 private PrivateKey mUserPrivateKey; 456 private X509Certificate mUserEndCert; 457 458 private LocalRequestFactory mLocalRequestFactory; 459 460 private ArgumentCaptor<IkeMessage> mIkeMessageCaptor = 461 ArgumentCaptor.forClass(IkeMessage.class); 462 private ArgumentCaptor<IkeSaRecordConfig> mIkeSaRecordConfigCaptor = 463 ArgumentCaptor.forClass(IkeSaRecordConfig.class); 464 private ArgumentCaptor<IChildSessionSmCallback> mChildSessionSmCbCaptor = 465 ArgumentCaptor.forClass(IChildSessionSmCallback.class); 466 private ArgumentCaptor<List<IkePayload>> mPayloadListCaptor = 467 ArgumentCaptor.forClass(List.class); 468 makeDummyReceivedIkeInitRespPacket(List<IkePayload> payloadList)469 private ReceivedIkePacket makeDummyReceivedIkeInitRespPacket(List<IkePayload> payloadList) 470 throws Exception { 471 long dummyInitSpi = 1L; 472 long dummyRespSpi = 2L; 473 474 return makeDummyUnencryptedReceivedIkePacket( 475 dummyInitSpi, 476 dummyRespSpi, 477 IkeHeader.EXCHANGE_TYPE_IKE_SA_INIT, 478 true /*isResp*/, 479 false /*fromIkeInit*/, 480 payloadList); 481 } 482 makeDummyReceivedIkeInitRespPacket( List<Integer> payloadTypeList, List<String> payloadHexStringList)483 private ReceivedIkePacket makeDummyReceivedIkeInitRespPacket( 484 List<Integer> payloadTypeList, List<String> payloadHexStringList) throws Exception { 485 486 List<IkePayload> payloadList = 487 hexStrListToIkePayloadList( 488 payloadTypeList, payloadHexStringList, true /* isResp */); 489 return makeDummyReceivedIkeInitRespPacket(payloadList); 490 } 491 makeDummyUnencryptedReceivedIkePacket( long initiatorSpi, long responderSpi, @IkeHeader.ExchangeType int eType, boolean isResp, boolean fromIkeInit, List<IkePayload> payloadList)492 private ReceivedIkePacket makeDummyUnencryptedReceivedIkePacket( 493 long initiatorSpi, 494 long responderSpi, 495 @IkeHeader.ExchangeType int eType, 496 boolean isResp, 497 boolean fromIkeInit, 498 List<IkePayload> payloadList) 499 throws Exception { 500 IkeMessage dummyIkeMessage = 501 makeDummyIkeMessageForTest( 502 initiatorSpi, 503 responderSpi, 504 eType, 505 isResp, 506 fromIkeInit, 507 0, 508 false /*isEncrypted*/, 509 payloadList); 510 511 byte[] dummyIkePacketBytes = new byte[0]; 512 doReturn(new DecodeResultOk(dummyIkeMessage, dummyIkePacketBytes)) 513 .when(mMockIkeMessageHelper) 514 .decode(0, dummyIkeMessage.ikeHeader, dummyIkePacketBytes); 515 516 return new ReceivedIkePacket(dummyIkeMessage.ikeHeader, dummyIkePacketBytes); 517 } 518 makeDummyEncryptedReceivedIkePacket( IkeSaRecord ikeSaRecord, @IkeHeader.ExchangeType int eType, boolean isResp, List<Integer> payloadTypeList, List<String> payloadHexStringList)519 private ReceivedIkePacket makeDummyEncryptedReceivedIkePacket( 520 IkeSaRecord ikeSaRecord, 521 @IkeHeader.ExchangeType int eType, 522 boolean isResp, 523 List<Integer> payloadTypeList, 524 List<String> payloadHexStringList) 525 throws Exception { 526 List<IkePayload> payloadList = 527 hexStrListToIkePayloadList(payloadTypeList, payloadHexStringList, isResp); 528 return makeDummyEncryptedReceivedIkePacketWithPayloadList( 529 ikeSaRecord, eType, isResp, payloadList); 530 } 531 makeDummyEncryptedReceivedIkePacketWithPayloadList( IkeSaRecord ikeSaRecord, @IkeHeader.ExchangeType int eType, boolean isResp, List<IkePayload> payloadList)532 private ReceivedIkePacket makeDummyEncryptedReceivedIkePacketWithPayloadList( 533 IkeSaRecord ikeSaRecord, 534 @IkeHeader.ExchangeType int eType, 535 boolean isResp, 536 List<IkePayload> payloadList) 537 throws Exception { 538 return makeDummyEncryptedReceivedIkePacketWithPayloadList( 539 ikeSaRecord, 540 eType, 541 isResp, 542 isResp 543 ? ikeSaRecord.getLocalRequestMessageId() 544 : ikeSaRecord.getRemoteRequestMessageId(), 545 payloadList, 546 new byte[0] /*dummyIkePacketBytes*/); 547 } 548 makeDummyEncryptedReceivedIkePacketWithPayloadList( IkeSaRecord ikeSaRecord, @IkeHeader.ExchangeType int eType, boolean isResp, int msgId, List<IkePayload> payloadList, byte[] dummyIkePacketBytes)549 private ReceivedIkePacket makeDummyEncryptedReceivedIkePacketWithPayloadList( 550 IkeSaRecord ikeSaRecord, 551 @IkeHeader.ExchangeType int eType, 552 boolean isResp, 553 int msgId, 554 List<IkePayload> payloadList, 555 byte[] dummyIkePacketBytes) 556 throws Exception { 557 boolean fromIkeInit = !ikeSaRecord.isLocalInit; 558 IkeMessage dummyIkeMessage = 559 makeDummyIkeMessageForTest( 560 ikeSaRecord.getInitiatorSpi(), 561 ikeSaRecord.getResponderSpi(), 562 eType, 563 isResp, 564 fromIkeInit, 565 msgId, 566 true /*isEncyprted*/, 567 payloadList); 568 569 setDecodeEncryptedPacketResult( 570 ikeSaRecord, 571 dummyIkeMessage.ikeHeader, 572 null /*collectedFrags*/, 573 new DecodeResultOk(dummyIkeMessage, dummyIkePacketBytes)); 574 575 return new ReceivedIkePacket(dummyIkeMessage.ikeHeader, dummyIkePacketBytes); 576 } 577 makeDummyReceivedIkePacketWithInvalidSyntax( IkeSaRecord ikeSaRecord, boolean isResp, int eType)578 private ReceivedIkePacket makeDummyReceivedIkePacketWithInvalidSyntax( 579 IkeSaRecord ikeSaRecord, boolean isResp, int eType) { 580 return makeDummyReceivedIkePacketWithDecodingError( 581 ikeSaRecord, isResp, eType, new InvalidSyntaxException("IkeStateMachineTest")); 582 } 583 makeDummyReceivedIkePacketWithDecodingError( IkeSaRecord ikeSaRecord, boolean isResp, int eType, IkeProtocolException exception)584 private ReceivedIkePacket makeDummyReceivedIkePacketWithDecodingError( 585 IkeSaRecord ikeSaRecord, boolean isResp, int eType, IkeProtocolException exception) { 586 IkeHeader header = 587 makeDummyIkeHeader(ikeSaRecord, isResp, eType, IkePayload.PAYLOAD_TYPE_SK); 588 byte[] dummyPacket = new byte[0]; 589 doReturn(new DecodeResultProtectedError(exception, dummyPacket)) 590 .when(mMockIkeMessageHelper) 591 .decode(anyInt(), any(), any(), eq(ikeSaRecord), eq(header), any(), any()); 592 593 return new ReceivedIkePacket(header, dummyPacket); 594 } 595 makeDummyReceivedIkePacketWithUnprotectedError( IkeSaRecord ikeSaRecord, boolean isResp, int eType, IkeException exception)596 private ReceivedIkePacket makeDummyReceivedIkePacketWithUnprotectedError( 597 IkeSaRecord ikeSaRecord, boolean isResp, int eType, IkeException exception) { 598 IkeHeader header = 599 makeDummyIkeHeader(ikeSaRecord, isResp, eType, IkePayload.PAYLOAD_TYPE_SK); 600 byte[] dummyPacket = new byte[0]; 601 doReturn(new DecodeResultUnprotectedError(exception)) 602 .when(mMockIkeMessageHelper) 603 .decode(anyInt(), any(), any(), eq(ikeSaRecord), eq(header), any(), any()); 604 605 return new ReceivedIkePacket(header, dummyPacket); 606 } 607 makeDummyReceivedIkeFragmentPacket( IkeSaRecord ikeSaRecord, boolean isResp, int eType, IkeSkfPayload skfPayload, int nextPayloadType, DecodeResultPartial collectedFrags)608 private ReceivedIkePacket makeDummyReceivedIkeFragmentPacket( 609 IkeSaRecord ikeSaRecord, 610 boolean isResp, 611 int eType, 612 IkeSkfPayload skfPayload, 613 int nextPayloadType, 614 DecodeResultPartial collectedFrags) { 615 IkeHeader header = 616 makeDummyIkeHeader(ikeSaRecord, isResp, eType, IkePayload.PAYLOAD_TYPE_SKF); 617 618 byte[] dummyPacket = new byte[0]; 619 DecodeResultPartial resultFrags = 620 new DecodeResultPartial( 621 header, dummyPacket, skfPayload, nextPayloadType, collectedFrags); 622 setDecodeEncryptedPacketResult(ikeSaRecord, header, collectedFrags, resultFrags); 623 624 return new ReceivedIkePacket(header, dummyPacket); 625 } 626 makeDummyReceivedLastIkeFragmentPacketOk( IkeSaRecord ikeSaRecord, boolean isResp, int eType, DecodeResultPartial collectedFrags, List<IkePayload> payloadList, byte[] firstFragBytes)627 private ReceivedIkePacket makeDummyReceivedLastIkeFragmentPacketOk( 628 IkeSaRecord ikeSaRecord, 629 boolean isResp, 630 int eType, 631 DecodeResultPartial collectedFrags, 632 List<IkePayload> payloadList, 633 byte[] firstFragBytes) { 634 IkeHeader header = 635 makeDummyIkeHeader(ikeSaRecord, isResp, eType, IkePayload.PAYLOAD_TYPE_SKF); 636 637 IkeMessage completeMessage = new IkeMessage(header, payloadList); 638 639 setDecodeEncryptedPacketResult( 640 ikeSaRecord, 641 header, 642 collectedFrags, 643 new DecodeResultOk(completeMessage, firstFragBytes)); 644 645 return new ReceivedIkePacket(header, new byte[0] /*dummyIkePacketBytes*/); 646 } 647 makeDummyReceivedLastIkeFragmentPacketError( IkeSaRecord ikeSaRecord, boolean isResp, int eType, DecodeResultPartial collectedFrags, IkeException exception)648 private ReceivedIkePacket makeDummyReceivedLastIkeFragmentPacketError( 649 IkeSaRecord ikeSaRecord, 650 boolean isResp, 651 int eType, 652 DecodeResultPartial collectedFrags, 653 IkeException exception) { 654 IkeHeader header = 655 makeDummyIkeHeader(ikeSaRecord, isResp, eType, IkePayload.PAYLOAD_TYPE_SKF); 656 657 byte[] dummyIkePacketBytes = new byte[0]; 658 setDecodeEncryptedPacketResult( 659 ikeSaRecord, 660 header, 661 collectedFrags, 662 new DecodeResultProtectedError(exception, dummyIkePacketBytes)); 663 664 return new ReceivedIkePacket(header, dummyIkePacketBytes); 665 } 666 makeDummyIkeHeader( IkeSaRecord ikeSaRecord, boolean isResp, int eType, int firstPayloadType)667 private IkeHeader makeDummyIkeHeader( 668 IkeSaRecord ikeSaRecord, boolean isResp, int eType, int firstPayloadType) { 669 return new IkeHeader( 670 ikeSaRecord.getInitiatorSpi(), 671 ikeSaRecord.getResponderSpi(), 672 firstPayloadType, 673 eType, 674 isResp, 675 !ikeSaRecord.isLocalInit, 676 isResp 677 ? ikeSaRecord.getLocalRequestMessageId() 678 : ikeSaRecord.getRemoteRequestMessageId()); 679 } 680 setDecodeEncryptedPacketResult( IkeSaRecord ikeSaRecord, IkeHeader header, DecodeResultPartial collectedFrags, DecodeResult result)681 private void setDecodeEncryptedPacketResult( 682 IkeSaRecord ikeSaRecord, 683 IkeHeader header, 684 DecodeResultPartial collectedFrags, 685 DecodeResult result) { 686 doReturn(result) 687 .when(mMockIkeMessageHelper) 688 .decode( 689 anyInt(), 690 any(), 691 any(), 692 eq(ikeSaRecord), 693 eq(header), 694 any(), 695 eq(collectedFrags)); 696 } 697 makeDummyIkeMessageForTest( long initSpi, long respSpi, @IkeHeader.ExchangeType int eType, boolean isResp, boolean fromikeInit, int messageId, boolean isEncrypted, List<IkePayload> payloadList)698 private IkeMessage makeDummyIkeMessageForTest( 699 long initSpi, 700 long respSpi, 701 @IkeHeader.ExchangeType int eType, 702 boolean isResp, 703 boolean fromikeInit, 704 int messageId, 705 boolean isEncrypted, 706 List<IkePayload> payloadList) 707 throws Exception { 708 int firstPayloadType = 709 isEncrypted ? IkePayload.PAYLOAD_TYPE_SK : IkePayload.PAYLOAD_TYPE_NO_NEXT; 710 711 IkeHeader header = 712 new IkeHeader( 713 initSpi, respSpi, firstPayloadType, eType, isResp, fromikeInit, messageId); 714 715 return new IkeMessage(header, payloadList); 716 } 717 hexStrListToIkePayloadList( List<Integer> payloadTypeList, List<String> payloadHexStringList, boolean isResp)718 private static List<IkePayload> hexStrListToIkePayloadList( 719 List<Integer> payloadTypeList, List<String> payloadHexStringList, boolean isResp) 720 throws Exception { 721 List<IkePayload> payloadList = new ArrayList<>(); 722 for (int i = 0; i < payloadTypeList.size(); i++) { 723 payloadList.add( 724 IkeTestUtils.hexStringToIkePayload( 725 payloadTypeList.get(i), isResp, payloadHexStringList.get(i))); 726 } 727 return payloadList; 728 } 729 verifyDecodeEncryptedMessage(IkeSaRecord record, ReceivedIkePacket rcvPacket)730 private void verifyDecodeEncryptedMessage(IkeSaRecord record, ReceivedIkePacket rcvPacket) 731 throws Exception { 732 verify(mMockIkeMessageHelper) 733 .decode( 734 anyInt(), 735 any(), 736 any(), 737 eq(record), 738 eq(rcvPacket.ikeHeader), 739 eq(rcvPacket.ikePacketBytes), 740 eq(null)); 741 } 742 makeDummyIkeSaRecord(long initSpi, long respSpi, boolean isLocalInit)743 private static IkeSaRecord makeDummyIkeSaRecord(long initSpi, long respSpi, boolean isLocalInit) 744 throws IOException { 745 Inet4Address initAddress = isLocalInit ? LOCAL_ADDRESS : REMOTE_ADDRESS; 746 Inet4Address respAddress = isLocalInit ? REMOTE_ADDRESS : LOCAL_ADDRESS; 747 748 return new IkeSaRecord( 749 IKE_SPI_GENERATOR.allocateSpi(initAddress, initSpi), 750 IKE_SPI_GENERATOR.allocateSpi(respAddress, respSpi), 751 isLocalInit, 752 TestUtils.hexStringToByteArray(NONCE_INIT_HEX_STRING), 753 TestUtils.hexStringToByteArray(NONCE_RESP_HEX_STRING), 754 new byte[KEY_LEN_IKE_SKD], 755 new byte[KEY_LEN_IKE_INTE], 756 new byte[KEY_LEN_IKE_INTE], 757 new byte[KEY_LEN_IKE_ENCR], 758 new byte[KEY_LEN_IKE_ENCR], 759 TestUtils.hexStringToByteArray(PRF_KEY_INIT_HEX_STRING), 760 TestUtils.hexStringToByteArray(PRF_KEY_RESP_HEX_STRING), 761 mock(SaLifetimeAlarmScheduler.class)); 762 } 763 mockScheduleRekey(SaLifetimeAlarmScheduler mockSaLifetimeAlarmScheduler)764 private void mockScheduleRekey(SaLifetimeAlarmScheduler mockSaLifetimeAlarmScheduler) { 765 IkeLocalRequest rekeyReq = 766 mLocalRequestFactory.getIkeLocalRequest( 767 IkeSessionStateMachine.CMD_LOCAL_REQUEST_REKEY_IKE); 768 doAnswer( 769 (invocation) -> { 770 mIkeSessionStateMachine.sendMessageDelayed( 771 IkeSessionStateMachine.CMD_LOCAL_REQUEST_REKEY_IKE, 772 rekeyReq, 773 mIkeSessionStateMachine.mIkeSessionParams 774 .getSoftLifetimeMsInternal()); 775 return null; 776 }) 777 .when(mockSaLifetimeAlarmScheduler) 778 .scheduleLifetimeExpiryAlarm(anyString()); 779 } 780 781 @Override 782 @Before setUp()783 public void setUp() throws Exception { 784 super.setUp(); 785 786 mSpyIkeLog = TestUtils.makeSpyLogThrowExceptionForWtf(TAG); 787 IkeManager.setIkeLog(mSpyIkeLog); 788 789 mEapSessionConfig = 790 new EapSessionConfig.Builder() 791 .setEapSimConfig(EAP_SIM_SUB_ID, TelephonyManager.APPTYPE_USIM) 792 .build(); 793 setupLocalAddressForNetwork(mMockDefaultNetwork, LOCAL_ADDRESS, LOCAL_ADDRESS_V6); 794 795 mMockEapAuthenticator = mock(EapAuthenticator.class); 796 mMockChildSessionStateMachine = mock(ChildSessionStateMachine.class); 797 798 mRootCertificate = CertUtils.createCertFromPemFile("self-signed-ca-a.pem"); 799 mServerEndCertificate = CertUtils.createCertFromPemFile("end-cert-a.pem"); 800 mUserEndCert = CertUtils.createCertFromPemFile("end-cert-b.pem"); 801 mUserPrivateKey = CertUtils.createRsaPrivateKeyFromKeyFile("end-cert-key-b.key"); 802 803 mPsk = TestUtils.hexStringToByteArray(PSK_HEX_STRING); 804 805 mChildSessionParams = buildChildSessionParams(); 806 807 mIkeEncryptionTransform = 808 new EncryptionTransform( 809 SaProposal.ENCRYPTION_ALGORITHM_AES_CBC, SaProposal.KEY_LEN_AES_128); 810 mIkeIntegrityTransform = 811 new IntegrityTransform(SaProposal.INTEGRITY_ALGORITHM_HMAC_SHA1_96); 812 mIkePrfTransform = new PrfTransform(SaProposal.PSEUDORANDOM_FUNCTION_HMAC_SHA1); 813 mIkeDhGroupTransform = new DhGroupTransform(SaProposal.DH_GROUP_1024_BIT_MODP); 814 815 mSpyUserCbExecutor = 816 spy( 817 (command) -> { 818 command.run(); 819 }); 820 821 mMockIkeSessionCallback = mock(IkeSessionCallback.class); 822 mMockChildSessionCallback = mock(ChildSessionCallback.class); 823 mLocalRequestFactory = new LocalRequestFactory(); 824 825 mLooper = new TestLooper(); 826 827 // Setup state machine 828 mIkeSessionStateMachine = makeAndStartIkeSession(buildIkeSessionParamsPsk(mPsk)); 829 830 mMockIkeMessageHelper = mock(IkeMessage.IIkeMessageHelper.class); 831 IkeMessage.setIkeMessageHelper(mMockIkeMessageHelper); 832 resetMockIkeMessageHelper(); 833 834 mMockSaRecordHelper = mock(SaRecord.ISaRecordHelper.class); 835 SaRecord.setSaRecordHelper(mMockSaRecordHelper); 836 837 mSpyCurrentIkeSaRecord = spy(makeDummyIkeSaRecord(11, 12, true)); 838 mSpyLocalInitIkeSaRecord = spy(makeDummyIkeSaRecord(21, 22, true)); 839 mSpyRemoteInitIkeSaRecord = spy(makeDummyIkeSaRecord(31, 32, false)); 840 841 mExpectedCurrentSaLocalReqMsgId = 0; 842 mExpectedCurrentSaRemoteReqMsgId = 0; 843 844 mMockIke3gppDataListener = mock(Ike3gppDataListener.class); 845 } 846 847 @After tearDown()848 public void tearDown() throws Exception { 849 mIkeSessionStateMachine.killSession(); 850 mLooper.dispatchAll(); 851 mIkeSessionStateMachine.setDbg(false); 852 853 mSpyCurrentIkeSaRecord.close(); 854 mSpyLocalInitIkeSaRecord.close(); 855 mSpyRemoteInitIkeSaRecord.close(); 856 857 IkeManager.resetIkeLog(); 858 IkeMessage.setIkeMessageHelper(new IkeMessageHelper()); 859 SaRecord.setSaRecordHelper(new SaRecordHelper()); 860 } 861 injectChildSessionInSpyDeps( IkeSessionStateMachine.Dependencies spyDeps, ChildSessionStateMachine child, ChildSessionCallback childCb)862 private void injectChildSessionInSpyDeps( 863 IkeSessionStateMachine.Dependencies spyDeps, 864 ChildSessionStateMachine child, 865 ChildSessionCallback childCb) { 866 doReturn(child) 867 .when(spyDeps) 868 .newChildSessionStateMachine( 869 any(IkeContext.class), 870 any(ChildSessionStateMachine.Config.class), 871 eq(childCb), 872 any(IChildSessionSmCallback.class)); 873 } 874 buildSpyDepsWithChildSession( ChildSessionStateMachine child, ChildSessionCallback childCb)875 private IkeSessionStateMachine.Dependencies buildSpyDepsWithChildSession( 876 ChildSessionStateMachine child, ChildSessionCallback childCb) { 877 IkeSessionStateMachine.Dependencies spyDeps = 878 spy(new IkeSessionStateMachine.Dependencies()); 879 880 doReturn(mMockEapAuthenticator) 881 .when(spyDeps) 882 .newEapAuthenticator( 883 any(IkeContext.class), 884 any(IEapCallback.class), 885 any(EapSessionConfig.class)); 886 doReturn(mSpyIkeConnectionCtrl) 887 .when(spyDeps) 888 .newIkeConnectionController( 889 any(IkeContext.class), any(IkeConnectionController.Config.class)); 890 injectChildSessionInSpyDeps(spyDeps, child, childCb); 891 892 893 return spyDeps; 894 } 895 makeAndStartIkeSession(IkeSessionParams ikeParams)896 private IkeSessionStateMachine makeAndStartIkeSession(IkeSessionParams ikeParams) 897 throws Exception { 898 return makeAndStartIkeSession(ikeParams, LOCAL_ADDRESS, REMOTE_ADDRESS); 899 } 900 setupIkeConnectionCtrlCbWithIkeSession( IkeConnectionController.Callback mockCallback, IkeSessionStateMachine ikeSession)901 private void setupIkeConnectionCtrlCbWithIkeSession( 902 IkeConnectionController.Callback mockCallback, IkeSessionStateMachine ikeSession) { 903 doAnswer( 904 (invocation) -> { 905 ikeSession.onUnderlyingNetworkUpdated(); 906 return null; 907 }) 908 .when(mockCallback) 909 .onUnderlyingNetworkUpdated(); 910 911 doAnswer( 912 (invocation) -> { 913 ikeSession.onUnderlyingNetworkDied(invocation.getArgument(0)); 914 return null; 915 }) 916 .when(mockCallback) 917 .onUnderlyingNetworkDied(any()); 918 919 doAnswer( 920 (invocation) -> { 921 ikeSession.onError(invocation.getArgument(0)); 922 return null; 923 }) 924 .when(mockCallback) 925 .onError(any()); 926 } 927 makeAndStartIkeSession( IkeSessionParams ikeParams, InetAddress localAddress, InetAddress expectedRemoteAddress)928 private IkeSessionStateMachine makeAndStartIkeSession( 929 IkeSessionParams ikeParams, 930 InetAddress localAddress, 931 InetAddress expectedRemoteAddress) 932 throws Exception { 933 IkeContext ikeContext = 934 new IkeSessionStateMachine.Dependencies() 935 .newIkeContext( 936 mLooper.getLooper(), mSpyContext, ikeParams.getConfiguredNetwork()); 937 IkeConnectionController.Callback mockIkeConnectionCtrlCb = 938 mock(IkeConnectionController.Callback.class); 939 IkeConnectionController.Dependencies spyIkeConnectionCtrlDeps = 940 spy(new IkeConnectionController.Dependencies()); 941 doReturn(mMockIkeLocalAddressGenerator) 942 .when(spyIkeConnectionCtrlDeps) 943 .newIkeLocalAddressGenerator(); 944 mMockIkeNattKeepalive = mock(IkeNattKeepalive.class); 945 doAnswer( 946 (invocation) -> { 947 mMockIkeNattKeepalive.start(); 948 return mMockIkeNattKeepalive; 949 }) 950 .when(spyIkeConnectionCtrlDeps) 951 .newIkeNattKeepalive(any(), any()); 952 953 // Setup socket instances used by the IkeSessionStateMachine 954 mMockIkeUdp4Socket = newMockIkeSocket(IkeUdp4Socket.class); 955 mMockIkeUdp6Socket = newMockIkeSocket(IkeUdp6Socket.class); 956 mMockIkeUdpEncapSocket = newMockIkeSocket(IkeUdpEncapSocket.class); 957 mMockIkeUdp6WithEncapPortSocket = newMockIkeSocket(IkeUdp6WithEncapPortSocket.class); 958 959 doReturn(mMockIkeUdp4Socket) 960 .when(spyIkeConnectionCtrlDeps) 961 .newIkeUdp4Socket(any(), any(), any()); 962 doReturn(mMockIkeUdp6Socket) 963 .when(spyIkeConnectionCtrlDeps) 964 .newIkeUdp6Socket(any(), any(), any()); 965 doReturn(mMockIkeUdpEncapSocket) 966 .when(spyIkeConnectionCtrlDeps) 967 .newIkeUdpEncapSocket(any(), any(), any(), any()); 968 doReturn(mMockIkeUdp6WithEncapPortSocket) 969 .when(spyIkeConnectionCtrlDeps) 970 .newIkeUdp6WithEncapPortSocket(any(), any(), any()); 971 972 // Can't use a mock object because delayMs must be nonzero. Otherwise, setNetwork will 973 // spuriously restart keepalives, thinking that the current delay is zero. 974 final IkeAlarmConfig alarmConfig = spy(new IkeAlarmConfig(mSpyContext, 975 "mock", NATT_KEEPALIVE_DELAY * 1_000, null, null)); 976 mSpyIkeConnectionCtrl = 977 spy( 978 new IkeConnectionController( 979 ikeContext, 980 new IkeConnectionController.Config( 981 ikeParams, 982 FAKE_SESSION_ID, 983 CMD_ALARM_FIRED, 984 CMD_SEND_KEEPALIVE, 985 mockIkeConnectionCtrlCb), 986 spyIkeConnectionCtrlDeps)); 987 mSpyDeps = 988 buildSpyDepsWithChildSession( 989 mMockChildSessionStateMachine, mMockChildSessionCallback); 990 991 IkeSessionStateMachine ikeSession = 992 new IkeSessionStateMachine( 993 mLooper.getLooper(), 994 mSpyContext, 995 mIpSecManager, 996 mMockConnectManager, 997 ikeParams, 998 mChildSessionParams, 999 mSpyUserCbExecutor, 1000 mMockIkeSessionCallback, 1001 mMockChildSessionCallback, 1002 mSpyDeps); 1003 setupIkeConnectionCtrlCbWithIkeSession(mockIkeConnectionCtrlCb, ikeSession); 1004 1005 ikeSession.setDbg(true); 1006 1007 mLooper.dispatchAll(); 1008 mMockCurrentIkeSocket = mSpyIkeConnectionCtrl.getIkeSocket(); 1009 assertEquals(expectedRemoteAddress, mSpyIkeConnectionCtrl.getRemoteAddress()); 1010 1011 if (ikeParams.getConfiguredNetwork() == null) { 1012 verify(mMockConnectManager, atLeast(1)).getActiveNetwork(); 1013 } else { 1014 verify(mMockConnectManager, never()).getActiveNetwork(); 1015 } 1016 return ikeSession; 1017 } 1018 buildSaProposal()1019 public static IkeSaProposal buildSaProposal() throws Exception { 1020 return buildSaProposalCommon().addDhGroup(SaProposal.DH_GROUP_2048_BIT_MODP).build(); 1021 } 1022 buildNegotiatedSaProposal()1023 private static IkeSaProposal buildNegotiatedSaProposal() throws Exception { 1024 return buildSaProposalCommon().build(); 1025 } 1026 buildSaProposalCommon()1027 private static IkeSaProposal.Builder buildSaProposalCommon() throws Exception { 1028 return new IkeSaProposal.Builder() 1029 .addEncryptionAlgorithm( 1030 SaProposal.ENCRYPTION_ALGORITHM_AES_CBC, SaProposal.KEY_LEN_AES_128) 1031 .addIntegrityAlgorithm(SaProposal.INTEGRITY_ALGORITHM_HMAC_SHA1_96) 1032 .addPseudorandomFunction(SaProposal.PSEUDORANDOM_FUNCTION_HMAC_SHA1) 1033 .addDhGroup(SaProposal.DH_GROUP_1024_BIT_MODP); 1034 } 1035 buildIkeSessionParamsCommon()1036 private IkeSessionParams.Builder buildIkeSessionParamsCommon() throws Exception { 1037 return new IkeSessionParams.Builder(mMockConnectManager) 1038 .setServerHostname(REMOTE_HOSTNAME) 1039 .addSaProposal(buildSaProposal()) 1040 .setLocalIdentification(LOCAL_ID_IPV4) 1041 .setRemoteIdentification(REMOTE_ID_FQDN) 1042 .setNattKeepAliveDelaySeconds(NATT_KEEPALIVE_DELAY) 1043 .addPcscfServerRequest(AF_INET) 1044 .addPcscfServerRequest(AF_INET6) 1045 .setRetransmissionTimeoutsMillis( 1046 new int[] {5000, 10000, 20000, 30000, 40000, 50000}); 1047 } 1048 buildIkeSessionParams()1049 private IkeSessionParams buildIkeSessionParams() throws Exception { 1050 return buildIkeSessionParamsCommon().setAuthPsk(mPsk).build(); 1051 } 1052 buildIkeSessionParamsPsk(byte[] psk)1053 private IkeSessionParams buildIkeSessionParamsPsk(byte[] psk) throws Exception { 1054 return buildIkeSessionParamsCommon().setAuthPsk(psk).build(); 1055 } 1056 buildIkeSessionParamsEap()1057 private IkeSessionParams buildIkeSessionParamsEap() throws Exception { 1058 return buildIkeSessionParamsCommon() 1059 .setAuthEap(mRootCertificate, mEapSessionConfig) 1060 .build(); 1061 } 1062 buildIkeSessionParamsEapAkaWithDeviceIdentity()1063 private IkeSessionParams buildIkeSessionParamsEapAkaWithDeviceIdentity() throws Exception { 1064 Ike3gppParams ike3gppParams = 1065 new Ike3gppParams.Builder().setMobileDeviceIdentity(DEVICE_IDENTITY_IMEI).build(); 1066 Ike3gppExtension ike3gppExtension = 1067 new Ike3gppExtension(ike3gppParams, mock(Ike3gppDataListener.class)); 1068 mEapSessionConfigEapAka = 1069 new EapSessionConfig.Builder() 1070 .setEapAkaConfig(0, TelephonyManager.APPTYPE_ISIM) 1071 .build(); 1072 1073 return buildIkeSessionParamsCommon() 1074 .setAuthEap(mock(X509Certificate.class), mEapSessionConfigEapAka) 1075 .setIke3gppExtension(ike3gppExtension) 1076 .addIkeOption(IKE_OPTION_EAP_ONLY_AUTH) 1077 .build(); 1078 } 1079 buildIkeSessionParamsDigitalSignature()1080 private IkeSessionParams buildIkeSessionParamsDigitalSignature() throws Exception { 1081 return buildIkeSessionParamsCommon() 1082 .setAuthDigitalSignature(mRootCertificate, mUserEndCert, mUserPrivateKey) 1083 .build(); 1084 } 1085 buildIkeSessionParamsIke3gppExtension(byte pduSessionId)1086 private IkeSessionParams buildIkeSessionParamsIke3gppExtension(byte pduSessionId) 1087 throws Exception { 1088 Ike3gppExtension ike3gppExtension = 1089 new Ike3gppExtension( 1090 new Ike3gppParams.Builder().setPduSessionId(pduSessionId).build(), 1091 mMockIke3gppDataListener); 1092 return buildIkeSessionParamsCommon() 1093 .setAuthPsk(mPsk) 1094 .setIke3gppExtension(ike3gppExtension) 1095 .build(); 1096 } 1097 buildIkeSessionParamsWithIkeOptions(int... ikeOptions)1098 private IkeSessionParams buildIkeSessionParamsWithIkeOptions(int... ikeOptions) 1099 throws Exception { 1100 IkeSessionParams.Builder builder = buildIkeSessionParamsCommon().setAuthPsk(mPsk); 1101 for (int option : ikeOptions) { 1102 builder.addIkeOption(option); 1103 } 1104 1105 return builder.build(); 1106 } 1107 buildChildSessionParams()1108 private ChildSessionParams buildChildSessionParams() throws Exception { 1109 ChildSaProposal saProposal = 1110 new ChildSaProposal.Builder() 1111 .addEncryptionAlgorithm( 1112 SaProposal.ENCRYPTION_ALGORITHM_AES_CBC, SaProposal.KEY_LEN_AES_128) 1113 .addIntegrityAlgorithm(SaProposal.INTEGRITY_ALGORITHM_HMAC_SHA1_96) 1114 .build(); 1115 1116 return new TunnelModeChildSessionParams.Builder() 1117 .addSaProposal(saProposal) 1118 .addInternalAddressRequest(AF_INET) 1119 .addInternalAddressRequest(AF_INET6) 1120 .build(); 1121 } 1122 1123 // Common IKE INIT response makeIkeInitResponse()1124 private ReceivedIkePacket makeIkeInitResponse() throws Exception { 1125 List<Integer> payloadTypeList = new ArrayList<>(); 1126 List<String> payloadHexStringList = new ArrayList<>(); 1127 1128 payloadTypeList.add(IkePayload.PAYLOAD_TYPE_NOTIFY); 1129 payloadTypeList.add(IkePayload.PAYLOAD_TYPE_NOTIFY); 1130 payloadTypeList.add(IkePayload.PAYLOAD_TYPE_NOTIFY); 1131 payloadTypeList.add(IkePayload.PAYLOAD_TYPE_NOTIFY); 1132 payloadTypeList.add(IkePayload.PAYLOAD_TYPE_VENDOR); 1133 1134 payloadHexStringList.add(NAT_DETECTION_SOURCE_PAYLOAD_HEX_STRING); 1135 payloadHexStringList.add(NAT_DETECTION_DESTINATION_PAYLOAD_HEX_STRING); 1136 payloadHexStringList.add(FRAGMENTATION_SUPPORTED_PAYLOAD_HEX_STRING); 1137 payloadHexStringList.add(SIGNATURE_HASH_SUPPORTED_PAYLOAD_HEX_STRING); 1138 payloadHexStringList.add(VENDOR_ID_PAYLOAD_HEX_STRING); 1139 1140 return makeIkeInitResponseWithRequiredPayloads(payloadTypeList, payloadHexStringList); 1141 } 1142 1143 // Simplest IKE INIT response that does not include any optional payloads makeIkeInitResponseWithRequiredPayloads( List<Integer> optionalPayloadTypes, List<String> optionalPayloadHexStrings)1144 private ReceivedIkePacket makeIkeInitResponseWithRequiredPayloads( 1145 List<Integer> optionalPayloadTypes, List<String> optionalPayloadHexStrings) 1146 throws Exception { 1147 List<Integer> payloadTypeList = new ArrayList<>(); 1148 List<String> payloadHexStringList = new ArrayList<>(); 1149 1150 payloadTypeList.add(IkePayload.PAYLOAD_TYPE_SA); 1151 payloadTypeList.add(IkePayload.PAYLOAD_TYPE_KE); 1152 payloadTypeList.add(IkePayload.PAYLOAD_TYPE_NONCE); 1153 payloadTypeList.addAll(optionalPayloadTypes); 1154 1155 payloadHexStringList.add(IKE_SA_PAYLOAD_HEX_STRING); 1156 payloadHexStringList.add(KE_PAYLOAD_HEX_STRING); 1157 payloadHexStringList.add(NONCE_RESP_PAYLOAD_HEX_STRING); 1158 payloadHexStringList.addAll(optionalPayloadHexStrings); 1159 1160 return makeDummyReceivedIkeInitRespPacket( 1161 payloadTypeList, 1162 payloadHexStringList); 1163 } 1164 getIkeAuthPayloadListWithChildPayloads( List<IkePayload> authRelatedPayloads)1165 private List<IkePayload> getIkeAuthPayloadListWithChildPayloads( 1166 List<IkePayload> authRelatedPayloads) throws Exception { 1167 List<Integer> payloadTypeList = new ArrayList<>(); 1168 List<String> payloadHexStringList = new ArrayList<>(); 1169 1170 payloadTypeList.add(IkePayload.PAYLOAD_TYPE_SA); 1171 payloadTypeList.add(IkePayload.PAYLOAD_TYPE_TS_INITIATOR); 1172 payloadTypeList.add(IkePayload.PAYLOAD_TYPE_TS_RESPONDER); 1173 1174 payloadHexStringList.add(CHILD_SA_PAYLOAD_HEX_STRING); 1175 payloadHexStringList.add(TS_INIT_PAYLOAD_HEX_STRING); 1176 payloadHexStringList.add(TS_RESP_PAYLOAD_HEX_STRING); 1177 1178 List<IkePayload> payloadList = 1179 hexStrListToIkePayloadList(payloadTypeList, payloadHexStringList, true /*isResp*/); 1180 payloadList.addAll(authRelatedPayloads); 1181 1182 return payloadList; 1183 } 1184 makeIkeAuthRespWithChildPayloads(List<IkePayload> authRelatedPayloads)1185 private ReceivedIkePacket makeIkeAuthRespWithChildPayloads(List<IkePayload> authRelatedPayloads) 1186 throws Exception { 1187 List<IkePayload> payloadList = getIkeAuthPayloadListWithChildPayloads(authRelatedPayloads); 1188 1189 return makeDummyEncryptedReceivedIkePacketWithPayloadList( 1190 mSpyCurrentIkeSaRecord, 1191 IkeHeader.EXCHANGE_TYPE_IKE_AUTH, 1192 true /*isResp*/, 1193 payloadList); 1194 } 1195 makeIkeAuthRespWithoutChildPayloads( List<IkePayload> authRelatedPayloads)1196 private ReceivedIkePacket makeIkeAuthRespWithoutChildPayloads( 1197 List<IkePayload> authRelatedPayloads) throws Exception { 1198 return makeDummyEncryptedReceivedIkePacketWithPayloadList( 1199 mSpyCurrentIkeSaRecord, 1200 IkeHeader.EXCHANGE_TYPE_IKE_AUTH, 1201 true /*isResp*/, 1202 authRelatedPayloads); 1203 } 1204 makeCreateChildCreateMessage(boolean isResp)1205 private ReceivedIkePacket makeCreateChildCreateMessage(boolean isResp) throws Exception { 1206 return makeDummyEncryptedReceivedIkePacketWithPayloadList( 1207 mSpyCurrentIkeSaRecord, 1208 IkeHeader.EXCHANGE_TYPE_CREATE_CHILD_SA, 1209 isResp, 1210 makeCreateChildPayloadList(isResp)); 1211 } 1212 makeRekeyChildCreateMessage(boolean isResp, int spi)1213 private ReceivedIkePacket makeRekeyChildCreateMessage(boolean isResp, int spi) 1214 throws Exception { 1215 IkeNotifyPayload rekeyPayload = 1216 new IkeNotifyPayload( 1217 IkePayload.PROTOCOL_ID_ESP, 1218 spi, 1219 IkeNotifyPayload.NOTIFY_TYPE_REKEY_SA, 1220 new byte[0]); 1221 1222 List<IkePayload> payloadList = makeCreateChildPayloadList(isResp); 1223 payloadList.add(rekeyPayload); 1224 1225 return makeDummyEncryptedReceivedIkePacketWithPayloadList( 1226 mSpyCurrentIkeSaRecord, 1227 IkeHeader.EXCHANGE_TYPE_CREATE_CHILD_SA, 1228 isResp, 1229 payloadList); 1230 } 1231 makeCreateChildPayloadList(boolean isResp)1232 private List<IkePayload> makeCreateChildPayloadList(boolean isResp) throws Exception { 1233 List<Integer> payloadTypeList = new ArrayList<>(); 1234 List<String> payloadHexStringList = new ArrayList<>(); 1235 1236 payloadTypeList.add(IkePayload.PAYLOAD_TYPE_SA); 1237 payloadTypeList.add(IkePayload.PAYLOAD_TYPE_NONCE); 1238 payloadTypeList.add(IkePayload.PAYLOAD_TYPE_TS_INITIATOR); 1239 payloadTypeList.add(IkePayload.PAYLOAD_TYPE_TS_RESPONDER); 1240 1241 payloadHexStringList.add(CHILD_SA_PAYLOAD_HEX_STRING); 1242 payloadHexStringList.add(NONCE_RESP_PAYLOAD_HEX_STRING); 1243 payloadHexStringList.add(TS_INIT_PAYLOAD_HEX_STRING); 1244 payloadHexStringList.add(TS_RESP_PAYLOAD_HEX_STRING); 1245 1246 return hexStrListToIkePayloadList(payloadTypeList, payloadHexStringList, isResp); 1247 } 1248 makeDeleteChildPacket(IkeDeletePayload[] payloads, boolean isResp)1249 private ReceivedIkePacket makeDeleteChildPacket(IkeDeletePayload[] payloads, boolean isResp) 1250 throws Exception { 1251 return makeDummyEncryptedReceivedIkePacketWithPayloadList( 1252 mSpyCurrentIkeSaRecord, 1253 IkeHeader.EXCHANGE_TYPE_INFORMATIONAL, 1254 isResp, 1255 Arrays.asList(payloads)); 1256 } 1257 makeRekeyIkeResponse()1258 private ReceivedIkePacket makeRekeyIkeResponse() throws Exception { 1259 List<Integer> payloadTypeList = new ArrayList<>(); 1260 List<String> payloadHexStringList = new ArrayList<>(); 1261 1262 payloadTypeList.add(IkePayload.PAYLOAD_TYPE_SA); 1263 payloadTypeList.add(IkePayload.PAYLOAD_TYPE_KE); 1264 payloadTypeList.add(IkePayload.PAYLOAD_TYPE_NONCE); 1265 1266 payloadHexStringList.add(IKE_REKEY_SA_PAYLOAD_HEX_STRING); 1267 payloadHexStringList.add(KE_PAYLOAD_HEX_STRING); 1268 payloadHexStringList.add(NONCE_RESP_PAYLOAD_HEX_STRING); 1269 1270 return makeDummyEncryptedReceivedIkePacket( 1271 mSpyCurrentIkeSaRecord, 1272 IkeHeader.EXCHANGE_TYPE_CREATE_CHILD_SA, 1273 true /*isResp*/, 1274 payloadTypeList, 1275 payloadHexStringList); 1276 } 1277 makeDeleteIkeResponse(IkeSaRecord ikeSaRecord)1278 private ReceivedIkePacket makeDeleteIkeResponse(IkeSaRecord ikeSaRecord) throws Exception { 1279 return makeDummyEncryptedReceivedIkePacket( 1280 ikeSaRecord, 1281 IkeHeader.EXCHANGE_TYPE_INFORMATIONAL, 1282 true /*isResp*/, 1283 new ArrayList<>(), 1284 new ArrayList<>()); 1285 } 1286 makeDpdIkeRequest(IkeSaRecord saRecord)1287 private ReceivedIkePacket makeDpdIkeRequest(IkeSaRecord saRecord) throws Exception { 1288 return makeDummyEncryptedReceivedIkePacket( 1289 saRecord, 1290 IkeHeader.EXCHANGE_TYPE_INFORMATIONAL, 1291 false /*isResp*/, 1292 new ArrayList<>(), 1293 new ArrayList<>()); 1294 } 1295 makeDpdIkeRequest(int msgId, byte[] dummyIkePacketBytes)1296 private ReceivedIkePacket makeDpdIkeRequest(int msgId, byte[] dummyIkePacketBytes) 1297 throws Exception { 1298 return makeDummyEncryptedReceivedIkePacketWithPayloadList( 1299 mSpyCurrentIkeSaRecord, 1300 EXCHANGE_TYPE_INFORMATIONAL, 1301 false /*isResp*/, 1302 msgId, 1303 new ArrayList<>(), 1304 dummyIkePacketBytes); 1305 } 1306 makeDeviceIdentityIkeRequest()1307 private ReceivedIkePacket makeDeviceIdentityIkeRequest() throws Exception { 1308 IkeNotifyPayload deviceIdentity = 1309 new IkeNotifyPayload( 1310 NOTIFY_TYPE_DEVICE_IDENTITY, HexDump.hexStringToByteArray("01")); 1311 return makeDummyEncryptedReceivedIkePacketWithPayloadList( 1312 mSpyCurrentIkeSaRecord, 1313 EXCHANGE_TYPE_INFORMATIONAL, 1314 false /*isResp*/, 1315 Arrays.asList(deviceIdentity)); 1316 } 1317 makeRoutabilityCheckIkeRequest()1318 private ReceivedIkePacket makeRoutabilityCheckIkeRequest() throws Exception { 1319 IkeNotifyPayload cookie2Notify = new IkeNotifyPayload(NOTIFY_TYPE_COOKIE2, COOKIE2_DATA); 1320 return makeDummyEncryptedReceivedIkePacketWithPayloadList( 1321 mSpyCurrentIkeSaRecord, 1322 EXCHANGE_TYPE_INFORMATIONAL, 1323 false /*isResp*/, 1324 Arrays.asList(cookie2Notify)); 1325 } 1326 makeRekeyIkeRequest()1327 private ReceivedIkePacket makeRekeyIkeRequest() throws Exception { 1328 IkeSaPayload saPayload = 1329 (IkeSaPayload) 1330 IkeTestUtils.hexStringToIkePayload( 1331 IkePayload.PAYLOAD_TYPE_SA, 1332 false /*isResp*/, 1333 IKE_REKEY_SA_PAYLOAD_HEX_STRING); 1334 return makeRekeyIkeRequest(saPayload); 1335 } 1336 makeRekeyIkeRequestWithUnacceptableProposal()1337 private ReceivedIkePacket makeRekeyIkeRequestWithUnacceptableProposal() throws Exception { 1338 IkeSaPayload saPayload = 1339 (IkeSaPayload) 1340 IkeTestUtils.hexStringToIkePayload( 1341 IkePayload.PAYLOAD_TYPE_SA, 1342 false /*isResp*/, 1343 IKE_REKEY_UNACCEPTABLE_SA_PAYLOAD_HEX_STRING); 1344 return makeRekeyIkeRequest(saPayload); 1345 } 1346 makeRekeyIkeRequestWithPayloads(List<IkePayload> payloads)1347 private ReceivedIkePacket makeRekeyIkeRequestWithPayloads(List<IkePayload> payloads) 1348 throws Exception { 1349 return makeDummyEncryptedReceivedIkePacketWithPayloadList( 1350 mSpyCurrentIkeSaRecord, 1351 IkeHeader.EXCHANGE_TYPE_CREATE_CHILD_SA, 1352 false /*isResp*/, 1353 payloads); 1354 } 1355 makeRekeyIkeRequest(IkeSaPayload saPayload)1356 private ReceivedIkePacket makeRekeyIkeRequest(IkeSaPayload saPayload) throws Exception { 1357 List<Integer> payloadTypeList = new ArrayList<>(); 1358 List<String> payloadHexStringList = new ArrayList<>(); 1359 1360 payloadTypeList.add(IkePayload.PAYLOAD_TYPE_KE); 1361 payloadTypeList.add(IkePayload.PAYLOAD_TYPE_NONCE); 1362 1363 payloadHexStringList.add(KE_PAYLOAD_HEX_STRING); 1364 payloadHexStringList.add(NONCE_INIT_PAYLOAD_HEX_STRING); 1365 1366 List<IkePayload> payloadList = 1367 hexStrListToIkePayloadList(payloadTypeList, payloadHexStringList, false /*isResp*/); 1368 payloadList.add(saPayload); 1369 1370 return makeRekeyIkeRequestWithPayloads(payloadList); 1371 } 1372 makeDeleteIkeRequest(IkeSaRecord saRecord)1373 private ReceivedIkePacket makeDeleteIkeRequest(IkeSaRecord saRecord) throws Exception { 1374 List<Integer> payloadTypeList = new ArrayList<>(); 1375 List<String> payloadHexStringList = new ArrayList<>(); 1376 1377 payloadTypeList.add(IkePayload.PAYLOAD_TYPE_DELETE); 1378 1379 payloadHexStringList.add(DELETE_IKE_PAYLOAD_HEX_STRING); 1380 1381 return makeDummyEncryptedReceivedIkePacket( 1382 saRecord, 1383 IkeHeader.EXCHANGE_TYPE_INFORMATIONAL, 1384 false /*isResp*/, 1385 payloadTypeList, 1386 payloadHexStringList); 1387 } 1388 makeResponseWithErrorNotify(IkeNotifyPayload notify)1389 private ReceivedIkePacket makeResponseWithErrorNotify(IkeNotifyPayload notify) 1390 throws Exception { 1391 List<IkePayload> payloads = new ArrayList<>(); 1392 payloads.add(notify); 1393 return makeDummyEncryptedReceivedIkePacketWithPayloadList( 1394 mSpyCurrentIkeSaRecord, EXCHANGE_TYPE_INFORMATIONAL, true /*isResp*/, payloads); 1395 } 1396 isIkePayloadExist( List<IkePayload> payloadList, @IkePayload.PayloadType int payloadType)1397 private static boolean isIkePayloadExist( 1398 List<IkePayload> payloadList, @IkePayload.PayloadType int payloadType) { 1399 for (IkePayload payload : payloadList) { 1400 if (payload.payloadType == payloadType) return true; 1401 } 1402 return false; 1403 } 1404 isNotifyExist( List<IkePayload> payloadList, @IkeNotifyPayload.NotifyType int notifyType)1405 private static boolean isNotifyExist( 1406 List<IkePayload> payloadList, @IkeNotifyPayload.NotifyType int notifyType) { 1407 for (IkeNotifyPayload notify : 1408 IkePayload.getPayloadListForTypeInProvidedList( 1409 PAYLOAD_TYPE_NOTIFY, IkeNotifyPayload.class, payloadList)) { 1410 if (notify.notifyType == notifyType) return true; 1411 } 1412 return false; 1413 } 1414 assertByteArrayListEquals( List<byte[]> expectedList, List<byte[]> resultList)1415 private static void assertByteArrayListEquals( 1416 List<byte[]> expectedList, List<byte[]> resultList) { 1417 assertEquals(expectedList.size(), resultList.size()); 1418 for (int i = 0; i < expectedList.size(); i++) { 1419 assertArrayEquals(expectedList.get(i), resultList.get(i)); 1420 } 1421 } 1422 verifyIncrementLocaReqMsgId()1423 private void verifyIncrementLocaReqMsgId() { 1424 assertEquals( 1425 ++mExpectedCurrentSaLocalReqMsgId, 1426 mSpyCurrentIkeSaRecord.getLocalRequestMessageId()); 1427 } 1428 verifyIncrementRemoteReqMsgId()1429 private void verifyIncrementRemoteReqMsgId() { 1430 assertEquals( 1431 ++mExpectedCurrentSaRemoteReqMsgId, 1432 mSpyCurrentIkeSaRecord.getRemoteRequestMessageId()); 1433 } 1434 verifyRetransmissionStarted()1435 private void verifyRetransmissionStarted() { 1436 assertTrue( 1437 mIkeSessionStateMachine 1438 .getHandler() 1439 .hasMessages(IkeSessionStateMachine.CMD_RETRANSMIT)); 1440 } 1441 verifyRetransmissionStopped()1442 private void verifyRetransmissionStopped() { 1443 assertFalse( 1444 mIkeSessionStateMachine 1445 .getHandler() 1446 .hasMessages(IkeSessionStateMachine.CMD_RETRANSMIT)); 1447 } 1448 verifyEncryptAndEncodeAndGetMessage(IkeSaRecord ikeSaRecord)1449 private IkeMessage verifyEncryptAndEncodeAndGetMessage(IkeSaRecord ikeSaRecord) { 1450 verify(mMockIkeMessageHelper) 1451 .encryptAndEncode( 1452 anyObject(), 1453 anyObject(), 1454 eq(ikeSaRecord), 1455 mIkeMessageCaptor.capture(), 1456 anyBoolean(), 1457 anyInt()); 1458 return mIkeMessageCaptor.getValue(); 1459 } 1460 verifyEncryptAndEncodeNeverCalled(IkeSaRecord ikeSaRecord)1461 private void verifyEncryptAndEncodeNeverCalled(IkeSaRecord ikeSaRecord) { 1462 verify(mMockIkeMessageHelper, never()) 1463 .encryptAndEncode( 1464 anyObject(), 1465 anyObject(), 1466 eq(ikeSaRecord), 1467 any(IkeMessage.class), 1468 anyBoolean(), 1469 anyInt()); 1470 } 1471 verifyEncryptAndEncodeNeverCalled()1472 private void verifyEncryptAndEncodeNeverCalled() { 1473 verify(mMockIkeMessageHelper, never()) 1474 .encryptAndEncode( 1475 anyObject(), 1476 anyObject(), 1477 any(IkeSaRecord.class), 1478 any(IkeMessage.class), 1479 anyBoolean(), 1480 anyInt()); 1481 } 1482 resetMockIkeMessageHelper()1483 private void resetMockIkeMessageHelper() { 1484 reset(mMockIkeMessageHelper); 1485 doReturn(new byte[0]).when(mMockIkeMessageHelper).encode(any()); 1486 doReturn(new byte[1][0]) 1487 .when(mMockIkeMessageHelper) 1488 .encryptAndEncode(any(), any(), any(), any(), anyBoolean(), anyInt()); 1489 } 1490 resetSpyUserCbExecutor()1491 private void resetSpyUserCbExecutor() { 1492 reset(mSpyUserCbExecutor); 1493 } 1494 1495 @Test testQuit()1496 public void testQuit() { 1497 mIkeSessionStateMachine.quit(); 1498 mLooper.dispatchAll(); 1499 1500 verify(mMockCurrentIkeSocket).releaseReference(eq(mSpyIkeConnectionCtrl)); 1501 verify(mMockBusyWakelock).release(); 1502 } 1503 1504 @Test testAllocateIkeSpi()1505 public void testAllocateIkeSpi() throws Exception { 1506 // Test randomness. 1507 IkeSecurityParameterIndex ikeSpiOne = IKE_SPI_GENERATOR.allocateSpi(LOCAL_ADDRESS); 1508 IkeSecurityParameterIndex ikeSpiTwo = IKE_SPI_GENERATOR.allocateSpi(LOCAL_ADDRESS); 1509 1510 assertNotEquals(ikeSpiOne.getSpi(), ikeSpiTwo.getSpi()); 1511 ikeSpiTwo.close(); 1512 1513 // Test duplicate SPIs. 1514 long spiValue = ikeSpiOne.getSpi(); 1515 try { 1516 IKE_SPI_GENERATOR.allocateSpi(LOCAL_ADDRESS, spiValue); 1517 fail("Expected to fail because duplicate SPI was assigned to the same address."); 1518 } catch (IOException expected) { 1519 1520 } 1521 1522 ikeSpiOne.close(); 1523 IkeSecurityParameterIndex ikeSpiThree = 1524 IKE_SPI_GENERATOR.allocateSpi(LOCAL_ADDRESS, spiValue); 1525 ikeSpiThree.close(); 1526 } 1527 setupFirstIkeSa()1528 private void setupFirstIkeSa() throws Exception { 1529 // Inject IkeSaRecord and release IKE SPI resource since we will lose their references 1530 // later. 1531 when(mMockSaRecordHelper.makeFirstIkeSaRecord(any(), any(), any())) 1532 .thenAnswer( 1533 (invocation) -> { 1534 captureAndReleaseIkeSpiResource(invocation, 2); 1535 mockScheduleRekey(mSpyCurrentIkeSaRecord.mSaLifetimeAlarmScheduler); 1536 mSpyCurrentIkeSaRecord.mSaLifetimeAlarmScheduler 1537 .scheduleLifetimeExpiryAlarm(anyString()); 1538 return mSpyCurrentIkeSaRecord; 1539 }); 1540 } 1541 setupRekeyedIkeSa(IkeSaRecord rekeySaRecord)1542 private void setupRekeyedIkeSa(IkeSaRecord rekeySaRecord) throws Exception { 1543 // Inject IkeSaRecord and release IKE SPI resource since we will lose their references 1544 // later. 1545 when(mMockSaRecordHelper.makeRekeyedIkeSaRecord( 1546 eq(mSpyCurrentIkeSaRecord), any(), any(), any(), any())) 1547 .thenAnswer( 1548 (invocation) -> { 1549 captureAndReleaseIkeSpiResource(invocation, 4); 1550 mockScheduleRekey(rekeySaRecord.mSaLifetimeAlarmScheduler); 1551 rekeySaRecord.mSaLifetimeAlarmScheduler.scheduleLifetimeExpiryAlarm( 1552 anyString()); 1553 return rekeySaRecord; 1554 }); 1555 } 1556 throwExceptionWhenMakeRekeyIkeSa(Exception exception)1557 private void throwExceptionWhenMakeRekeyIkeSa(Exception exception) throws Exception { 1558 // Inject IkeSaRecord and release IKE SPI resource since we will lose their references 1559 // later. 1560 when(mMockSaRecordHelper.makeRekeyedIkeSaRecord( 1561 eq(mSpyCurrentIkeSaRecord), any(), any(), any(), any())) 1562 .thenAnswer( 1563 (invocation) -> { 1564 captureAndReleaseIkeSpiResource(invocation, 4); 1565 throw exception; 1566 }); 1567 } 1568 captureAndReleaseIkeSpiResource(InvocationOnMock invocation, int ikeConfigIndex)1569 private void captureAndReleaseIkeSpiResource(InvocationOnMock invocation, int ikeConfigIndex) { 1570 IkeSaRecordConfig config = (IkeSaRecordConfig) invocation.getArguments()[ikeConfigIndex]; 1571 config.initSpi.close(); 1572 config.respSpi.close(); 1573 } 1574 setupDnsResolutionForNetwork( Network network, int dnsLookupsForSuccess, InetAddress remoteAddress)1575 private void setupDnsResolutionForNetwork( 1576 Network network, int dnsLookupsForSuccess, InetAddress remoteAddress) 1577 throws Exception { 1578 doAnswer(new Answer() { 1579 private int mAttempedDnsLookups = 0; 1580 1581 public Object answer(InvocationOnMock invocation) throws IOException { 1582 mAttempedDnsLookups++; 1583 if (mAttempedDnsLookups < dnsLookupsForSuccess) { 1584 throw new UnknownHostException("DNS failed"); 1585 } else { 1586 return new InetAddress[] {remoteAddress}; 1587 } 1588 } 1589 }).when(network).getAllByName(REMOTE_HOSTNAME); 1590 } 1591 verifyFireCallbackOnDnsFailure(IkeSessionCallback callback)1592 private void verifyFireCallbackOnDnsFailure(IkeSessionCallback callback) { 1593 if (SdkLevel.isAtLeastT()) { 1594 verify(callback).onClosedWithException( 1595 argThat(e -> e instanceof IkeIOException 1596 && e.getCause() instanceof UnknownHostException)); 1597 } else { 1598 verify(callback).onClosedWithException( 1599 argThat(e -> e instanceof IkeInternalException 1600 && e.getCause() instanceof IOException)); 1601 } 1602 } 1603 setupAndVerifyDnsResolutionForIkeSession( int dnsLookupsForSuccess, int expectedDnsLookups, boolean expectSessionClosed)1604 private void setupAndVerifyDnsResolutionForIkeSession( 1605 int dnsLookupsForSuccess, int expectedDnsLookups, boolean expectSessionClosed) 1606 throws Exception { 1607 mIkeSessionStateMachine.quitNow(); 1608 1609 // Reset the network to ignore DNS resolution from mIkeSessionStateMachine creation in 1610 // setUp() 1611 resetDefaultNetwork(); 1612 1613 setupDnsResolutionForNetwork(mMockDefaultNetwork, dnsLookupsForSuccess, REMOTE_ADDRESS); 1614 1615 IkeSessionParams ikeParams = 1616 buildIkeSessionParamsCommon() 1617 .setAuthPsk(mPsk) 1618 .setServerHostname(REMOTE_HOSTNAME) 1619 .build(); 1620 mIkeSessionStateMachine = 1621 makeAndStartIkeSession( 1622 ikeParams, 1623 LOCAL_ADDRESS, 1624 expectSessionClosed ? null : REMOTE_ADDRESS); 1625 1626 verify(mMockDefaultNetwork, times(expectedDnsLookups)).getAllByName(REMOTE_HOSTNAME); 1627 if (expectSessionClosed) { 1628 assertNull(mIkeSessionStateMachine.getCurrentState()); 1629 verifyFireCallbackOnDnsFailure(mMockIkeSessionCallback); 1630 } 1631 } 1632 1633 @Test testResolveRemoteHostName()1634 public void testResolveRemoteHostName() throws Exception { 1635 setupAndVerifyDnsResolutionForIkeSession( 1636 1 /* dnsLookupsForSuccess */, 1637 1 /* expectedDnsLookups */, 1638 false /* expectSessionClosed */); 1639 } 1640 1641 @Test testResolveRemoteHostNameWithDnsRetries()1642 public void testResolveRemoteHostNameWithDnsRetries() throws Exception { 1643 setupAndVerifyDnsResolutionForIkeSession( 1644 2 /* dnsLookupsForSuccess */, 1645 2 /* expectedDnsLookups */, 1646 false /* expectSessionClosed */); 1647 } 1648 1649 @Test testResolveRemoteHostNameWithDnsFailure()1650 public void testResolveRemoteHostNameWithDnsFailure() throws Exception { 1651 // Require more lookups for successful DNS than IKE allows to force failure 1652 setupAndVerifyDnsResolutionForIkeSession( 1653 4 /* dnsLookupsForSuccess */, 1654 3 /* expectedDnsLookups */, 1655 true /* expectSessionClosed */); 1656 } 1657 verifyTestMode(boolean isTestNetwork)1658 private void verifyTestMode(boolean isTestNetwork) throws Exception { 1659 doReturn(isTestNetwork) 1660 .when(mMockNetworkCapabilities) 1661 .hasTransport(RandomnessFactory.TRANSPORT_TEST); 1662 1663 Network network = mockNewNetworkAndAddress(true /*isIpv4*/); 1664 IkeSessionParams ikeParams = 1665 buildIkeSessionParamsCommon() 1666 .setNetwork(network) 1667 .setAuthPsk("psk".getBytes()) 1668 .build(); 1669 1670 // Clear #getActiveNetwork() call in #setUp() to pass the verification in 1671 // #makeAndStartIkeSession() 1672 resetMockConnectManager(); 1673 setupLocalAddressForNetwork(network, LOCAL_ADDRESS); 1674 setupRemoteAddressForNetwork(network, REMOTE_ADDRESS); 1675 IkeSessionStateMachine ikeSession = makeAndStartIkeSession(ikeParams); 1676 1677 SecureRandom random = ikeSession.mIkeContext.getRandomnessFactory().getRandom(); 1678 if (isTestNetwork) { 1679 assertNotNull(random); 1680 assertTrue(random instanceof DeterministicSecureRandom); 1681 } else { 1682 assertNull(random); 1683 } 1684 } 1685 1686 @Test testEnableTestMode()1687 public void testEnableTestMode() throws Exception { 1688 verifyTestMode(true /* isTestNetwork */); 1689 } 1690 1691 @Test testDisableTestMode()1692 public void testDisableTestMode() throws Exception { 1693 verifyTestMode(false /* isTestNetwork */); 1694 } 1695 verifyOutboundKePayload(int expectedDhGroup)1696 private void verifyOutboundKePayload(int expectedDhGroup) { 1697 verify(mMockIkeMessageHelper, atLeastOnce()).encode(mIkeMessageCaptor.capture()); 1698 IkeMessage reqMsg = mIkeMessageCaptor.getValue(); 1699 IkeKePayload kePayload = 1700 reqMsg.getPayloadForType(IkePayload.PAYLOAD_TYPE_KE, IkeKePayload.class); 1701 assertEquals(expectedDhGroup, kePayload.dhGroup); 1702 } 1703 1704 @Test testCreateIkeLocalIkeInitNegotiatesDhGroup()1705 public void testCreateIkeLocalIkeInitNegotiatesDhGroup() throws Exception { 1706 // Clear the calls triggered by starting IkeSessionStateMachine in #setup() 1707 reset(mSpyIkeConnectionCtrl); 1708 1709 setupFirstIkeSa(); 1710 mIkeSessionStateMachine.sendMessage(IkeSessionStateMachine.CMD_LOCAL_REQUEST_CREATE_IKE); 1711 mLooper.dispatchAll(); 1712 1713 // Verify we started with the top proposed DH group 1714 verifyOutboundKePayload(SaProposal.DH_GROUP_1024_BIT_MODP); 1715 1716 // Send back a INVALID_KE_PAYLOAD, and verify that the selected DH group changes 1717 resetMockIkeMessageHelper(); 1718 ReceivedIkePacket resp = 1719 makeDummyReceivedIkeInitRespPacket( 1720 Arrays.asList(IkePayload.PAYLOAD_TYPE_NOTIFY), 1721 Arrays.asList(INVALID_KE_PAYLOAD_HEX_STRING)); 1722 mIkeSessionStateMachine.sendMessage(IkeSessionStateMachine.CMD_RECEIVE_IKE_PACKET, resp); 1723 mLooper.dispatchAll(); 1724 1725 verifyOutboundKePayload(SaProposal.DH_GROUP_2048_BIT_MODP); 1726 verify(mSpyIkeConnectionCtrl, atLeast(1)).tearDown(); 1727 } 1728 getIkeInitRespWithCookie()1729 private ReceivedIkePacket getIkeInitRespWithCookie() throws Exception { 1730 IkeNotifyPayload inCookieNotify = new IkeNotifyPayload(NOTIFY_TYPE_COOKIE, COOKIE_DATA); 1731 List<IkePayload> payloads = new ArrayList<>(); 1732 payloads.add(inCookieNotify); 1733 return makeDummyReceivedIkeInitRespPacket(payloads); 1734 } 1735 1736 @Test testCreateIkeLocalIkeInitReceivesCookie()1737 public void testCreateIkeLocalIkeInitReceivesCookie() throws Exception { 1738 setupFirstIkeSa(); 1739 1740 mIkeSessionStateMachine.sendMessage(IkeSessionStateMachine.CMD_LOCAL_REQUEST_CREATE_IKE); 1741 mLooper.dispatchAll(); 1742 1743 // Encode 2 times: one for mIkeInitRequestBytes and one for sending packets 1744 verify(mMockIkeMessageHelper, times(2)).encode(mIkeMessageCaptor.capture()); 1745 IkeMessage originalReqMsg = mIkeMessageCaptor.getValue(); 1746 List<IkePayload> originalPayloadList = originalReqMsg.ikePayloadList; 1747 1748 // Reset to forget sending original IKE INIT request 1749 resetMockIkeMessageHelper(); 1750 1751 // Send back a Notify-Cookie 1752 ReceivedIkePacket resp = getIkeInitRespWithCookie(); 1753 mIkeSessionStateMachine.sendMessage(IkeSessionStateMachine.CMD_RECEIVE_IKE_PACKET, resp); 1754 mLooper.dispatchAll(); 1755 1756 // Verify retry IKE INIT request 1757 verify(mMockIkeMessageHelper, times(2)).encode(mIkeMessageCaptor.capture()); 1758 IkeMessage ikeInitReqMessage = mIkeMessageCaptor.getValue(); 1759 List<IkePayload> payloadList = ikeInitReqMessage.ikePayloadList; 1760 1761 IkeNotifyPayload outCookieNotify = (IkeNotifyPayload) payloadList.get(0); 1762 assertEquals(NOTIFY_TYPE_COOKIE, outCookieNotify.notifyType); 1763 assertArrayEquals(COOKIE_DATA, outCookieNotify.notifyData); 1764 1765 // First 4 payloads MUST follow RFC 4306 so that IKE library can be compatible with old 1766 // implementations. 1767 int[] expectedPayloadType = 1768 new int[] { 1769 PAYLOAD_TYPE_NOTIFY, PAYLOAD_TYPE_SA, PAYLOAD_TYPE_KE, PAYLOAD_TYPE_NONCE 1770 }; 1771 int len = expectedPayloadType.length; 1772 for (int i = 0; i < len; i++) { 1773 assertEquals(expectedPayloadType[i], payloadList.get(i).payloadType); 1774 } 1775 1776 assertEquals(originalPayloadList, payloadList.subList(1, payloadList.size())); 1777 1778 assertTrue( 1779 mIkeSessionStateMachine.getCurrentState() 1780 instanceof IkeSessionStateMachine.CreateIkeLocalIkeInit); 1781 } 1782 1783 @Test testCreateIkeLocalIkeInitRcvRespAfterRcvCookie()1784 public void testCreateIkeLocalIkeInitRcvRespAfterRcvCookie() throws Exception { 1785 setupFirstIkeSa(); 1786 1787 mIkeSessionStateMachine.sendMessage(IkeSessionStateMachine.CMD_LOCAL_REQUEST_CREATE_IKE); 1788 mLooper.dispatchAll(); 1789 1790 // Receive IKE INIT response with Cookie 1791 mIkeSessionStateMachine.sendMessage( 1792 IkeSessionStateMachine.CMD_RECEIVE_IKE_PACKET, getIkeInitRespWithCookie()); 1793 1794 // Receive IKE INIT response 1795 mIkeSessionStateMachine.sendMessage( 1796 IkeSessionStateMachine.CMD_RECEIVE_IKE_PACKET, makeIkeInitResponse()); 1797 mLooper.dispatchAll(); 1798 1799 assertTrue( 1800 mIkeSessionStateMachine.getCurrentState() 1801 instanceof IkeSessionStateMachine.CreateIkeLocalIkeAuth); 1802 verifyIkeSaNegotiationResult(); 1803 } 1804 1805 @Test testCreateIkeLocalIkeInitSwitchesToEncapPortsIpv4()1806 public void testCreateIkeLocalIkeInitSwitchesToEncapPortsIpv4() throws Exception { 1807 setupFirstIkeSa(); 1808 assertFalse(mSpyIkeConnectionCtrl.useUdpEncapSocket()); 1809 1810 triggerAndVerifyIkeInitReq(true /* expectingNatDetection */, true /* expectingFakedNatd */); 1811 1812 receiveAndGetIkeInitResp(); 1813 1814 assertTrue(mSpyIkeConnectionCtrl.useUdpEncapSocket()); 1815 assertEquals(NAT_DETECTED, mSpyIkeConnectionCtrl.getNatStatus()); 1816 1817 verify(mMockIkeUdp4Socket).unregisterIke(anyLong()); 1818 } 1819 restartIkeSessionWithEnforcePort4500AndVerifyIkeSocket()1820 private void restartIkeSessionWithEnforcePort4500AndVerifyIkeSocket() throws Exception { 1821 // Quit and start a new IKE Session with IKE_OPTION_FORCE_PORT_4500 1822 mIkeSessionStateMachine.quitNow(); 1823 IkeSessionParams ikeParams = 1824 buildIkeSessionParamsWithIkeOptions(IKE_OPTION_FORCE_PORT_4500); 1825 mIkeSessionStateMachine = makeAndStartIkeSession(ikeParams); 1826 mLooper.dispatchAll(); 1827 1828 assertTrue(mSpyIkeConnectionCtrl.useUdpEncapSocket()); 1829 } 1830 1831 @Test testInitialStateWithEnforcePort4500()1832 public void testInitialStateWithEnforcePort4500() throws Exception { 1833 restartIkeSessionWithEnforcePort4500AndVerifyIkeSocket(); 1834 } 1835 1836 @Test testCreateIkeLocalIkeInitNatTraversalWithEnforcePort4500()1837 public void testCreateIkeLocalIkeInitNatTraversalWithEnforcePort4500() throws Exception { 1838 restartIkeSessionWithEnforcePort4500AndVerifyIkeSocket(); 1839 setupFirstIkeSa(); 1840 assertTrue(mSpyIkeConnectionCtrl.useUdpEncapSocket()); 1841 1842 triggerAndVerifyIkeInitReq(true /* expectingNatDetection */, true /* expectingFakedNatd */); 1843 1844 receiveAndGetIkeInitResp(); 1845 1846 assertTrue(mSpyIkeConnectionCtrl.useUdpEncapSocket()); 1847 assertEquals(NAT_DETECTED, mSpyIkeConnectionCtrl.getNatStatus()); 1848 } 1849 1850 @Test testCreateIkeLocalIkeInitNatTraversalNotSupported()1851 public void testCreateIkeLocalIkeInitNatTraversalNotSupported() throws Exception { 1852 setupFirstIkeSa(); 1853 mIkeSessionStateMachine.sendMessage(IkeSessionStateMachine.CMD_LOCAL_REQUEST_CREATE_IKE); 1854 mLooper.dispatchAll(); 1855 1856 // Receive IKE INIT response 1857 ReceivedIkePacket dummyReceivedIkePacket = 1858 makeIkeInitResponseWithRequiredPayloads( 1859 Collections.emptyList(), Collections.emptyList()); 1860 mIkeSessionStateMachine.sendMessage( 1861 IkeSessionStateMachine.CMD_RECEIVE_IKE_PACKET, dummyReceivedIkePacket); 1862 mLooper.dispatchAll(); 1863 1864 // Validate socket switched 1865 assertEquals(mMockIkeUdp4Socket, mSpyIkeConnectionCtrl.getIkeSocket()); 1866 assertEquals(NAT_TRAVERSAL_UNSUPPORTED, mSpyIkeConnectionCtrl.getNatStatus()); 1867 verify(mMockIkeUdp4Socket, never()).unregisterIke(anyLong()); 1868 } 1869 verifyNatdSrcIpFromIkeInitReqMessage(IkeMessage ikeInitReqMessag)1870 private void verifyNatdSrcIpFromIkeInitReqMessage(IkeMessage ikeInitReqMessag) { 1871 verifyNatdSrcIpFromIkeInitReqMessage(ikeInitReqMessag, false /* expectingFakedNatd */); 1872 } 1873 verifyNatdSrcIpFromIkeInitReqMessage( IkeMessage ikeInitReqMessage, boolean expectingFakedNatd)1874 private void verifyNatdSrcIpFromIkeInitReqMessage( 1875 IkeMessage ikeInitReqMessage, boolean expectingFakedNatd) { 1876 List<IkeNotifyPayload> notifyPayloads = 1877 ikeInitReqMessage.getPayloadListForType( 1878 IkePayload.PAYLOAD_TYPE_NOTIFY, IkeNotifyPayload.class); 1879 IkeNotifyPayload natdSrcIpPayload = null; 1880 for (IkeNotifyPayload notifyPayload : notifyPayloads) { 1881 if (notifyPayload.notifyType == NOTIFY_TYPE_NAT_DETECTION_SOURCE_IP) { 1882 natdSrcIpPayload = notifyPayload; 1883 } 1884 } 1885 assertNotNull(natdSrcIpPayload); 1886 1887 byte[] localNatDataNotFaked = 1888 IkeNotifyPayload.generateNatDetectionData( 1889 ikeInitReqMessage.ikeHeader.ikeInitiatorSpi, 1890 ikeInitReqMessage.ikeHeader.ikeResponderSpi, 1891 mSpyIkeConnectionCtrl.getLocalAddress(), 1892 mSpyIkeConnectionCtrl.getLocalPort()); 1893 1894 assertEquals( 1895 !expectingFakedNatd, 1896 Arrays.equals(localNatDataNotFaked, natdSrcIpPayload.notifyData)); 1897 } 1898 triggerAndVerifyIkeInitReq(boolean expectingNatDetection)1899 private void triggerAndVerifyIkeInitReq(boolean expectingNatDetection) throws Exception { 1900 triggerAndVerifyIkeInitReq(expectingNatDetection, false); 1901 } 1902 triggerAndVerifyIkeInitReq( boolean expectingNatDetection, boolean expectingFakedNatd)1903 private void triggerAndVerifyIkeInitReq( 1904 boolean expectingNatDetection, boolean expectingFakedNatd) throws Exception { 1905 // Send IKE INIT request 1906 mIkeSessionStateMachine.sendMessage(IkeSessionStateMachine.CMD_LOCAL_REQUEST_CREATE_IKE); 1907 mLooper.dispatchAll(); 1908 verifyRetransmissionStarted(); 1909 1910 // Validate outbound IKE INIT request 1911 verify(mMockIkeMessageHelper, times(2)).encode(mIkeMessageCaptor.capture()); 1912 IkeMessage ikeInitReqMessage = mIkeMessageCaptor.getValue(); 1913 1914 IkeHeader ikeHeader = ikeInitReqMessage.ikeHeader; 1915 assertEquals(IkeHeader.EXCHANGE_TYPE_IKE_SA_INIT, ikeHeader.exchangeType); 1916 assertFalse(ikeHeader.isResponseMsg); 1917 assertTrue(ikeHeader.fromIkeInitiator); 1918 1919 List<IkePayload> payloadList = ikeInitReqMessage.ikePayloadList; 1920 assertTrue(isIkePayloadExist(payloadList, IkePayload.PAYLOAD_TYPE_SA)); 1921 assertTrue(isIkePayloadExist(payloadList, IkePayload.PAYLOAD_TYPE_KE)); 1922 assertTrue(isIkePayloadExist(payloadList, IkePayload.PAYLOAD_TYPE_NONCE)); 1923 assertTrue(isNotifyExist(payloadList, NOTIFY_TYPE_IKEV2_FRAGMENTATION_SUPPORTED)); 1924 assertTrue(isNotifyExist(payloadList, NOTIFY_TYPE_SIGNATURE_HASH_ALGORITHMS)); 1925 1926 assertEquals( 1927 expectingNatDetection, 1928 isNotifyExist(payloadList, NOTIFY_TYPE_NAT_DETECTION_SOURCE_IP)); 1929 assertEquals( 1930 expectingNatDetection, 1931 isNotifyExist(payloadList, NOTIFY_TYPE_NAT_DETECTION_DESTINATION_IP)); 1932 1933 if (expectingNatDetection) { 1934 verifyNatdSrcIpFromIkeInitReqMessage(ikeInitReqMessage, expectingFakedNatd); 1935 } 1936 } 1937 receiveAndGetIkeInitResp()1938 private ReceivedIkePacket receiveAndGetIkeInitResp() throws Exception { 1939 ReceivedIkePacket dummyReceivedIkePacket = makeIkeInitResponse(); 1940 mIkeSessionStateMachine.sendMessage( 1941 IkeSessionStateMachine.CMD_RECEIVE_IKE_PACKET, dummyReceivedIkePacket); 1942 mLooper.dispatchAll(); 1943 verifyIncrementLocaReqMsgId(); 1944 return dummyReceivedIkePacket; 1945 } 1946 1947 @Test 1948 @SdkSuppress(minSdkVersion = 31, codeName = "S") testCreateIkeLocalIkeInitWithoutIpv6NatD()1949 public void testCreateIkeLocalIkeInitWithoutIpv6NatD() throws Exception { 1950 mIkeSessionStateMachine.quitNow(); 1951 resetMockConnectManager(); 1952 resetMockIkeMessageHelper(); 1953 1954 // Restart mIkeSessionStateMachine so it uses IPv6 addresses 1955 final Network v6OnlyNetwork = 1956 mockNewNetworkAndAddress(false /* isIpv4 */, LOCAL_ADDRESS_V6, REMOTE_ADDRESS_V6); 1957 final IkeSessionParams params = 1958 buildIkeSessionParamsCommon() 1959 .setAuthPsk(mPsk) 1960 .setNetwork(v6OnlyNetwork) 1961 .addIkeOption(IKE_OPTION_MOBIKE) 1962 .build(); 1963 mIkeSessionStateMachine = 1964 makeAndStartIkeSession( 1965 params, 1966 LOCAL_ADDRESS_V6, 1967 REMOTE_ADDRESS_V6); 1968 setupFirstIkeSa(); 1969 1970 triggerAndVerifyIkeInitReq(false /* expectingNatDetection */); 1971 receiveAndGetIkeInitResp(); 1972 1973 assertTrue(mSpyIkeConnectionCtrl.getIkeSocket() instanceof IkeUdp6Socket); 1974 assertEquals(NAT_TRAVERSAL_SUPPORT_NOT_CHECKED, mSpyIkeConnectionCtrl.getNatStatus()); 1975 } 1976 1977 @Ignore disableTestCreateIkeLocalIkeInit()1978 public void disableTestCreateIkeLocalIkeInit() throws Exception { 1979 setupFirstIkeSa(); 1980 1981 triggerAndVerifyIkeInitReq(true /* expectingNatDetection */); 1982 final ReceivedIkePacket dummyReceivedIkePacket = receiveAndGetIkeInitResp(); 1983 1984 verify(mMockCurrentIkeSocket) 1985 .registerIke(eq(mSpyCurrentIkeSaRecord.getLocalSpi()), eq(mSpyIkeConnectionCtrl)); 1986 1987 verify(mMockIkeMessageHelper) 1988 .decode(0, dummyReceivedIkePacket.ikeHeader, dummyReceivedIkePacket.ikePacketBytes); 1989 assertTrue( 1990 mIkeSessionStateMachine.getCurrentState() 1991 instanceof IkeSessionStateMachine.CreateIkeLocalIkeAuth); 1992 verifyRetransmissionStarted(); 1993 verifyIkeSaNegotiationResult(); 1994 } 1995 verifyIkeSaNegotiationResult()1996 private void verifyIkeSaNegotiationResult() throws Exception { 1997 // Validate negotiated SA proposal. 1998 IkeSaProposal negotiatedProposal = mIkeSessionStateMachine.mSaProposal; 1999 assertNotNull(negotiatedProposal); 2000 2001 assertEquals( 2002 new EncryptionTransform[] {mIkeEncryptionTransform}, 2003 negotiatedProposal.getEncryptionTransforms()); 2004 assertEquals( 2005 new IntegrityTransform[] {mIkeIntegrityTransform}, 2006 negotiatedProposal.getIntegrityTransforms()); 2007 assertEquals(new PrfTransform[] {mIkePrfTransform}, negotiatedProposal.getPrfTransforms()); 2008 2009 // Validate current IkeSaRecord. 2010 verify(mMockSaRecordHelper) 2011 .makeFirstIkeSaRecord( 2012 any(IkeMessage.class), 2013 any(IkeMessage.class), 2014 mIkeSaRecordConfigCaptor.capture()); 2015 2016 IkeSaRecordConfig ikeSaRecordConfig = mIkeSaRecordConfigCaptor.getValue(); 2017 assertEquals(KEY_LEN_IKE_PRF, ikeSaRecordConfig.prf.getKeyLength()); 2018 assertEquals(KEY_LEN_IKE_INTE, ikeSaRecordConfig.integrityKeyLength); 2019 assertEquals(KEY_LEN_IKE_ENCR, ikeSaRecordConfig.encryptionKeyLength); 2020 assertNotNull(ikeSaRecordConfig.saLifetimeAlarmScheduler); 2021 2022 // Validate NAT detection 2023 assertEquals(NAT_DETECTED, mSpyIkeConnectionCtrl.getNatStatus()); 2024 2025 // Validate vendor IDs 2026 List<byte[]> vendorIds = new ArrayList<>(); 2027 vendorIds.add(REMOTE_VENDOR_ID_ONE); 2028 assertByteArrayListEquals(vendorIds, mIkeSessionStateMachine.mRemoteVendorIds); 2029 2030 // Validate fragmentation support negotiation 2031 assertEquals( 2032 Arrays.asList(EXTENSION_TYPE_FRAGMENTATION), 2033 mIkeSessionStateMachine.mEnabledExtensions); 2034 2035 // Validate Signature Hash Algorithms received in IKE INIT response 2036 Set<Short> expectedHashAlgos = new HashSet<Short>(); 2037 for (short algo : IkeAuthDigitalSignPayload.ALL_SIGNATURE_ALGO_TYPES) { 2038 expectedHashAlgos.add(algo); 2039 } 2040 assertEquals( 2041 expectedHashAlgos, 2042 ((CreateIkeLocalIkeAuth) mIkeSessionStateMachine.mCreateIkeLocalIkeAuth) 2043 .mSetupData 2044 .peerSignatureHashAlgorithms); 2045 } 2046 setIkeInitResults()2047 private void setIkeInitResults() throws Exception { 2048 mIkeSessionStateMachine.mIkeCipher = mock(IkeCipher.class); 2049 mIkeSessionStateMachine.mIkeIntegrity = mock(IkeMacIntegrity.class); 2050 mIkeSessionStateMachine.mIkePrf = mock(IkeMacPrf.class); 2051 mIkeSessionStateMachine.mSaProposal = buildNegotiatedSaProposal(); 2052 mIkeSessionStateMachine.mCurrentIkeSaRecord = mSpyCurrentIkeSaRecord; 2053 mIkeSessionStateMachine.mRemoteVendorIds = 2054 Arrays.asList(REMOTE_VENDOR_ID_ONE, REMOTE_VENDOR_ID_TWO); 2055 mIkeSessionStateMachine.mEnabledExtensions.add(EXTENSION_TYPE_FRAGMENTATION); 2056 mIkeSessionStateMachine.addIkeSaRecord(mSpyCurrentIkeSaRecord); 2057 2058 mSpyIkeConnectionCtrl.handleNatDetectionResultInIkeInit( 2059 false /* isNatDetected */, mSpyCurrentIkeSaRecord.getLocalSpi()); 2060 mMockCurrentIkeSocket = mSpyIkeConnectionCtrl.getIkeSocket(); 2061 } 2062 2063 /** Initializes the mIkeSessionStateMachine in the IDLE state. */ setupIdleStateMachine()2064 private void setupIdleStateMachine() throws Exception { 2065 verify(mMockBusyWakelock).acquire(); 2066 2067 setIkeInitResults(); 2068 2069 mIkeSessionStateMachine.sendMessage( 2070 IkeSessionStateMachine.CMD_FORCE_TRANSITION, mIkeSessionStateMachine.mIdle); 2071 mLooper.dispatchAll(); 2072 2073 mDummyChildSmCallback = 2074 createChildAndGetChildSessionSmCallback( 2075 mMockChildSessionStateMachine, CHILD_SPI_REMOTE, mMockChildSessionCallback); 2076 2077 assertTrue( 2078 mIkeSessionStateMachine.getCurrentState() instanceof IkeSessionStateMachine.Idle); 2079 2080 verify(mMockBusyWakelock).release(); 2081 2082 // For convenience to verify wakelocks in all other places. 2083 reset(mMockBusyWakelock); 2084 } 2085 2086 private abstract class IkeAuthTestPretestBase { 2087 protected IkeInitData mIkeInitData; 2088 IkeAuthTestPretestBase()2089 IkeAuthTestPretestBase() { 2090 this(new HashSet<>() /* peerSignatureHashAlgorithms */); 2091 } 2092 IkeAuthTestPretestBase(Set<Short> peerSignatureHashAlgorithms)2093 IkeAuthTestPretestBase(Set<Short> peerSignatureHashAlgorithms) { 2094 InitialSetupData initialSetupData = 2095 new InitialSetupData( 2096 mChildSessionParams, 2097 mMockChildSessionCallback, 2098 SaProposal.DH_GROUP_1024_BIT_MODP); 2099 2100 mIkeInitData = 2101 new IkeInitData( 2102 initialSetupData, 2103 new byte[0], 2104 new byte[0], 2105 new IkeNoncePayload(createMockRandomFactory()), 2106 new IkeNoncePayload(createMockRandomFactory()), 2107 peerSignatureHashAlgorithms); 2108 } 2109 mockIkeInitAndTransitionToIkeAuth()2110 public void mockIkeInitAndTransitionToIkeAuth() throws Exception { 2111 setIkeInitResults(); 2112 2113 // Need to create a real IkeMacPrf instance for authentication because we cannot inject 2114 // a method stub for IkeMacPrf#signBytes. IkeMacPrf#signBytes is inherited from a 2115 // package protected class IkePrf. We don't have the visibility to mock it. 2116 mIkeSessionStateMachine.mIkePrf = 2117 IkeMacPrf.create(new PrfTransform(SaProposal.PSEUDORANDOM_FUNCTION_HMAC_SHA1)); 2118 2119 performStateTransition(); 2120 } 2121 performStateTransition()2122 abstract void performStateTransition() throws Exception; 2123 } 2124 2125 private final class IkeFirstAuthTestPretest extends IkeAuthTestPretestBase { IkeFirstAuthTestPretest()2126 IkeFirstAuthTestPretest() { 2127 super(); 2128 } 2129 IkeFirstAuthTestPretest(Set<Short> peerSignatureHashAlgorithms)2130 IkeFirstAuthTestPretest(Set<Short> peerSignatureHashAlgorithms) { 2131 super(peerSignatureHashAlgorithms); 2132 } 2133 2134 @Override performStateTransition()2135 void performStateTransition() throws Exception { 2136 mIkeSessionStateMachine.mCreateIkeLocalIkeAuth.setIkeSetupData(mIkeInitData); 2137 mIkeSessionStateMachine.sendMessage( 2138 IkeSessionStateMachine.CMD_FORCE_TRANSITION, 2139 mIkeSessionStateMachine.mCreateIkeLocalIkeAuth); 2140 mLooper.dispatchAll(); 2141 } 2142 } 2143 2144 private abstract class IkeAuthEapTestPretestBase extends IkeAuthTestPretestBase { 2145 protected IkeAuthData mIkeAuthData; 2146 IkeAuthEapTestPretestBase(IkeIdPayload initIdPayload, IkeIdPayload respIdPayload)2147 IkeAuthEapTestPretestBase(IkeIdPayload initIdPayload, IkeIdPayload respIdPayload) 2148 throws Exception { 2149 super(); 2150 List<Integer> payloadTypeList = new ArrayList<>(); 2151 List<String> payloadHexStringList = new ArrayList<>(); 2152 2153 payloadTypeList.add(IkePayload.PAYLOAD_TYPE_SA); 2154 payloadTypeList.add(IkePayload.PAYLOAD_TYPE_TS_INITIATOR); 2155 payloadTypeList.add(IkePayload.PAYLOAD_TYPE_TS_RESPONDER); 2156 2157 payloadHexStringList.add(CHILD_SA_PAYLOAD_HEX_STRING); 2158 payloadHexStringList.add(TS_INIT_PAYLOAD_HEX_STRING); 2159 payloadHexStringList.add(TS_RESP_PAYLOAD_HEX_STRING); 2160 2161 List<IkePayload> firstChildReqList = 2162 hexStrListToIkePayloadList( 2163 payloadTypeList, payloadHexStringList, false /*isResp*/); 2164 mIkeAuthData = 2165 new IkeAuthData(mIkeInitData, initIdPayload, respIdPayload, firstChildReqList); 2166 } 2167 } 2168 buildMockIkeIdPayload()2169 private static IkeIdPayload buildMockIkeIdPayload() { 2170 IkeIdPayload idPayload = mock(IkeIdPayload.class); 2171 doReturn(new byte[0]).when(idPayload).getEncodedPayloadBody(); 2172 return idPayload; 2173 } 2174 2175 private final class IkeAuthInEapTestPretest extends IkeAuthEapTestPretestBase { IkeAuthInEapTestPretest()2176 IkeAuthInEapTestPretest() throws Exception { 2177 super(buildMockIkeIdPayload(), buildMockIkeIdPayload()); 2178 } 2179 2180 @Override performStateTransition()2181 void performStateTransition() throws Exception { 2182 mIkeSessionStateMachine.mCreateIkeLocalIkeAuthInEap.setIkeSetupData(mIkeAuthData); 2183 mIkeSessionStateMachine.sendMessage( 2184 IkeSessionStateMachine.CMD_FORCE_TRANSITION, 2185 mIkeSessionStateMachine.mCreateIkeLocalIkeAuthInEap); 2186 mLooper.dispatchAll(); 2187 } 2188 } 2189 2190 private final class IkeAuthPostEapTestPretest extends IkeAuthEapTestPretestBase { IkeAuthPostEapTestPretest(IkeIdPayload initIdPayload, IkeIdPayload respIdPayload)2191 IkeAuthPostEapTestPretest(IkeIdPayload initIdPayload, IkeIdPayload respIdPayload) 2192 throws Exception { 2193 super(initIdPayload, respIdPayload); 2194 } 2195 2196 @Override performStateTransition()2197 void performStateTransition() throws Exception { 2198 mIkeSessionStateMachine.mCreateIkeLocalIkeAuthPostEap.setIkeSetupData(mIkeAuthData); 2199 mIkeSessionStateMachine.sendMessage( 2200 IkeSessionStateMachine.CMD_FORCE_TRANSITION, 2201 mIkeSessionStateMachine.mCreateIkeLocalIkeAuthPostEap); 2202 mLooper.dispatchAll(); 2203 } 2204 } 2205 2206 /** 2207 * Utility to register a new callback -> state machine mapping. 2208 * 2209 * <p>Must be used if IkeSessionStateMachine.openChildSession() is not called, but commands 2210 * injected instead. 2211 * 2212 * @param callback The callback to be used for the mapping 2213 * @param sm The ChildSessionStateMachine instance to be used. 2214 */ registerChildStateMachine( ChildSessionCallback callback, ChildSessionStateMachine sm)2215 private void registerChildStateMachine( 2216 ChildSessionCallback callback, ChildSessionStateMachine sm) { 2217 injectChildSessionInSpyDeps(mSpyDeps, sm, callback); 2218 mIkeSessionStateMachine.registerChildSessionCallback( 2219 mChildSessionParams, callback, false /*isFirstChild*/); 2220 } 2221 verifyMakeChildAndReturnChildSmCb( ChildSessionCallback expectedChildSessionCb)2222 private IChildSessionSmCallback verifyMakeChildAndReturnChildSmCb( 2223 ChildSessionCallback expectedChildSessionCb) { 2224 ArgumentCaptor<IkeContext> ikeContextCaptor = ArgumentCaptor.forClass(IkeContext.class); 2225 verify(mSpyDeps) 2226 .newChildSessionStateMachine( 2227 ikeContextCaptor.capture(), 2228 any(ChildSessionStateMachine.Config.class), 2229 eq(expectedChildSessionCb), 2230 mChildSessionSmCbCaptor.capture()); 2231 2232 IkeContext ikeContext = ikeContextCaptor.getValue(); 2233 assertEquals(mLooper.getLooper(), ikeContext.getLooper()); 2234 assertEquals(mSpyContext, ikeContext.getContext()); 2235 2236 return mChildSessionSmCbCaptor.getValue(); 2237 } 2238 2239 @Test testCreateAdditionalChild()2240 public void testCreateAdditionalChild() throws Exception { 2241 setupIdleStateMachine(); 2242 2243 ChildSessionCallback childCallback = mock(ChildSessionCallback.class); 2244 ChildSessionStateMachine childStateMachine = mock(ChildSessionStateMachine.class); 2245 registerChildStateMachine(childCallback, childStateMachine); 2246 2247 mIkeSessionStateMachine.sendMessage( 2248 IkeSessionStateMachine.CMD_EXECUTE_LOCAL_REQ, 2249 mLocalRequestFactory.getChildLocalRequest( 2250 IkeSessionStateMachine.CMD_LOCAL_REQUEST_CREATE_CHILD, 2251 childCallback, 2252 mChildSessionParams)); 2253 mLooper.dispatchAll(); 2254 2255 assertTrue( 2256 mIkeSessionStateMachine.getCurrentState() 2257 instanceof IkeSessionStateMachine.ChildProcedureOngoing); 2258 verify(childStateMachine) 2259 .createChildSession( 2260 eq(LOCAL_ADDRESS), 2261 eq(REMOTE_ADDRESS), 2262 any(), // udpEncapSocket 2263 eq(mIkeSessionStateMachine.mIkePrf), 2264 eq(mIkeSessionStateMachine.mSaProposal.getDhGroupTransforms()[0].id), 2265 any()); // sk_d 2266 2267 IChildSessionSmCallback cb = verifyMakeChildAndReturnChildSmCb(childCallback); 2268 2269 // Mocking sending request 2270 cb.onOutboundPayloadsReady( 2271 IkeHeader.EXCHANGE_TYPE_CREATE_CHILD_SA, 2272 false /*isResp*/, 2273 new ArrayList<>(), 2274 childStateMachine); 2275 mLooper.dispatchAll(); 2276 verifyRetransmissionStarted(); 2277 2278 IkeMessage createChildRequest = verifyEncryptAndEncodeAndGetMessage(mSpyCurrentIkeSaRecord); 2279 2280 IkeHeader ikeHeader = createChildRequest.ikeHeader; 2281 assertEquals(IkeHeader.EXCHANGE_TYPE_CREATE_CHILD_SA, ikeHeader.exchangeType); 2282 assertFalse(ikeHeader.isResponseMsg); 2283 assertTrue(ikeHeader.fromIkeInitiator); 2284 assertEquals(mSpyCurrentIkeSaRecord.getLocalRequestMessageId(), ikeHeader.messageId); 2285 assertTrue(createChildRequest.ikePayloadList.isEmpty()); 2286 2287 assertTrue( 2288 mIkeSessionStateMachine.getCurrentState() 2289 instanceof IkeSessionStateMachine.ChildProcedureOngoing); 2290 2291 // Mocking receiving response 2292 ReceivedIkePacket dummyCreateChildResp = makeCreateChildCreateMessage(true /*isResp*/); 2293 mIkeSessionStateMachine.sendMessage( 2294 IkeSessionStateMachine.CMD_RECEIVE_IKE_PACKET, dummyCreateChildResp); 2295 mLooper.dispatchAll(); 2296 2297 verifyIncrementLocaReqMsgId(); 2298 verifyDecodeEncryptedMessage(mSpyCurrentIkeSaRecord, dummyCreateChildResp); 2299 2300 verify(childStateMachine) 2301 .receiveResponse( 2302 eq(IkeHeader.EXCHANGE_TYPE_CREATE_CHILD_SA), mPayloadListCaptor.capture()); 2303 2304 List<IkePayload> childRespList = mPayloadListCaptor.getValue(); 2305 assertTrue(isIkePayloadExist(childRespList, IkePayload.PAYLOAD_TYPE_SA)); 2306 assertTrue(isIkePayloadExist(childRespList, IkePayload.PAYLOAD_TYPE_TS_INITIATOR)); 2307 assertTrue(isIkePayloadExist(childRespList, IkePayload.PAYLOAD_TYPE_TS_RESPONDER)); 2308 assertTrue(isIkePayloadExist(childRespList, IkePayload.PAYLOAD_TYPE_NONCE)); 2309 2310 // Mock finishing procedure 2311 cb.onProcedureFinished(childStateMachine); 2312 mLooper.dispatchAll(); 2313 assertTrue( 2314 mIkeSessionStateMachine.getCurrentState() instanceof IkeSessionStateMachine.Idle); 2315 verifyRetransmissionStopped(); 2316 } 2317 2318 @Test testTriggerDeleteChildLocal()2319 public void testTriggerDeleteChildLocal() throws Exception { 2320 setupIdleStateMachine(); 2321 2322 mIkeSessionStateMachine.sendMessage( 2323 IkeSessionStateMachine.CMD_EXECUTE_LOCAL_REQ, 2324 mLocalRequestFactory.getChildLocalRequest( 2325 IkeSessionStateMachine.CMD_LOCAL_REQUEST_DELETE_CHILD, 2326 mMockChildSessionCallback, 2327 null /*childParams*/)); 2328 mLooper.dispatchAll(); 2329 2330 assertTrue( 2331 mIkeSessionStateMachine.getCurrentState() 2332 instanceof IkeSessionStateMachine.ChildProcedureOngoing); 2333 verify(mMockChildSessionStateMachine).deleteChildSession(); 2334 verify(mMockBusyWakelock).acquire(); 2335 } 2336 2337 @Test testHandleDeleteChildBeforeCreation()2338 public void testHandleDeleteChildBeforeCreation() throws Exception { 2339 setupIdleStateMachine(); 2340 2341 mIkeSessionStateMachine.sendMessage( 2342 IkeSessionStateMachine.CMD_EXECUTE_LOCAL_REQ, 2343 mLocalRequestFactory.getChildLocalRequest( 2344 IkeSessionStateMachine.CMD_LOCAL_REQUEST_DELETE_CHILD, 2345 mock(ChildSessionCallback.class), 2346 null /*childParams*/)); 2347 mLooper.dispatchAll(); 2348 2349 assertTrue( 2350 mIkeSessionStateMachine.getCurrentState() instanceof IkeSessionStateMachine.Idle); 2351 } 2352 2353 @Test testTriggerRekeyChildLocal()2354 public void testTriggerRekeyChildLocal() throws Exception { 2355 setupIdleStateMachine(); 2356 2357 mIkeSessionStateMachine.sendMessage( 2358 IkeSessionStateMachine.CMD_EXECUTE_LOCAL_REQ, 2359 mLocalRequestFactory.getChildLocalRequest( 2360 IkeSessionStateMachine.CMD_LOCAL_REQUEST_REKEY_CHILD, 2361 mMockChildSessionCallback, 2362 null /*childParams*/)); 2363 mLooper.dispatchAll(); 2364 2365 assertTrue( 2366 mIkeSessionStateMachine.getCurrentState() 2367 instanceof IkeSessionStateMachine.ChildProcedureOngoing); 2368 verify(mMockChildSessionStateMachine).rekeyChildSession(); 2369 verify(mMockBusyWakelock).acquire(); 2370 } 2371 createChildAndGetChildSessionSmCallback( ChildSessionStateMachine child, int remoteSpi)2372 private IChildSessionSmCallback createChildAndGetChildSessionSmCallback( 2373 ChildSessionStateMachine child, int remoteSpi) throws Exception { 2374 return createChildAndGetChildSessionSmCallback( 2375 child, remoteSpi, mock(ChildSessionCallback.class)); 2376 } 2377 createChildAndGetChildSessionSmCallback( ChildSessionStateMachine child, int remoteSpi, ChildSessionCallback childCallback)2378 private IChildSessionSmCallback createChildAndGetChildSessionSmCallback( 2379 ChildSessionStateMachine child, int remoteSpi, ChildSessionCallback childCallback) 2380 throws Exception { 2381 registerChildStateMachine(childCallback, child); 2382 2383 IChildSessionSmCallback cb = mIkeSessionStateMachine.new ChildSessionSmCallback(); 2384 cb.onChildSaCreated(remoteSpi, child); 2385 mLooper.dispatchAll(); 2386 2387 return cb; 2388 } 2389 transitionToChildProcedureOngoing()2390 private void transitionToChildProcedureOngoing() { 2391 mIkeSessionStateMachine.sendMessage( 2392 IkeSessionStateMachine.CMD_FORCE_TRANSITION, 2393 mIkeSessionStateMachine.mChildProcedureOngoing); 2394 mLooper.dispatchAll(); 2395 assertTrue( 2396 mIkeSessionStateMachine.getCurrentState() 2397 instanceof IkeSessionStateMachine.ChildProcedureOngoing); 2398 } 2399 verifyChildReceiveDeleteRequest( ChildSessionStateMachine child, IkeDeletePayload[] expectedDelPayloads)2400 private void verifyChildReceiveDeleteRequest( 2401 ChildSessionStateMachine child, IkeDeletePayload[] expectedDelPayloads) { 2402 verify(child) 2403 .receiveRequest( 2404 eq(IKE_EXCHANGE_SUBTYPE_DELETE_CHILD), 2405 eq(EXCHANGE_TYPE_INFORMATIONAL), 2406 mPayloadListCaptor.capture()); 2407 List<IkePayload> reqPayloads = mPayloadListCaptor.getValue(); 2408 2409 int numExpectedDelPayloads = expectedDelPayloads.length; 2410 assertEquals(numExpectedDelPayloads, reqPayloads.size()); 2411 2412 for (int i = 0; i < numExpectedDelPayloads; i++) { 2413 assertEquals(expectedDelPayloads[i], (IkeDeletePayload) reqPayloads.get(i)); 2414 } 2415 } 2416 outboundDeleteChildPayloadsReady( IChildSessionSmCallback childSmCb, IkeDeletePayload delPayload, boolean isResp, ChildSessionStateMachine child)2417 private void outboundDeleteChildPayloadsReady( 2418 IChildSessionSmCallback childSmCb, 2419 IkeDeletePayload delPayload, 2420 boolean isResp, 2421 ChildSessionStateMachine child) { 2422 List<IkePayload> outPayloadList = new ArrayList<>(); 2423 outPayloadList.add(delPayload); 2424 childSmCb.onOutboundPayloadsReady( 2425 IkeHeader.EXCHANGE_TYPE_INFORMATIONAL, isResp, outPayloadList, child); 2426 mLooper.dispatchAll(); 2427 } 2428 verifyOutInfoMsgHeaderAndGetPayloads(boolean isResp)2429 private List<IkePayload> verifyOutInfoMsgHeaderAndGetPayloads(boolean isResp) { 2430 IkeMessage deleteChildMessage = verifyEncryptAndEncodeAndGetMessage(mSpyCurrentIkeSaRecord); 2431 2432 IkeHeader ikeHeader = deleteChildMessage.ikeHeader; 2433 assertEquals(mSpyCurrentIkeSaRecord.getInitiatorSpi(), ikeHeader.ikeInitiatorSpi); 2434 assertEquals(mSpyCurrentIkeSaRecord.getResponderSpi(), ikeHeader.ikeResponderSpi); 2435 assertEquals(IkePayload.PAYLOAD_TYPE_SK, ikeHeader.nextPayloadType); 2436 assertEquals(IkeHeader.EXCHANGE_TYPE_INFORMATIONAL, ikeHeader.exchangeType); 2437 assertEquals(mSpyCurrentIkeSaRecord.isLocalInit, ikeHeader.fromIkeInitiator); 2438 assertEquals(isResp, ikeHeader.isResponseMsg); 2439 2440 return deleteChildMessage.ikePayloadList; 2441 } 2442 2443 @Test testDeferChildRequestToChildProcedureOngoing()2444 public void testDeferChildRequestToChildProcedureOngoing() throws Exception { 2445 setupIdleStateMachine(); 2446 2447 IkeDeletePayload[] inboundDelPayloads = 2448 new IkeDeletePayload[] {new IkeDeletePayload(new int[] {CHILD_SPI_REMOTE})}; 2449 mIkeSessionStateMachine.sendMessage( 2450 IkeSessionStateMachine.CMD_RECEIVE_IKE_PACKET, 2451 makeDeleteChildPacket(inboundDelPayloads, false /*isResp*/)); 2452 mLooper.dispatchAll(); 2453 2454 assertTrue( 2455 mIkeSessionStateMachine.getCurrentState() 2456 instanceof IkeSessionStateMachine.ChildProcedureOngoing); 2457 verifyChildReceiveDeleteRequest(mMockChildSessionStateMachine, inboundDelPayloads); 2458 } 2459 2460 @Test testRemoteDeleteOneChild()2461 public void testRemoteDeleteOneChild() throws Exception { 2462 setupIdleStateMachine(); 2463 transitionToChildProcedureOngoing(); 2464 2465 // Receive Delete Child Request 2466 IkeDeletePayload[] inboundDelPayloads = 2467 new IkeDeletePayload[] {new IkeDeletePayload(new int[] {CHILD_SPI_REMOTE})}; 2468 mIkeSessionStateMachine.sendMessage( 2469 IkeSessionStateMachine.CMD_RECEIVE_IKE_PACKET, 2470 makeDeleteChildPacket(inboundDelPayloads, false /*isResp*/)); 2471 mLooper.dispatchAll(); 2472 2473 // Verify received payloads 2474 verifyChildReceiveDeleteRequest(mMockChildSessionStateMachine, inboundDelPayloads); 2475 2476 // Outbound payload list ready 2477 IkeDeletePayload outDelPayload = new IkeDeletePayload(new int[] {CHILD_SPI_LOCAL}); 2478 outboundDeleteChildPayloadsReady( 2479 mDummyChildSmCallback, 2480 outDelPayload, 2481 true /*isResp*/, 2482 mMockChildSessionStateMachine); 2483 2484 // Verify outbound response 2485 List<IkePayload> payloadList = verifyOutInfoMsgHeaderAndGetPayloads(true /*isResp*/); 2486 assertEquals(1, payloadList.size()); 2487 assertEquals(outDelPayload, ((IkeDeletePayload) payloadList.get(0))); 2488 verify(mMockBusyWakelock).acquire(); 2489 } 2490 2491 @Test testRemoteDeleteMultipleChildSession()2492 public void testRemoteDeleteMultipleChildSession() throws Exception { 2493 ChildSessionStateMachine childOne = mock(ChildSessionStateMachine.class); 2494 int childOneRemoteSpi = 11; 2495 int childOneLocalSpi = 12; 2496 2497 ChildSessionStateMachine childTwo = mock(ChildSessionStateMachine.class); 2498 int childTwoRemoteSpi = 21; 2499 int childTwoLocalSpi = 22; 2500 2501 setupIdleStateMachine(); 2502 IChildSessionSmCallback childSmCbOne = 2503 createChildAndGetChildSessionSmCallback(childOne, childOneRemoteSpi); 2504 IChildSessionSmCallback childSmCbTwo = 2505 createChildAndGetChildSessionSmCallback(childTwo, childTwoRemoteSpi); 2506 2507 transitionToChildProcedureOngoing(); 2508 2509 // Receive Delete Child Request 2510 IkeDeletePayload[] inboundDelPayloads = 2511 new IkeDeletePayload[] { 2512 new IkeDeletePayload(new int[] {childOneRemoteSpi, childTwoRemoteSpi}) 2513 }; 2514 mIkeSessionStateMachine.sendMessage( 2515 IkeSessionStateMachine.CMD_RECEIVE_IKE_PACKET, 2516 makeDeleteChildPacket(inboundDelPayloads, false /*isResp*/)); 2517 mLooper.dispatchAll(); 2518 2519 // Verify received payloads 2520 verifyChildReceiveDeleteRequest(childOne, inboundDelPayloads); 2521 verifyChildReceiveDeleteRequest(childTwo, inboundDelPayloads); 2522 2523 // childOne outbound payload list ready 2524 IkeDeletePayload outDelPayloadOne = new IkeDeletePayload(new int[] {childOneLocalSpi}); 2525 outboundDeleteChildPayloadsReady(childSmCbOne, outDelPayloadOne, true /*isResp*/, childOne); 2526 mLooper.dispatchAll(); 2527 2528 // Verify that no response is sent 2529 verifyEncryptAndEncodeNeverCalled(mSpyCurrentIkeSaRecord); 2530 2531 // childTwo outbound payload list ready 2532 IkeDeletePayload outDelPayloadTwo = new IkeDeletePayload(new int[] {childTwoLocalSpi}); 2533 outboundDeleteChildPayloadsReady(childSmCbTwo, outDelPayloadTwo, true /*isResp*/, childTwo); 2534 mLooper.dispatchAll(); 2535 2536 // Verify outbound response 2537 List<IkePayload> payloadList = verifyOutInfoMsgHeaderAndGetPayloads(true /*isResp*/); 2538 assertEquals(2, payloadList.size()); 2539 assertEquals(outDelPayloadOne, ((IkeDeletePayload) payloadList.get(0))); 2540 assertEquals(outDelPayloadTwo, ((IkeDeletePayload) payloadList.get(1))); 2541 } 2542 2543 @Test testRemoteDeleteMultipleChildSaInSameSession()2544 public void testRemoteDeleteMultipleChildSaInSameSession() throws Exception { 2545 int newChildRemoteSpi = 21; 2546 int newChildLocalSpi = 22; 2547 2548 setupIdleStateMachine(); 2549 mDummyChildSmCallback.onChildSaCreated(newChildRemoteSpi, mMockChildSessionStateMachine); 2550 2551 transitionToChildProcedureOngoing(); 2552 2553 // Receive Delete Child Request 2554 IkeDeletePayload[] inboundDelPayloads = 2555 new IkeDeletePayload[] { 2556 new IkeDeletePayload(new int[] {CHILD_SPI_REMOTE}), 2557 new IkeDeletePayload(new int[] {newChildRemoteSpi}) 2558 }; 2559 mIkeSessionStateMachine.sendMessage( 2560 IkeSessionStateMachine.CMD_RECEIVE_IKE_PACKET, 2561 makeDeleteChildPacket(inboundDelPayloads, false /*isResp*/)); 2562 mLooper.dispatchAll(); 2563 2564 // Verify received payloads 2565 verifyChildReceiveDeleteRequest(mMockChildSessionStateMachine, inboundDelPayloads); 2566 2567 // child outbound payload list ready 2568 IkeDeletePayload outDelPayload = 2569 new IkeDeletePayload(new int[] {CHILD_SPI_LOCAL, newChildLocalSpi}); 2570 outboundDeleteChildPayloadsReady( 2571 mDummyChildSmCallback, 2572 outDelPayload, 2573 true /*isResp*/, 2574 mMockChildSessionStateMachine); 2575 mLooper.dispatchAll(); 2576 2577 // Verify outbound response 2578 List<IkePayload> payloadList = verifyOutInfoMsgHeaderAndGetPayloads(true /*isResp*/); 2579 assertEquals(1, payloadList.size()); 2580 assertEquals(outDelPayload, ((IkeDeletePayload) payloadList.get(0))); 2581 } 2582 2583 @Test testIgnoreUnrecognizedChildSpi()2584 public void testIgnoreUnrecognizedChildSpi() throws Exception { 2585 int unrecognizedSpi = 2; 2586 2587 setupIdleStateMachine(); 2588 transitionToChildProcedureOngoing(); 2589 2590 // Receive Delete Child Request 2591 IkeDeletePayload[] inboundDelPayloads = 2592 new IkeDeletePayload[] { 2593 new IkeDeletePayload(new int[] {unrecognizedSpi, CHILD_SPI_REMOTE}) 2594 }; 2595 mIkeSessionStateMachine.sendMessage( 2596 IkeSessionStateMachine.CMD_RECEIVE_IKE_PACKET, 2597 makeDeleteChildPacket(inboundDelPayloads, false /*isResp*/)); 2598 mLooper.dispatchAll(); 2599 2600 // Verify received payloads 2601 verifyChildReceiveDeleteRequest(mMockChildSessionStateMachine, inboundDelPayloads); 2602 2603 // child outbound payload list ready 2604 IkeDeletePayload outPayload = new IkeDeletePayload(new int[] {CHILD_SPI_LOCAL}); 2605 outboundDeleteChildPayloadsReady( 2606 mDummyChildSmCallback, outPayload, true /*isResp*/, mMockChildSessionStateMachine); 2607 mLooper.dispatchAll(); 2608 2609 // Verify outbound response 2610 List<IkePayload> payloadList = verifyOutInfoMsgHeaderAndGetPayloads(true /*isResp*/); 2611 assertEquals(1, payloadList.size()); 2612 assertEquals(outPayload, ((IkeDeletePayload) payloadList.get(0))); 2613 } 2614 2615 @Test testRemoteDeleteChildHandlesReqWithNoRecognizedSpi()2616 public void testRemoteDeleteChildHandlesReqWithNoRecognizedSpi() throws Exception { 2617 int unrecognizedSpi = 2; 2618 2619 setupIdleStateMachine(); 2620 2621 // Receive Delete Child Request without any recognized SPI 2622 IkeDeletePayload[] inboundDelPayloads = 2623 new IkeDeletePayload[] {new IkeDeletePayload(new int[] {unrecognizedSpi})}; 2624 mIkeSessionStateMachine.sendMessage( 2625 IkeSessionStateMachine.CMD_RECEIVE_IKE_PACKET, 2626 makeDeleteChildPacket(inboundDelPayloads, false /*isResp*/)); 2627 mLooper.dispatchAll(); 2628 2629 // Verify outbound empty response was sent 2630 List<IkePayload> payloadList = verifyOutInfoMsgHeaderAndGetPayloads(true /*isResp*/); 2631 assertTrue(payloadList.isEmpty()); 2632 2633 // Verify IKE Session was back to Idle 2634 assertTrue( 2635 mIkeSessionStateMachine.getCurrentState() instanceof IkeSessionStateMachine.Idle); 2636 } 2637 2638 @Test testRemoteCreateChild()2639 public void testRemoteCreateChild() throws Exception { 2640 setupIdleStateMachine(); 2641 2642 mIkeSessionStateMachine.sendMessage( 2643 CMD_RECEIVE_IKE_PACKET, makeCreateChildCreateMessage(false /*isResp*/)); 2644 2645 mLooper.dispatchAll(); 2646 2647 assertTrue( 2648 mIkeSessionStateMachine.getCurrentState() instanceof IkeSessionStateMachine.Idle); 2649 2650 List<IkePayload> ikePayloadList = verifyOutInfoMsgHeaderAndGetPayloads(true /*isResp*/); 2651 assertEquals(1, ikePayloadList.size()); 2652 assertEquals( 2653 ERROR_TYPE_NO_ADDITIONAL_SAS, 2654 ((IkeNotifyPayload) ikePayloadList.get(0)).notifyType); 2655 } 2656 2657 @Test testRemoteRekeyChild()2658 public void testRemoteRekeyChild() throws Exception { 2659 setupIdleStateMachine(); 2660 2661 // Receive Rekey Create request 2662 mIkeSessionStateMachine.sendMessage( 2663 CMD_RECEIVE_IKE_PACKET, 2664 makeRekeyChildCreateMessage(false /*isResp*/, CHILD_SPI_REMOTE)); 2665 mLooper.dispatchAll(); 2666 2667 verify(mMockChildSessionStateMachine) 2668 .receiveRequest( 2669 eq(IKE_EXCHANGE_SUBTYPE_REKEY_CHILD), 2670 eq(EXCHANGE_TYPE_CREATE_CHILD_SA), 2671 any(List.class)); 2672 assertTrue( 2673 mIkeSessionStateMachine.getCurrentState() 2674 instanceof IkeSessionStateMachine.ChildProcedureOngoing); 2675 2676 // Send Rekey Create response 2677 List<IkePayload> mockRekeyCreatePayloads = Arrays.asList(mock(IkePayload.class)); 2678 mDummyChildSmCallback.onOutboundPayloadsReady( 2679 IkeHeader.EXCHANGE_TYPE_CREATE_CHILD_SA, 2680 true /*isResp*/, 2681 mockRekeyCreatePayloads, 2682 mMockChildSessionStateMachine); 2683 mLooper.dispatchAll(); 2684 2685 IkeMessage rekeyCreateResp = 2686 verifyAndGetOutboundEncryptedResp(IkeHeader.EXCHANGE_TYPE_CREATE_CHILD_SA); 2687 assertEquals(mockRekeyCreatePayloads, rekeyCreateResp.ikePayloadList); 2688 2689 // Forget sending Rekey Create response 2690 resetMockIkeMessageHelper(); 2691 2692 // Receive Delete Child Request 2693 IkeDeletePayload[] inboundDelPayloads = 2694 new IkeDeletePayload[] {new IkeDeletePayload(new int[] {CHILD_SPI_REMOTE})}; 2695 mIkeSessionStateMachine.sendMessage( 2696 IkeSessionStateMachine.CMD_RECEIVE_IKE_PACKET, 2697 makeDeleteChildPacket(inboundDelPayloads, false /*isResp*/)); 2698 mLooper.dispatchAll(); 2699 2700 verify(mMockChildSessionStateMachine) 2701 .receiveRequest( 2702 eq(IKE_EXCHANGE_SUBTYPE_DELETE_CHILD), 2703 eq(EXCHANGE_TYPE_INFORMATIONAL), 2704 any(List.class)); 2705 2706 // Send Rekey Delete response 2707 List<IkePayload> mockRekeyDeletePayloads = Arrays.asList(mock(IkePayload.class)); 2708 mDummyChildSmCallback.onOutboundPayloadsReady( 2709 IkeHeader.EXCHANGE_TYPE_INFORMATIONAL, 2710 true /*isResp*/, 2711 mockRekeyDeletePayloads, 2712 mMockChildSessionStateMachine); 2713 mLooper.dispatchAll(); 2714 2715 IkeMessage rekeyDeleteResp = 2716 verifyAndGetOutboundEncryptedResp(IkeHeader.EXCHANGE_TYPE_INFORMATIONAL); 2717 assertEquals(mockRekeyDeletePayloads, rekeyDeleteResp.ikePayloadList); 2718 } 2719 2720 @Test testHandleRekeyChildReqWithUnrecognizedSpi()2721 public void testHandleRekeyChildReqWithUnrecognizedSpi() throws Exception { 2722 int unrecognizedSpi = 2; 2723 2724 setupIdleStateMachine(); 2725 2726 mIkeSessionStateMachine.sendMessage( 2727 CMD_RECEIVE_IKE_PACKET, 2728 makeRekeyChildCreateMessage(false /*isResp*/, unrecognizedSpi)); 2729 mLooper.dispatchAll(); 2730 2731 verify(mMockChildSessionStateMachine, never()).receiveRequest(anyInt(), anyInt(), any()); 2732 assertTrue( 2733 mIkeSessionStateMachine.getCurrentState() instanceof IkeSessionStateMachine.Idle); 2734 2735 List<IkePayload> ikePayloadList = verifyOutInfoMsgHeaderAndGetPayloads(true /*isResp*/); 2736 assertEquals(1, ikePayloadList.size()); 2737 IkeNotifyPayload notifyPayload = (IkeNotifyPayload) ikePayloadList.get(0); 2738 assertEquals(ERROR_TYPE_CHILD_SA_NOT_FOUND, notifyPayload.notifyType); 2739 assertEquals(unrecognizedSpi, notifyPayload.spi); 2740 } 2741 verifyNotifyUserCloseSession()2742 private void verifyNotifyUserCloseSession() { 2743 verify(mSpyUserCbExecutor).execute(any(Runnable.class)); 2744 verify(mMockIkeSessionCallback).onClosed(); 2745 } 2746 verifyNotifyUserCloseSessionWithException(Exception exception)2747 private void verifyNotifyUserCloseSessionWithException(Exception exception) { 2748 IkeException ikeException = 2749 exception instanceof IkeException 2750 ? (IkeException) exception 2751 : new IkeInternalException(exception); 2752 2753 verify(mSpyUserCbExecutor).execute(any(Runnable.class)); 2754 verify(mMockIkeSessionCallback) 2755 .onClosedWithException(argThat(e -> e.getCause() == ikeException.getCause())); 2756 } 2757 2758 @Test testRcvRemoteDeleteIkeWhenChildProcedureOngoing()2759 public void testRcvRemoteDeleteIkeWhenChildProcedureOngoing() throws Exception { 2760 setupIdleStateMachine(); 2761 transitionToChildProcedureOngoing(); 2762 2763 mIkeSessionStateMachine.sendMessage( 2764 CMD_RECEIVE_IKE_PACKET, makeDeleteIkeRequest(mSpyCurrentIkeSaRecord)); 2765 2766 mLooper.dispatchAll(); 2767 2768 verifyNotifyUserCloseSession(); 2769 2770 // Verify state machine quit properly 2771 assertNull(mIkeSessionStateMachine.getCurrentState()); 2772 2773 List<IkePayload> ikePayloadList = verifyOutInfoMsgHeaderAndGetPayloads(true /*isResp*/); 2774 assertTrue(ikePayloadList.isEmpty()); 2775 } 2776 2777 @Test testRcvRemoteRekeyIkeWhenChildProcedureOngoing()2778 public void testRcvRemoteRekeyIkeWhenChildProcedureOngoing() throws Exception { 2779 setupIdleStateMachine(); 2780 transitionToChildProcedureOngoing(); 2781 2782 mIkeSessionStateMachine.sendMessage(CMD_RECEIVE_IKE_PACKET, makeRekeyIkeRequest()); 2783 2784 mLooper.dispatchAll(); 2785 2786 // Since we have forced state machine to transition to ChildProcedureOngoing state without 2787 // really starting any Child procedure, it should transition to Idle at this time. 2788 assertTrue( 2789 mIkeSessionStateMachine.getCurrentState() instanceof IkeSessionStateMachine.Idle); 2790 2791 List<IkePayload> ikePayloadList = verifyOutInfoMsgHeaderAndGetPayloads(true /*isResp*/); 2792 assertEquals(1, ikePayloadList.size()); 2793 assertEquals( 2794 ERROR_TYPE_TEMPORARY_FAILURE, 2795 ((IkeNotifyPayload) ikePayloadList.get(0)).notifyType); 2796 } 2797 2798 @Test testKillChildSessions()2799 public void testKillChildSessions() throws Exception { 2800 setupIdleStateMachine(); 2801 2802 ChildSessionStateMachine childOne = mock(ChildSessionStateMachine.class); 2803 ChildSessionStateMachine childTwo = mock(ChildSessionStateMachine.class); 2804 registerChildStateMachine(mock(ChildSessionCallback.class), childOne); 2805 registerChildStateMachine(mock(ChildSessionCallback.class), childTwo); 2806 2807 mIkeSessionStateMachine.mCurrentIkeSaRecord = null; 2808 2809 mIkeSessionStateMachine.quitNow(); 2810 2811 mLooper.dispatchAll(); 2812 2813 verify(childOne).killSession(); 2814 verify(childTwo).killSession(); 2815 } 2816 verifyAuthReqAndGetMsg()2817 private IkeMessage verifyAuthReqAndGetMsg() { 2818 IkeMessage ikeAuthReqMessage = verifyEncryptAndEncodeAndGetMessage(mSpyCurrentIkeSaRecord); 2819 2820 IkeHeader ikeHeader = ikeAuthReqMessage.ikeHeader; 2821 assertEquals(IkeHeader.EXCHANGE_TYPE_IKE_AUTH, ikeHeader.exchangeType); 2822 assertFalse(ikeHeader.isResponseMsg); 2823 assertTrue(ikeHeader.fromIkeInitiator); 2824 2825 return ikeAuthReqMessage; 2826 } 2827 verifyAuthReqWithChildPayloadsAndGetMsg()2828 private IkeMessage verifyAuthReqWithChildPayloadsAndGetMsg() { 2829 IkeMessage ikeAuthReqMessage = verifyAuthReqAndGetMsg(); 2830 2831 assertNotNull( 2832 ikeAuthReqMessage.getPayloadForType( 2833 IkePayload.PAYLOAD_TYPE_ID_INITIATOR, IkeIdPayload.class)); 2834 assertNotNull( 2835 ikeAuthReqMessage.getPayloadForType( 2836 IkePayload.PAYLOAD_TYPE_ID_RESPONDER, IkeIdPayload.class)); 2837 assertNotNull( 2838 ikeAuthReqMessage.getPayloadForType( 2839 IkePayload.PAYLOAD_TYPE_SA, IkeSaPayload.class)); 2840 assertNotNull( 2841 ikeAuthReqMessage.getPayloadForType( 2842 IkePayload.PAYLOAD_TYPE_TS_INITIATOR, IkeTsPayload.class)); 2843 assertNotNull( 2844 ikeAuthReqMessage.getPayloadForType( 2845 IkePayload.PAYLOAD_TYPE_TS_RESPONDER, IkeTsPayload.class)); 2846 2847 IkeConfigPayload configPayload = 2848 ikeAuthReqMessage.getPayloadForType( 2849 IkePayload.PAYLOAD_TYPE_CP, IkeConfigPayload.class); 2850 assertNotNull(configPayload); 2851 2852 Map<Integer, Integer> expectedAttributes = 2853 Map.of( 2854 CONFIG_ATTR_IP4_PCSCF, 2855 1, 2856 CONFIG_ATTR_IP6_PCSCF, 2857 1, 2858 CONFIG_ATTR_INTERNAL_IP4_ADDRESS, 2859 1, 2860 CONFIG_ATTR_INTERNAL_IP6_ADDRESS, 2861 1, 2862 CONFIG_ATTR_APPLICATION_VERSION, 2863 1, 2864 CONFIG_ATTR_INTERNAL_IP4_NETMASK, 2865 1); 2866 Map<Integer, Integer> actualAttributes = 2867 buildAttributeMap(configPayload.recognizedAttributeList); 2868 assertEquals(expectedAttributes, actualAttributes); 2869 2870 IkeNoncePayload noncePayload = 2871 ikeAuthReqMessage.getPayloadForType( 2872 IkePayload.PAYLOAD_TYPE_NONCE, IkeNoncePayload.class); 2873 assertNull(noncePayload); 2874 2875 return ikeAuthReqMessage; 2876 } 2877 buildAttributeMap( List<IkeConfigPayload.ConfigAttribute> recognizedAttributeList)2878 private Map<Integer, Integer> buildAttributeMap( 2879 List<IkeConfigPayload.ConfigAttribute> recognizedAttributeList) { 2880 Map<Integer, Integer> attrCountMap = new HashMap<>(); 2881 for (IkeConfigPayload.ConfigAttribute attr : recognizedAttributeList) { 2882 attrCountMap.compute(attr.attributeType, (key, val) -> (val == null) ? 1 : val + 1); 2883 } 2884 2885 return attrCountMap; 2886 } 2887 verifyDigitalSignatureAuthentication( IkeAuthDigitalSignPayload spyAuthPayload, X509Certificate certificate, IkeIdPayload respIdPayload, List<IkePayload> authRelatedPayloads, boolean hasChildPayloads, boolean hasConfigPayloadInResp)2888 private void verifyDigitalSignatureAuthentication( 2889 IkeAuthDigitalSignPayload spyAuthPayload, 2890 X509Certificate certificate, 2891 IkeIdPayload respIdPayload, 2892 List<IkePayload> authRelatedPayloads, 2893 boolean hasChildPayloads, 2894 boolean hasConfigPayloadInResp) 2895 throws Exception { 2896 IkeMessage ikeAuthReqMessage = 2897 verifyAuthenticationCommonAndGetIkeMessage( 2898 respIdPayload, 2899 authRelatedPayloads, 2900 hasChildPayloads, 2901 hasConfigPayloadInResp, 2902 false /* isMobikeEnabled */, 2903 true /* isIpv4 */, 2904 0 /* ike3gppCallbackInvocations */); 2905 2906 // Calling mSpyCurrentIkeSaRecord.getSkPr() inline will introduce a mockito compile error: 2907 // InvalidUseOfMatchersException 2908 byte[] expectedSkPr = mSpyCurrentIkeSaRecord.getSkPr(); 2909 verify(spyAuthPayload) 2910 .verifyInboundSignature( 2911 eq(certificate), 2912 any(), 2913 eq(mSpyCurrentIkeSaRecord.nonceInitiator), 2914 eq(respIdPayload.getEncodedPayloadBody()), 2915 eq(mIkeSessionStateMachine.mIkePrf), 2916 eq(expectedSkPr)); 2917 2918 assertNotNull( 2919 ikeAuthReqMessage.getPayloadForType( 2920 IkePayload.PAYLOAD_TYPE_AUTH, IkeAuthDigitalSignPayload.class)); 2921 } 2922 verifySharedKeyAuthentication( IkeAuthPskPayload spyAuthPayload, IkeIdPayload respIdPayload, List<IkePayload> authRelatedPayloads, boolean hasChildPayloads, boolean hasConfigPayloadInResp)2923 private IkeMessage verifySharedKeyAuthentication( 2924 IkeAuthPskPayload spyAuthPayload, 2925 IkeIdPayload respIdPayload, 2926 List<IkePayload> authRelatedPayloads, 2927 boolean hasChildPayloads, 2928 boolean hasConfigPayloadInResp) 2929 throws Exception { 2930 return verifySharedKeyAuthentication( 2931 spyAuthPayload, 2932 respIdPayload, 2933 authRelatedPayloads, 2934 hasChildPayloads, 2935 hasConfigPayloadInResp, 2936 false /* isMobikeEnabled */, 2937 true /* isIpv4 */, 2938 0 /* ike3gppDataListenerInvocations */); 2939 } 2940 verifySharedKeyAuthentication( IkeAuthPskPayload spyAuthPayload, IkeIdPayload respIdPayload, List<IkePayload> authRelatedPayloads, boolean hasChildPayloads, boolean hasConfigPayloadInResp, boolean isMobikeEnabled, boolean isIpv4, int ike3gppDataListenerInvocations)2941 private IkeMessage verifySharedKeyAuthentication( 2942 IkeAuthPskPayload spyAuthPayload, 2943 IkeIdPayload respIdPayload, 2944 List<IkePayload> authRelatedPayloads, 2945 boolean hasChildPayloads, 2946 boolean hasConfigPayloadInResp, 2947 boolean isMobikeEnabled, 2948 boolean isIpv4, 2949 int ike3gppDataListenerInvocations) 2950 throws Exception { 2951 IkeMessage ikeAuthReqMessage = 2952 verifyAuthenticationCommonAndGetIkeMessage( 2953 respIdPayload, 2954 authRelatedPayloads, 2955 hasChildPayloads, 2956 hasConfigPayloadInResp, 2957 isMobikeEnabled, 2958 isIpv4, 2959 ike3gppDataListenerInvocations); 2960 2961 // Calling mSpyCurrentIkeSaRecord.getSkPr() inline will introduce a mockito compile error: 2962 // InvalidUseOfMatchersException 2963 byte[] expectedSkPr = mSpyCurrentIkeSaRecord.getSkPr(); 2964 verify(spyAuthPayload) 2965 .verifyInboundSignature( 2966 eq(mPsk), 2967 any(), 2968 eq(mSpyCurrentIkeSaRecord.nonceInitiator), 2969 eq(respIdPayload.getEncodedPayloadBody()), 2970 eq(mIkeSessionStateMachine.mIkePrf), 2971 eq(expectedSkPr)); 2972 2973 assertNotNull( 2974 ikeAuthReqMessage.getPayloadForType( 2975 IkePayload.PAYLOAD_TYPE_AUTH, IkeAuthPskPayload.class)); 2976 2977 return ikeAuthReqMessage; 2978 } 2979 verifyAuthenticationCommonAndGetIkeMessage( IkeIdPayload respIdPayload, List<IkePayload> authRelatedPayloads, boolean hasChildPayloads, boolean hasConfigPayloadInResp, boolean isMobikeEnabled, boolean isIpv4, int ike3gppDataListenerInvocations)2980 private IkeMessage verifyAuthenticationCommonAndGetIkeMessage( 2981 IkeIdPayload respIdPayload, 2982 List<IkePayload> authRelatedPayloads, 2983 boolean hasChildPayloads, 2984 boolean hasConfigPayloadInResp, 2985 boolean isMobikeEnabled, 2986 boolean isIpv4, 2987 int ike3gppDataListenerInvocations) 2988 throws Exception { 2989 // Send IKE AUTH response to IKE state machine 2990 ReceivedIkePacket authResp = makeIkeAuthRespWithChildPayloads(authRelatedPayloads); 2991 mIkeSessionStateMachine.sendMessage( 2992 IkeSessionStateMachine.CMD_RECEIVE_IKE_PACKET, authResp); 2993 mLooper.dispatchAll(); 2994 2995 // Validate outbound IKE AUTH request 2996 IkeMessage ikeAuthReqMessage; 2997 if (hasChildPayloads) { 2998 ikeAuthReqMessage = verifyAuthReqWithChildPayloadsAndGetMsg(); 2999 } else { 3000 ikeAuthReqMessage = verifyAuthReqAndGetMsg(); 3001 } 3002 3003 // Validate that there is no EAP only notify payload 3004 List<IkeNotifyPayload> notifyPayloads = 3005 ikeAuthReqMessage.getPayloadListForType( 3006 IkePayload.PAYLOAD_TYPE_NOTIFY, IkeNotifyPayload.class); 3007 assertFalse(hasExpectedNotifyPayload(notifyPayloads, NOTIFY_TYPE_EAP_ONLY_AUTHENTICATION)); 3008 3009 // Validate the N1 Mode Capability payload 3010 verifyN1ModeCapabilityPayload(notifyPayloads); 3011 3012 // Validate inbound IKE AUTH response 3013 verifyIncrementLocaReqMsgId(); 3014 verifyDecodeEncryptedMessage(mSpyCurrentIkeSaRecord, authResp); 3015 3016 // Validate that user has been notified. Expect one invocation for 3017 // IkeSessionCallback#onOpened and 'ike3gppDataListenerInvocations' invocations for 3018 // Ike3gppDataListener#onIke3gppDataReceived 3019 verify(mSpyUserCbExecutor, times(1 + ike3gppDataListenerInvocations)) 3020 .execute(any(Runnable.class)); 3021 3022 // Verify IkeSessionConfiguration 3023 ArgumentCaptor<IkeSessionConfiguration> ikeSessionConfigurationArgumentCaptor = 3024 ArgumentCaptor.forClass(IkeSessionConfiguration.class); 3025 verify(mMockIkeSessionCallback).onOpened(ikeSessionConfigurationArgumentCaptor.capture()); 3026 3027 IkeSessionConfiguration sessionConfig = ikeSessionConfigurationArgumentCaptor.getValue(); 3028 assertNotNull(sessionConfig); 3029 if (hasConfigPayloadInResp) { 3030 List<InetAddress> pcscfAddressList = sessionConfig.getPcscfServers(); 3031 assertEquals(3, pcscfAddressList.size()); 3032 assertTrue(pcscfAddressList.contains(InetAddress.getByName(PCSCF_IPV6_ADDRESS1))); 3033 assertTrue(pcscfAddressList.contains(InetAddress.getByName(PCSCF_IPV6_ADDRESS2))); 3034 assertTrue(pcscfAddressList.contains(InetAddress.getByName(PCSCF_IPV6_ADDRESS3))); 3035 } else { 3036 assertTrue(sessionConfig.getPcscfServers().size() == 0); 3037 } 3038 3039 assertEquals( 3040 "" /*expected application version*/, sessionConfig.getRemoteApplicationVersion()); 3041 assertByteArrayListEquals( 3042 Arrays.asList(REMOTE_VENDOR_ID_ONE, REMOTE_VENDOR_ID_TWO), 3043 sessionConfig.getRemoteVendorIds()); 3044 assertTrue( 3045 sessionConfig.isIkeExtensionEnabled( 3046 IkeSessionConfiguration.EXTENSION_TYPE_FRAGMENTATION)); 3047 assertEquals( 3048 isMobikeEnabled, 3049 sessionConfig.isIkeExtensionEnabled(IkeSessionConfiguration.EXTENSION_TYPE_MOBIKE)); 3050 3051 IkeSessionConnectionInfo ikeConnInfo = sessionConfig.getIkeSessionConnectionInfo(); 3052 3053 InetAddress expectedLocalAddress = isIpv4 ? LOCAL_ADDRESS : LOCAL_ADDRESS_V6; 3054 InetAddress expectedRemoteAddress = isIpv4 ? REMOTE_ADDRESS : REMOTE_ADDRESS_V6; 3055 3056 assertEquals(expectedLocalAddress, ikeConnInfo.getLocalAddress()); 3057 assertEquals(expectedRemoteAddress, ikeConnInfo.getRemoteAddress()); 3058 assertEquals(mMockDefaultNetwork, ikeConnInfo.getNetwork()); 3059 3060 // Verify payload list pair for first Child negotiation 3061 ArgumentCaptor<List<IkePayload>> mReqPayloadListCaptor = 3062 ArgumentCaptor.forClass(List.class); 3063 ArgumentCaptor<List<IkePayload>> mRespPayloadListCaptor = 3064 ArgumentCaptor.forClass(List.class); 3065 verify(mMockChildSessionStateMachine) 3066 .handleFirstChildExchange( 3067 mReqPayloadListCaptor.capture(), 3068 mRespPayloadListCaptor.capture(), 3069 eq(expectedLocalAddress), 3070 eq(expectedRemoteAddress), 3071 any(), // udpEncapSocket 3072 eq(mIkeSessionStateMachine.mIkePrf), 3073 eq(mIkeSessionStateMachine.mSaProposal.getDhGroupTransforms()[0].id), 3074 any()); // sk_d 3075 List<IkePayload> childReqList = mReqPayloadListCaptor.getValue(); 3076 List<IkePayload> childRespList = mRespPayloadListCaptor.getValue(); 3077 3078 assertTrue(isIkePayloadExist(childReqList, IkePayload.PAYLOAD_TYPE_SA)); 3079 assertTrue(isIkePayloadExist(childReqList, IkePayload.PAYLOAD_TYPE_TS_INITIATOR)); 3080 assertTrue(isIkePayloadExist(childReqList, IkePayload.PAYLOAD_TYPE_TS_RESPONDER)); 3081 assertTrue(isIkePayloadExist(childReqList, IkePayload.PAYLOAD_TYPE_NONCE)); 3082 IkeSaPayload reqSaPayload = 3083 IkePayload.getPayloadForTypeInProvidedList( 3084 IkePayload.PAYLOAD_TYPE_SA, IkeSaPayload.class, childReqList); 3085 assertFalse(reqSaPayload.isSaResponse); 3086 3087 assertTrue(isIkePayloadExist(childRespList, IkePayload.PAYLOAD_TYPE_SA)); 3088 assertTrue(isIkePayloadExist(childRespList, IkePayload.PAYLOAD_TYPE_TS_INITIATOR)); 3089 assertTrue(isIkePayloadExist(childRespList, IkePayload.PAYLOAD_TYPE_TS_RESPONDER)); 3090 assertTrue(isIkePayloadExist(childRespList, IkePayload.PAYLOAD_TYPE_NONCE)); 3091 if (hasConfigPayloadInResp) { 3092 assertTrue(isIkePayloadExist(childRespList, IkePayload.PAYLOAD_TYPE_CP)); 3093 } else { 3094 assertFalse(isIkePayloadExist(childRespList, IkePayload.PAYLOAD_TYPE_CP)); 3095 } 3096 IkeSaPayload respSaPayload = 3097 IkePayload.getPayloadForTypeInProvidedList( 3098 IkePayload.PAYLOAD_TYPE_SA, IkeSaPayload.class, childRespList); 3099 assertTrue(respSaPayload.isSaResponse); 3100 3101 // Mock finishing first Child SA negotiation. 3102 assertTrue( 3103 mIkeSessionStateMachine.getCurrentState() 3104 instanceof IkeSessionStateMachine.ChildProcedureOngoing); 3105 3106 IChildSessionSmCallback cb = verifyMakeChildAndReturnChildSmCb(mMockChildSessionCallback); 3107 3108 cb.onProcedureFinished(mMockChildSessionStateMachine); 3109 mLooper.dispatchAll(); 3110 assertTrue( 3111 mIkeSessionStateMachine.getCurrentState() instanceof IkeSessionStateMachine.Idle); 3112 3113 return ikeAuthReqMessage; 3114 } 3115 verifyN1ModeCapabilityPayload(List<IkeNotifyPayload> notifyPayloads)3116 private void verifyN1ModeCapabilityPayload(List<IkeNotifyPayload> notifyPayloads) 3117 throws Exception { 3118 IkeNotifyPayload n1ModeCapabilityPayload = null; 3119 for (IkeNotifyPayload notifyPayload : notifyPayloads) { 3120 if (notifyPayload.notifyType == NOTIFY_TYPE_N1_MODE_CAPABILITY) { 3121 n1ModeCapabilityPayload = notifyPayload; 3122 } 3123 } 3124 3125 // Only expect a N1_MODE_CAPABILITY payload if an Ike3gppExtension and PDU Session ID 3126 // are specified. 3127 Ike3gppExtension ike3gppExtension = 3128 mIkeSessionStateMachine.mIkeSessionParams.getIke3gppExtension(); 3129 if (ike3gppExtension == null || !ike3gppExtension.getIke3gppParams().hasPduSessionId()) { 3130 assertNull(n1ModeCapabilityPayload); 3131 } else { 3132 byte[] expectedNotifyData = 3133 TestUtils.hexStringToByteArray(N1_MODE_CAPABILITY_PAYLOAD_DATA); 3134 assertArrayEquals(expectedNotifyData, n1ModeCapabilityPayload.notifyData); 3135 } 3136 } 3137 makeSpyRespPskPayload()3138 private IkeAuthPskPayload makeSpyRespPskPayload() throws Exception { 3139 IkeAuthPskPayload spyAuthPayload = 3140 spy( 3141 (IkeAuthPskPayload) 3142 IkeTestUtils.hexStringToIkePayload( 3143 IkePayload.PAYLOAD_TYPE_AUTH, 3144 true /*isResp*/, 3145 PSK_AUTH_RESP_PAYLOAD_HEX_STRING)); 3146 3147 doNothing() 3148 .when(spyAuthPayload) 3149 .verifyInboundSignature(any(), any(), any(), any(), any(), any()); 3150 return spyAuthPayload; 3151 } 3152 makeSpyDigitalSignAuthPayload()3153 private IkeAuthDigitalSignPayload makeSpyDigitalSignAuthPayload() throws Exception { 3154 IkeAuthDigitalSignPayload spyAuthPayload = 3155 spy( 3156 (IkeAuthDigitalSignPayload) 3157 IkeTestUtils.hexStringToIkePayload( 3158 IkePayload.PAYLOAD_TYPE_AUTH, 3159 true /*isResp*/, 3160 GENERIC_DIGITAL_SIGN_AUTH_RESP_HEX_STRING)); 3161 doNothing() 3162 .when(spyAuthPayload) 3163 .verifyInboundSignature(any(), any(), any(), any(), any(), any()); 3164 return spyAuthPayload; 3165 } 3166 makeRespIdPayload()3167 private IkeIdPayload makeRespIdPayload() { 3168 return makeRespIdPayload(REMOTE_ID_FQDN); 3169 } 3170 makeDeviceIdentityPayloadFromNetwork()3171 private IkeNotifyPayload makeDeviceIdentityPayloadFromNetwork() { 3172 return new IkeNotifyPayload( 3173 NOTIFY_TYPE_DEVICE_IDENTITY, HexDump.hexStringToByteArray("01")); 3174 } 3175 makeRespIdPayload(IkeIdentification ikeId)3176 private IkeIdPayload makeRespIdPayload(IkeIdentification ikeId) { 3177 return new IkeIdPayload(false /* isInitiator */, ikeId); 3178 } 3179 verifyEmptyInformationalSent(int count, boolean expectedResp)3180 private void verifyEmptyInformationalSent(int count, boolean expectedResp) { 3181 verify(mMockIkeMessageHelper, times(count)) 3182 .encryptAndEncode( 3183 anyObject(), 3184 anyObject(), 3185 eq(mSpyCurrentIkeSaRecord), 3186 argThat( 3187 msg -> { 3188 return msg.ikePayloadList.isEmpty() 3189 && msg.ikeHeader.isResponseMsg == expectedResp 3190 && msg.ikeHeader.fromIkeInitiator 3191 && msg.ikeHeader.exchangeType 3192 == IkeHeader.EXCHANGE_TYPE_INFORMATIONAL; 3193 }), 3194 anyBoolean(), 3195 anyInt()); 3196 } 3197 3198 @Test testCreateIkeLocalIkeAuthDefersOtherMessages()3199 public void testCreateIkeLocalIkeAuthDefersOtherMessages() throws Exception { 3200 new IkeFirstAuthTestPretest().mockIkeInitAndTransitionToIkeAuth(); 3201 verifyRetransmissionStarted(); 3202 3203 // Build IKE AUTH response with Auth-PSK, ID-Responder and config payloads. 3204 List<IkePayload> authRelatedPayloads = new ArrayList<>(); 3205 IkeAuthPskPayload spyAuthPayload = makeSpyRespPskPayload(); 3206 authRelatedPayloads.add(spyAuthPayload); 3207 3208 ReceivedIkePacket req = 3209 makeDummyEncryptedReceivedIkePacket( 3210 mSpyCurrentIkeSaRecord, 3211 IkeHeader.EXCHANGE_TYPE_INFORMATIONAL, 3212 false, 3213 Collections.emptyList(), 3214 Collections.emptyList()); 3215 mIkeSessionStateMachine.sendMessage(IkeSessionStateMachine.CMD_RECEIVE_IKE_PACKET, req); 3216 3217 verifyEmptyInformationalSent(0, true /* expcetedResp*/); 3218 3219 // Send IKE AUTH response to IKE state machine to trigger moving to next state 3220 IkeIdPayload respIdPayload = makeRespIdPayload(); 3221 authRelatedPayloads.add(respIdPayload); 3222 authRelatedPayloads.add(makeConfigPayload()); 3223 3224 ReceivedIkePacket authResp = makeIkeAuthRespWithChildPayloads(authRelatedPayloads); 3225 mIkeSessionStateMachine.sendMessage( 3226 IkeSessionStateMachine.CMD_RECEIVE_IKE_PACKET, authResp); 3227 mLooper.dispatchAll(); 3228 3229 verifyEmptyInformationalSent(1, true /* expcetedResp*/); 3230 assertTrue( 3231 mIkeSessionStateMachine.getCurrentState() 3232 instanceof IkeSessionStateMachine.ChildProcedureOngoing); 3233 } 3234 verifyCreateIkeLocalIkeAuthDigitalSignature(Set<Short> peerSignatureHashAlgorithms)3235 private void verifyCreateIkeLocalIkeAuthDigitalSignature(Set<Short> peerSignatureHashAlgorithms) 3236 throws Exception { 3237 // Quit and restart IKE Session with Digital Signature Auth params 3238 mIkeSessionStateMachine.quitNow(); 3239 mIkeSessionStateMachine = makeAndStartIkeSession(buildIkeSessionParamsDigitalSignature()); 3240 3241 new IkeFirstAuthTestPretest(peerSignatureHashAlgorithms) 3242 .mockIkeInitAndTransitionToIkeAuth(); 3243 3244 // Build IKE AUTH response with Digital Signature Auth, ID-Responder and config payloads. 3245 List<IkePayload> authRelatedPayloads = new ArrayList<>(); 3246 IkeAuthDigitalSignPayload spyAuthPayload = makeSpyDigitalSignAuthPayload(); 3247 authRelatedPayloads.add(spyAuthPayload); 3248 authRelatedPayloads.add(new IkeCertX509CertPayload(mServerEndCertificate)); 3249 3250 IkeIdPayload respIdPayload = makeRespIdPayload(); 3251 authRelatedPayloads.add(respIdPayload); 3252 authRelatedPayloads.add(makeConfigPayload()); 3253 3254 verifyDigitalSignatureAuthentication( 3255 spyAuthPayload, 3256 mServerEndCertificate, 3257 respIdPayload, 3258 authRelatedPayloads, 3259 true /*hasChildPayloads*/, 3260 true /*hasConfigPayloadInResp*/); 3261 verifyRetransmissionStopped(); 3262 } 3263 3264 @Test testCreateIkeLocalIkeAuthRsaDigitalSignature()3265 public void testCreateIkeLocalIkeAuthRsaDigitalSignature() throws Exception { 3266 verifyCreateIkeLocalIkeAuthDigitalSignature(new HashSet<>()); 3267 } 3268 3269 @Test testCreateIkeLocalIkeAuthGenericDigitalSignature()3270 public void testCreateIkeLocalIkeAuthGenericDigitalSignature() throws Exception { 3271 Set<Short> hashAlgos = new HashSet<Short>(); 3272 for (short algo : IkeAuthDigitalSignPayload.ALL_SIGNATURE_ALGO_TYPES) { 3273 hashAlgos.add(algo); 3274 } 3275 verifyCreateIkeLocalIkeAuthDigitalSignature(hashAlgos); 3276 } 3277 3278 @Test testCreateIkeLocalIkeAuthPsk()3279 public void testCreateIkeLocalIkeAuthPsk() throws Exception { 3280 new IkeFirstAuthTestPretest().mockIkeInitAndTransitionToIkeAuth(); 3281 verifyRetransmissionStarted(); 3282 3283 // Build IKE AUTH response with Auth-PSK, ID-Responder and config payloads. 3284 List<IkePayload> authRelatedPayloads = new ArrayList<>(); 3285 IkeAuthPskPayload spyAuthPayload = makeSpyRespPskPayload(); 3286 authRelatedPayloads.add(spyAuthPayload); 3287 3288 IkeIdPayload respIdPayload = makeRespIdPayload(); 3289 authRelatedPayloads.add(respIdPayload); 3290 authRelatedPayloads.add(makeConfigPayload()); 3291 3292 verifySharedKeyAuthentication( 3293 spyAuthPayload, 3294 respIdPayload, 3295 authRelatedPayloads, 3296 true /*hasChildPayloads*/, 3297 true /*hasConfigPayloadInResp*/); 3298 verifyRetransmissionStopped(); 3299 } 3300 3301 @Test testCreateIkeLocalIkeAuthDigitalSignatureIdMismatch()3302 public void testCreateIkeLocalIkeAuthDigitalSignatureIdMismatch() throws Exception { 3303 // Quit and restart IKE Session with Digital Signature Auth params 3304 mIkeSessionStateMachine.quitNow(); 3305 mIkeSessionStateMachine = makeAndStartIkeSession(buildIkeSessionParamsDigitalSignature()); 3306 new IkeFirstAuthTestPretest().mockIkeInitAndTransitionToIkeAuth(); 3307 resetMockIkeMessageHelper(); 3308 3309 // Build IKE AUTH response with Digital Signature Auth, ID-Responder and config payloads. 3310 List<IkePayload> authRelatedPayloads = new ArrayList<>(); 3311 IkeAuthDigitalSignPayload spyAuthPayload = makeSpyDigitalSignAuthPayload(); 3312 authRelatedPayloads.add(spyAuthPayload); 3313 authRelatedPayloads.add(new IkeCertX509CertPayload(mServerEndCertificate)); 3314 3315 authRelatedPayloads.add(makeRespIdPayload(REMOTE_ID_IPV4)); 3316 3317 sendAuthFailRespAndVerifyCloseIke(makeIkeAuthRespWithChildPayloads(authRelatedPayloads)); 3318 } 3319 3320 @Test testCreateIkeLocalIkeAuthPskVerifyFail()3321 public void testCreateIkeLocalIkeAuthPskVerifyFail() throws Exception { 3322 new IkeFirstAuthTestPretest().mockIkeInitAndTransitionToIkeAuth(); 3323 verifyRetransmissionStarted(); 3324 resetMockIkeMessageHelper(); 3325 3326 // Build IKE AUTH response with invalid Auth-PSK Payload and ID-Responder Payload. 3327 List<IkePayload> authRelatedPayloads = new ArrayList<>(); 3328 IkeAuthPskPayload spyAuthPayload = makeSpyRespPskPayload(); 3329 doThrow(new AuthenticationFailedException("DummyAuthFailException")) 3330 .when(spyAuthPayload) 3331 .verifyInboundSignature(any(), any(), any(), any(), any(), any()); 3332 authRelatedPayloads.add(spyAuthPayload); 3333 3334 IkeIdPayload respIdPayload = makeRespIdPayload(); 3335 authRelatedPayloads.add(respIdPayload); 3336 3337 sendAuthFailRespAndVerifyCloseIke(makeIkeAuthRespWithChildPayloads(authRelatedPayloads)); 3338 } 3339 sendAuthFailRespAndVerifyCloseIke(ReceivedIkePacket authFailResp)3340 private void sendAuthFailRespAndVerifyCloseIke(ReceivedIkePacket authFailResp) 3341 throws Exception { 3342 // Send response to IKE state machine 3343 mIkeSessionStateMachine.sendMessage( 3344 IkeSessionStateMachine.CMD_RECEIVE_IKE_PACKET, authFailResp); 3345 mLooper.dispatchAll(); 3346 3347 // Verify Delete request was sent 3348 List<IkePayload> payloads = verifyOutInfoMsgHeaderAndGetPayloads(false /*isResp*/); 3349 assertEquals(1, payloads.size()); 3350 assertEquals(IkePayload.PAYLOAD_TYPE_DELETE, payloads.get(0).payloadType); 3351 3352 // Verify IKE Session was closed properly 3353 assertNull(mIkeSessionStateMachine.getCurrentState()); 3354 verify(mMockIkeSessionCallback) 3355 .onClosedWithException(any(AuthenticationFailedException.class)); 3356 } 3357 3358 @Test testAuthHandlesIkeErrorNotify()3359 public void testAuthHandlesIkeErrorNotify() throws Exception { 3360 new IkeFirstAuthTestPretest().mockIkeInitAndTransitionToIkeAuth(); 3361 verifyRetransmissionStarted(); 3362 resetMockIkeMessageHelper(); 3363 3364 // Mock rejecting IKE AUTH with Authentication Failure notification 3365 ReceivedIkePacket mockAuthFailPacket = 3366 makeIkeAuthRespWithoutChildPayloads( 3367 Arrays.asList(new IkeNotifyPayload(ERROR_TYPE_AUTHENTICATION_FAILED))); 3368 mIkeSessionStateMachine.sendMessage(CMD_RECEIVE_IKE_PACKET, mockAuthFailPacket); 3369 mLooper.dispatchAll(); 3370 3371 // Verify Delete request was never sent 3372 verifyEncryptAndEncodeNeverCalled(); 3373 3374 // Verify IKE Session is closed properly 3375 assertNull(mIkeSessionStateMachine.getCurrentState()); 3376 verify(mMockIkeSessionCallback) 3377 .onClosedWithException(any(AuthenticationFailedException.class)); 3378 } 3379 3380 @Test testAuthHandlesCreateChildErrorNotify()3381 public void testAuthHandlesCreateChildErrorNotify() throws Exception { 3382 new IkeFirstAuthTestPretest().mockIkeInitAndTransitionToIkeAuth(); 3383 verifyRetransmissionStarted(); 3384 resetMockIkeMessageHelper(); 3385 3386 // Mock rejecting IKE AUTH with a Create Child error notification 3387 ReceivedIkePacket mockAuthFailPacket = 3388 makeIkeAuthRespWithoutChildPayloads( 3389 Arrays.asList(new IkeNotifyPayload(ERROR_TYPE_INTERNAL_ADDRESS_FAILURE))); 3390 mIkeSessionStateMachine.sendMessage(CMD_RECEIVE_IKE_PACKET, mockAuthFailPacket); 3391 mLooper.dispatchAll(); 3392 3393 // Verify Delete request was sent 3394 List<IkePayload> payloads = verifyOutInfoMsgHeaderAndGetPayloads(false /*isResp*/); 3395 assertEquals(1, payloads.size()); 3396 assertEquals(IkePayload.PAYLOAD_TYPE_DELETE, payloads.get(0).payloadType); 3397 3398 // Verify IKE Session is closed properly 3399 assertNull(mIkeSessionStateMachine.getCurrentState()); 3400 3401 ArgumentCaptor<IkeProtocolException> captor = 3402 ArgumentCaptor.forClass(IkeProtocolException.class); 3403 verify(mMockIkeSessionCallback).onClosedWithException(captor.capture()); 3404 IkeProtocolException exception = captor.getValue(); 3405 assertEquals(ERROR_TYPE_INTERNAL_ADDRESS_FAILURE, exception.getErrorType()); 3406 } 3407 3408 @Test testAuthPskHandleRespWithParsingError()3409 public void testAuthPskHandleRespWithParsingError() throws Exception { 3410 new IkeFirstAuthTestPretest().mockIkeInitAndTransitionToIkeAuth(); 3411 verifyRetransmissionStarted(); 3412 resetMockIkeMessageHelper(); 3413 3414 // Mock receiving packet with syntax error 3415 ReceivedIkePacket mockInvalidPacket = 3416 makeDummyReceivedIkePacketWithInvalidSyntax( 3417 mSpyCurrentIkeSaRecord, true /*isResp*/, IkeHeader.EXCHANGE_TYPE_IKE_AUTH); 3418 mIkeSessionStateMachine.sendMessage(CMD_RECEIVE_IKE_PACKET, mockInvalidPacket); 3419 mLooper.dispatchAll(); 3420 3421 // Verify Delete request was sent 3422 List<IkePayload> payloads = verifyOutInfoMsgHeaderAndGetPayloads(false /*isResp*/); 3423 assertEquals(1, payloads.size()); 3424 assertEquals(IkePayload.PAYLOAD_TYPE_DELETE, payloads.get(0).payloadType); 3425 3426 // Verify IKE Session is closed properly 3427 assertNull(mIkeSessionStateMachine.getCurrentState()); 3428 verify(mMockIkeSessionCallback).onClosedWithException(any(InvalidSyntaxException.class)); 3429 } 3430 3431 @Test testAuthWithOptionAcceptAnyRemoteId()3432 public void testAuthWithOptionAcceptAnyRemoteId() throws Exception { 3433 mIkeSessionStateMachine.quitNow(); 3434 3435 IkeSessionParams ikeSessionParams = 3436 buildIkeSessionParamsWithIkeOptions( 3437 IkeSessionParams.IKE_OPTION_ACCEPT_ANY_REMOTE_ID); 3438 mIkeSessionStateMachine = makeAndStartIkeSession(ikeSessionParams); 3439 3440 // Mock IKE INIT 3441 new IkeFirstAuthTestPretest().mockIkeInitAndTransitionToIkeAuth(); 3442 verifyRetransmissionStarted(); 3443 3444 // Build IKE AUTH response with Auth-PSK Payload and ID-Responder Payload that is different 3445 // from configured ID-Responder. 3446 List<IkePayload> authRelatedPayloads = new ArrayList<>(); 3447 IkeAuthPskPayload spyAuthPayload = makeSpyRespPskPayload(); 3448 authRelatedPayloads.add(spyAuthPayload); 3449 3450 IkeIdPayload respIdPayload = makeRespIdPayload(REMOTE_ID_IPV4); 3451 authRelatedPayloads.add(respIdPayload); 3452 3453 // Send response to IKE state machine and verify authentication is done. 3454 verifySharedKeyAuthentication( 3455 spyAuthPayload, 3456 respIdPayload, 3457 authRelatedPayloads, 3458 true /*hasChildPayloads*/, 3459 false /*hasConfigPayloadInResp*/); 3460 verifyRetransmissionStopped(); 3461 } 3462 3463 @Test testAuthRejectOtherResponderId()3464 public void testAuthRejectOtherResponderId() throws Exception { 3465 new IkeFirstAuthTestPretest().mockIkeInitAndTransitionToIkeAuth(); 3466 verifyRetransmissionStarted(); 3467 3468 // Build IKE AUTH response with Auth-PSK Payload and ID-Responder Payload that is different 3469 // from configured ID-Responder. 3470 List<IkePayload> authRelatedPayloads = new ArrayList<>(); 3471 IkeAuthPskPayload spyAuthPayload = makeSpyRespPskPayload(); 3472 authRelatedPayloads.add(spyAuthPayload); 3473 3474 IkeIdPayload respIdPayload = makeRespIdPayload(REMOTE_ID_IPV4); 3475 authRelatedPayloads.add(respIdPayload); 3476 3477 // Send response to IKE state machine 3478 mIkeSessionStateMachine.sendMessage( 3479 IkeSessionStateMachine.CMD_RECEIVE_IKE_PACKET, 3480 makeIkeAuthRespWithChildPayloads(authRelatedPayloads)); 3481 mLooper.dispatchAll(); 3482 3483 // Verify IKE Session is closed properly 3484 assertNull(mIkeSessionStateMachine.getCurrentState()); 3485 verify(mMockIkeSessionCallback) 3486 .onClosedWithException(any(AuthenticationFailedException.class)); 3487 } 3488 3489 @Test testCreateIkeLocalIkeAuthPreEap()3490 public void testCreateIkeLocalIkeAuthPreEap() throws Exception { 3491 mIkeSessionStateMachine.quitNow(); 3492 mIkeSessionStateMachine = makeAndStartIkeSession(buildIkeSessionParamsEap()); 3493 3494 // Mock IKE INIT 3495 new IkeFirstAuthTestPretest().mockIkeInitAndTransitionToIkeAuth(); 3496 verifyRetransmissionStarted(); 3497 3498 // Build IKE AUTH response with EAP. Auth, ID-Resp and Cert payloads. 3499 List<IkePayload> authRelatedPayloads = new ArrayList<>(); 3500 3501 authRelatedPayloads.add(new IkeEapPayload(EAP_DUMMY_MSG)); 3502 authRelatedPayloads.add(makeSpyDigitalSignAuthPayload()); 3503 authRelatedPayloads.add(makeRespIdPayload()); 3504 3505 IkeCertX509CertPayload certPayload = new IkeCertX509CertPayload(mServerEndCertificate); 3506 authRelatedPayloads.add(certPayload); 3507 3508 // Send IKE AUTH response to IKE state machine 3509 mIkeSessionStateMachine.sendMessage( 3510 IkeSessionStateMachine.CMD_RECEIVE_IKE_PACKET, 3511 makeIkeAuthRespWithoutChildPayloads(authRelatedPayloads)); 3512 mLooper.dispatchAll(); 3513 3514 // Validate outbound IKE AUTH request 3515 IkeMessage ikeAuthReqMessage = verifyAuthReqWithChildPayloadsAndGetMsg(); 3516 assertNull( 3517 ikeAuthReqMessage.getPayloadForType( 3518 IkePayload.PAYLOAD_TYPE_AUTH, IkeAuthPayload.class)); 3519 3520 assertTrue( 3521 mIkeSessionStateMachine.getCurrentState() 3522 instanceof IkeSessionStateMachine.CreateIkeLocalIkeAuthInEap); 3523 verifyRetransmissionStopped(); 3524 3525 IkeAuthData setupData = 3526 ((CreateIkeLocalIkeAuthInEap) mIkeSessionStateMachine.mCreateIkeLocalIkeAuthInEap) 3527 .mSetupData; 3528 assertNotNull(setupData.initIdPayload); 3529 assertNotNull(setupData.respIdPayload); 3530 } 3531 verifyEapAuthenticatorCreatedAndGetCallback( EapSessionConfig eapSessionConfig)3532 private IEapCallback verifyEapAuthenticatorCreatedAndGetCallback( 3533 EapSessionConfig eapSessionConfig) { 3534 ArgumentCaptor<IkeContext> ikeContextCaptor = ArgumentCaptor.forClass(IkeContext.class); 3535 ArgumentCaptor<IEapCallback> eapCbCaptor = ArgumentCaptor.forClass(IEapCallback.class); 3536 3537 verify(mSpyDeps) 3538 .newEapAuthenticator( 3539 ikeContextCaptor.capture(), eapCbCaptor.capture(), eq(eapSessionConfig)); 3540 3541 IkeContext ikeContext = ikeContextCaptor.getValue(); 3542 assertEquals(mIkeSessionStateMachine.getHandler().getLooper(), ikeContext.getLooper()); 3543 assertEquals(mSpyContext, ikeContext.getContext()); 3544 3545 return eapCbCaptor.getValue(); 3546 } 3547 3548 @Test testCreateIkeLocalIkeAuthInEapStartsAuthenticatorAndProxiesMessage()3549 public void testCreateIkeLocalIkeAuthInEapStartsAuthenticatorAndProxiesMessage() 3550 throws Exception { 3551 mIkeSessionStateMachine.quitNow(); 3552 mIkeSessionStateMachine = makeAndStartIkeSession(buildIkeSessionParamsEap()); 3553 3554 // Setup state and go to IN_EAP state 3555 new IkeAuthInEapTestPretest().mockIkeInitAndTransitionToIkeAuth(); 3556 mLooper.dispatchAll(); 3557 3558 mIkeSessionStateMachine.sendMessage( 3559 IkeSessionStateMachine.CMD_EAP_START_EAP_AUTH, new IkeEapPayload(EAP_DUMMY_MSG)); 3560 mLooper.dispatchAll(); 3561 3562 verifyEapAuthenticatorCreatedAndGetCallback(mEapSessionConfig); 3563 3564 verify(mMockEapAuthenticator).processEapMessage(eq(EAP_DUMMY_MSG)); 3565 } 3566 3567 @Test testInformationalResponseWithDeviceIdentity()3568 public void testInformationalResponseWithDeviceIdentity() throws Exception { 3569 mIkeSessionStateMachine.quitNow(); 3570 mIkeSessionStateMachine = 3571 makeAndStartIkeSession(buildIkeSessionParamsEapAkaWithDeviceIdentity()); 3572 setIkeInitResults(); 3573 3574 mIkeSessionStateMachine.sendMessage( 3575 IkeSessionStateMachine.CMD_FORCE_TRANSITION, mIkeSessionStateMachine.mIdle); 3576 mLooper.dispatchAll(); 3577 3578 assertTrue( 3579 mIkeSessionStateMachine.getCurrentState() instanceof IkeSessionStateMachine.Idle); 3580 verifyRcvDeviceIdentityCheckReqAndReply(); 3581 } 3582 3583 @Test testCreateIkeLocalIkeAuthInEapOutboundResponseIncludesDeviceIdentity()3584 public void testCreateIkeLocalIkeAuthInEapOutboundResponseIncludesDeviceIdentity() 3585 throws Exception { 3586 mIkeSessionStateMachine.quitNow(); 3587 mIkeSessionStateMachine = 3588 makeAndStartIkeSession(buildIkeSessionParamsEapAkaWithDeviceIdentity()); 3589 3590 new IkeFirstAuthTestPretest().mockIkeInitAndTransitionToIkeAuth(); 3591 verifyRetransmissionStarted(); 3592 3593 // Build IKE AUTH response with EAP. Auth, ID-Resp and device identity 3594 List<IkePayload> authRelatedPayloads = new ArrayList<>(); 3595 authRelatedPayloads.add(new IkeEapPayload(EAP_DUMMY_MSG)); 3596 authRelatedPayloads.add(makeRespIdPayload()); 3597 authRelatedPayloads.add(makeDeviceIdentityPayloadFromNetwork()); 3598 3599 // Send IKE AUTH response to IKE state machine 3600 mIkeSessionStateMachine.sendMessage( 3601 IkeSessionStateMachine.CMD_RECEIVE_IKE_PACKET, 3602 makeIkeAuthRespWithoutChildPayloads(authRelatedPayloads)); 3603 mLooper.dispatchAll(); 3604 3605 IEapCallback callback = 3606 verifyEapAuthenticatorCreatedAndGetCallback(mEapSessionConfigEapAka); 3607 callback.onResponse( 3608 EAP_DUMMY_MSG, EAP_RESPONSE_FLAG_MASK_WITH_EAP_AKA_SERVER_AUTHENTICATED); 3609 mLooper.dispatchAll(); 3610 verifyRetransmissionStarted(); 3611 3612 verify(mMockIkeMessageHelper, times(2)) 3613 .encryptAndEncode( 3614 anyObject(), 3615 anyObject(), 3616 eq(mSpyCurrentIkeSaRecord), 3617 mIkeMessageCaptor.capture(), 3618 anyBoolean(), 3619 anyInt()); 3620 IkeMessage ikeAuthReqMessage = mIkeMessageCaptor.getValue(); 3621 3622 // Validate the DEVICE_IDENTITY payload and the content sent to the network 3623 List<IkeNotifyPayload> notifyPayloads = 3624 ikeAuthReqMessage.getPayloadListForType( 3625 IkePayload.PAYLOAD_TYPE_NOTIFY, IkeNotifyPayload.class); 3626 IkeNotifyPayload deviceIdentityPayload = null; 3627 for (IkeNotifyPayload notifyPayload : notifyPayloads) { 3628 if (notifyPayload.notifyType == NOTIFY_TYPE_DEVICE_IDENTITY) { 3629 deviceIdentityPayload = notifyPayload; 3630 } 3631 } 3632 assertArrayEquals(DEVICE_IDENTITY_PAYLOAD_IMEI, deviceIdentityPayload.notifyData); 3633 3634 assertTrue( 3635 mIkeSessionStateMachine.getCurrentState() 3636 instanceof IkeSessionStateMachine.CreateIkeLocalIkeAuthInEap); 3637 } 3638 3639 @Test testCreateIkeLocalIkeAuthInEapHandlesOutboundResponse()3640 public void testCreateIkeLocalIkeAuthInEapHandlesOutboundResponse() throws Exception { 3641 mIkeSessionStateMachine.quitNow(); 3642 mIkeSessionStateMachine = makeAndStartIkeSession(buildIkeSessionParamsEap()); 3643 3644 // Setup state and go to IN_EAP state 3645 new IkeAuthInEapTestPretest().mockIkeInitAndTransitionToIkeAuth(); 3646 mLooper.dispatchAll(); 3647 3648 IEapCallback callback = verifyEapAuthenticatorCreatedAndGetCallback(mEapSessionConfig); 3649 callback.onResponse(EAP_DUMMY_MSG, EAP_RESPONSE_FLAGS_NOT_SET); 3650 mLooper.dispatchAll(); 3651 verifyRetransmissionStarted(); 3652 3653 // Verify EAP response 3654 IkeMessage resp = verifyEncryptAndEncodeAndGetMessage(mSpyCurrentIkeSaRecord); 3655 IkeHeader ikeHeader = resp.ikeHeader; 3656 assertEquals(IkePayload.PAYLOAD_TYPE_SK, ikeHeader.nextPayloadType); 3657 assertEquals(IkeHeader.EXCHANGE_TYPE_IKE_AUTH, ikeHeader.exchangeType); 3658 assertFalse(ikeHeader.isResponseMsg); 3659 assertEquals(mSpyCurrentIkeSaRecord.isLocalInit, ikeHeader.fromIkeInitiator); 3660 3661 assertEquals(1, resp.ikePayloadList.size()); 3662 assertArrayEquals(EAP_DUMMY_MSG, ((IkeEapPayload) resp.ikePayloadList.get(0)).eapMessage); 3663 } 3664 3665 @Test testCreateIkeLocalIkeAuthInEapHandlesMissingEapPacket()3666 public void testCreateIkeLocalIkeAuthInEapHandlesMissingEapPacket() throws Exception { 3667 mIkeSessionStateMachine.quitNow(); 3668 mIkeSessionStateMachine = makeAndStartIkeSession(buildIkeSessionParamsEap()); 3669 3670 // Setup state and go to IN_EAP state 3671 new IkeAuthInEapTestPretest().mockIkeInitAndTransitionToIkeAuth(); 3672 mLooper.dispatchAll(); 3673 3674 // Mock sending IKE_AUTH{EAP} request 3675 IEapCallback callback = verifyEapAuthenticatorCreatedAndGetCallback(mEapSessionConfig); 3676 callback.onResponse(EAP_DUMMY_MSG, EAP_RESPONSE_FLAGS_NOT_SET); 3677 mLooper.dispatchAll(); 3678 verifyRetransmissionStarted(); 3679 3680 // Send IKE AUTH response with no EAP Payload to IKE state machine 3681 mIkeSessionStateMachine.sendMessage( 3682 IkeSessionStateMachine.CMD_RECEIVE_IKE_PACKET, 3683 makeIkeAuthRespWithoutChildPayloads(new ArrayList<>())); 3684 mLooper.dispatchAll(); 3685 3686 // Verify state machine quit properly 3687 verify(mMockIkeSessionCallback) 3688 .onClosedWithException(any(AuthenticationFailedException.class)); 3689 assertNull(mIkeSessionStateMachine.getCurrentState()); 3690 } 3691 3692 @Test testCreateIkeLocalIkeAuthInEapHandlesSuccess()3693 public void testCreateIkeLocalIkeAuthInEapHandlesSuccess() throws Exception { 3694 mIkeSessionStateMachine.quitNow(); 3695 mIkeSessionStateMachine = makeAndStartIkeSession(buildIkeSessionParamsEap()); 3696 3697 // Setup state and go to IN_EAP state 3698 new IkeAuthInEapTestPretest().mockIkeInitAndTransitionToIkeAuth(); 3699 mLooper.dispatchAll(); 3700 3701 IEapCallback callback = verifyEapAuthenticatorCreatedAndGetCallback(mEapSessionConfig); 3702 3703 EapAkaInfo eapInfo = 3704 new EapAkaInfo.Builder().setReauthId(REAUTH_ID_BYTES).build(); 3705 3706 callback.onSuccess(mPsk, new byte[0], eapInfo); // use mPsk as MSK, eMSK does not matter 3707 mLooper.dispatchAll(); 3708 3709 assertTrue( 3710 mIkeSessionStateMachine.getCurrentState() 3711 instanceof IkeSessionStateMachine.CreateIkeLocalIkeAuthPostEap); 3712 assertEquals(mIkeSessionStateMachine.mCreateIkeLocalIkeAuthPostEap.mEapInfo, eapInfo); 3713 } 3714 3715 @Test testCreateIkeLocalIkeAuthInEapHandlesError()3716 public void testCreateIkeLocalIkeAuthInEapHandlesError() throws Exception { 3717 mIkeSessionStateMachine.quitNow(); 3718 mIkeSessionStateMachine = makeAndStartIkeSession(buildIkeSessionParamsEap()); 3719 3720 // Setup state and go to IN_EAP state 3721 new IkeAuthInEapTestPretest().mockIkeInitAndTransitionToIkeAuth(); 3722 mLooper.dispatchAll(); 3723 3724 IEapCallback callback = verifyEapAuthenticatorCreatedAndGetCallback(mEapSessionConfig); 3725 3726 Throwable error = new IllegalArgumentException(); 3727 callback.onError(error); 3728 mLooper.dispatchAll(); 3729 3730 // Fires user error callbacks 3731 verify(mMockIkeSessionCallback) 3732 .onClosedWithException(argThat(err -> err.getCause() == error)); 3733 3734 // Verify state machine quit properly 3735 verify(mSpyCurrentIkeSaRecord).close(); 3736 assertNull(mIkeSessionStateMachine.getCurrentState()); 3737 } 3738 3739 @Test testCreateIkeLocalIkeAuthInEapHandlesFailure()3740 public void testCreateIkeLocalIkeAuthInEapHandlesFailure() throws Exception { 3741 mIkeSessionStateMachine.quitNow(); 3742 mIkeSessionStateMachine = makeAndStartIkeSession(buildIkeSessionParamsEap()); 3743 3744 // Setup state and go to IN_EAP state 3745 new IkeAuthInEapTestPretest().mockIkeInitAndTransitionToIkeAuth(); 3746 mLooper.dispatchAll(); 3747 3748 IEapCallback callback = verifyEapAuthenticatorCreatedAndGetCallback(mEapSessionConfig); 3749 callback.onFail(); 3750 mLooper.dispatchAll(); 3751 3752 // Fires user error callbacks 3753 verify(mMockIkeSessionCallback) 3754 .onClosedWithException(any(AuthenticationFailedException.class)); 3755 3756 // Verify state machine quit properly 3757 verify(mSpyCurrentIkeSaRecord).close(); 3758 assertNull(mIkeSessionStateMachine.getCurrentState()); 3759 } 3760 3761 @Test testCreateIkeLocalIkeAuthPostEap()3762 public void testCreateIkeLocalIkeAuthPostEap() throws Exception { 3763 verifyCreateIkeLocalIkeAuthPostEap( 3764 buildIkeSessionParamsEap(), 3765 new ArrayList<>() /* authRelatedPayloads */, 3766 false /* isMobikeEnabled */); 3767 } 3768 verifyCreateIkeLocalIkeAuthPostEap( IkeSessionParams params, List<IkePayload> authRelatedPayloads, boolean isMobikeEnabled)3769 private void verifyCreateIkeLocalIkeAuthPostEap( 3770 IkeSessionParams params, List<IkePayload> authRelatedPayloads, boolean isMobikeEnabled) 3771 throws Exception { 3772 mIkeSessionStateMachine.quitNow(); 3773 mIkeSessionStateMachine = makeAndStartIkeSession(params); 3774 3775 // Setup state and go to IN_EAP state 3776 IkeIdPayload initIdPayload = mock(IkeIdPayload.class); 3777 doReturn(new byte[0]).when(initIdPayload).getEncodedPayloadBody(); 3778 IkeIdPayload respIdPayload = makeRespIdPayload(); 3779 new IkeAuthPostEapTestPretest(initIdPayload, respIdPayload) 3780 .mockIkeInitAndTransitionToIkeAuth(); 3781 3782 EapAkaInfo eapInfo = 3783 new EapAkaInfo.Builder().setReauthId(REAUTH_ID_BYTES).build(); 3784 mIkeSessionStateMachine.mCreateIkeLocalIkeAuthPostEap.setEapInfo(eapInfo); 3785 mIkeSessionStateMachine.sendMessage(IkeSessionStateMachine.CMD_EAP_FINISH_EAP_AUTH, mPsk); 3786 mLooper.dispatchAll(); 3787 verifyRetransmissionStarted(); 3788 3789 // Build IKE AUTH response with Auth-PSK Payload and ID-Responder Payload. 3790 IkeAuthPskPayload spyAuthPayload = makeSpyRespPskPayload(); 3791 authRelatedPayloads.add(spyAuthPayload); 3792 3793 verifySharedKeyAuthentication( 3794 spyAuthPayload, 3795 respIdPayload, 3796 authRelatedPayloads, 3797 false /*hasChildPayloads*/, 3798 false /*hasConfigPayloadInResp*/, 3799 isMobikeEnabled, 3800 true /* isIpv4 */, 3801 0 /* ike3gppDataListenerInvocations */); 3802 verifyRetransmissionStopped(); 3803 3804 ArgumentCaptor<IkeSessionConfiguration> ikeSessionConfigurationArgumentCaptor = 3805 ArgumentCaptor.forClass(IkeSessionConfiguration.class); 3806 verify(mMockIkeSessionCallback).onOpened(ikeSessionConfigurationArgumentCaptor.capture()); 3807 3808 IkeSessionConfiguration sessionConfig = ikeSessionConfigurationArgumentCaptor.getValue(); 3809 assertNotNull(sessionConfig); 3810 assertArrayEquals(REAUTH_ID_BYTES, ((EapAkaInfo) sessionConfig.getEapInfo()).getReauthId()); 3811 } 3812 3813 @Test testCreateIkeLocalIkeAuthHandlesFirstFrag()3814 public void testCreateIkeLocalIkeAuthHandlesFirstFrag() throws Exception { 3815 new IkeFirstAuthTestPretest().mockIkeInitAndTransitionToIkeAuth(); 3816 verifyRetransmissionStarted(); 3817 3818 // Received IKE fragment 3819 byte[] unencryptedData = "testCreateIkeLocalIkeAuthHandlesFrag".getBytes(); 3820 int fragNum = 1; 3821 int totalFragments = 2; 3822 IkeSkfPayload skfPayload = 3823 IkeTestUtils.makeDummySkfPayload(unencryptedData, fragNum, totalFragments); 3824 3825 ReceivedIkePacket packet = 3826 makeDummyReceivedIkeFragmentPacket( 3827 mSpyCurrentIkeSaRecord, 3828 true /*isResp*/, 3829 IkeHeader.EXCHANGE_TYPE_IKE_AUTH, 3830 skfPayload, 3831 PAYLOAD_TYPE_AUTH, 3832 null /* collectedFrags*/); 3833 mIkeSessionStateMachine.sendMessage(IkeSessionStateMachine.CMD_RECEIVE_IKE_PACKET, packet); 3834 mLooper.dispatchAll(); 3835 3836 // Verify state doesn't change 3837 assertTrue( 3838 mIkeSessionStateMachine.getCurrentState() 3839 instanceof IkeSessionStateMachine.CreateIkeLocalIkeAuth); 3840 3841 // Verify the IkeSaRecord has stored the fragment. 3842 DecodeResultPartial resultPartial = 3843 mSpyCurrentIkeSaRecord.getCollectedFragments(true /*isResp*/); 3844 assertEquals(PAYLOAD_TYPE_AUTH, resultPartial.firstPayloadType); 3845 assertEquals(totalFragments, resultPartial.collectedFragsList.length); 3846 assertArrayEquals(unencryptedData, resultPartial.collectedFragsList[fragNum - 1]); 3847 assertFalse(resultPartial.isAllFragmentsReceived()); 3848 3849 assertNull(mSpyCurrentIkeSaRecord.getCollectedFragments(false /*isResp*/)); 3850 } 3851 3852 @Test testCreateIkeLocalIkeAuthHandlesLastFragOk()3853 public void testCreateIkeLocalIkeAuthHandlesLastFragOk() throws Exception { 3854 new IkeFirstAuthTestPretest().mockIkeInitAndTransitionToIkeAuth(); 3855 verifyRetransmissionStarted(); 3856 3857 // Set previously collected IKE fragments 3858 DecodeResultPartial mockCollectedFrags = mock(DecodeResultPartial.class); 3859 mSpyCurrentIkeSaRecord.updateCollectedFragments(mockCollectedFrags, true /*isResp*/); 3860 3861 // Build reassembled IKE AUTH response with Auth-PSK Payload and ID-Responder Payload. 3862 List<IkePayload> authRelatedPayloads = new ArrayList<>(); 3863 IkeAuthPskPayload spyAuthPayload = makeSpyRespPskPayload(); 3864 authRelatedPayloads.add(spyAuthPayload); 3865 3866 IkeIdPayload respIdPayload = makeRespIdPayload(); 3867 authRelatedPayloads.add(respIdPayload); 3868 3869 List<IkePayload> authPayloadList = 3870 getIkeAuthPayloadListWithChildPayloads(authRelatedPayloads); 3871 3872 // Receive last auth response and do IKE_AUTH 3873 ReceivedIkePacket packet = 3874 makeDummyReceivedLastIkeFragmentPacketOk( 3875 mSpyCurrentIkeSaRecord, 3876 true /*isResp*/, 3877 IkeHeader.EXCHANGE_TYPE_IKE_AUTH, 3878 mockCollectedFrags, 3879 authPayloadList, 3880 "FirstFrag".getBytes()); 3881 mIkeSessionStateMachine.sendMessage(IkeSessionStateMachine.CMD_RECEIVE_IKE_PACKET, packet); 3882 mLooper.dispatchAll(); 3883 3884 // Verify IKE AUTH is done 3885 assertTrue( 3886 mIkeSessionStateMachine.getCurrentState() 3887 instanceof IkeSessionStateMachine.ChildProcedureOngoing); 3888 3889 // Verify collected response fragments are cleared. 3890 assertNull(mSpyCurrentIkeSaRecord.getCollectedFragments(true /*isResp*/)); 3891 verify(mSpyCurrentIkeSaRecord).resetCollectedFragments(true /*isResp*/); 3892 } 3893 3894 @Test testCreateIkeLocalIkeAuthHandlesLastFragError()3895 public void testCreateIkeLocalIkeAuthHandlesLastFragError() throws Exception { 3896 new IkeFirstAuthTestPretest().mockIkeInitAndTransitionToIkeAuth(); 3897 verifyRetransmissionStarted(); 3898 resetMockIkeMessageHelper(); 3899 3900 // Set previously collected IKE fragments 3901 DecodeResultPartial mockCollectedFrags = mock(DecodeResultPartial.class); 3902 mSpyCurrentIkeSaRecord.updateCollectedFragments(mockCollectedFrags, true /*isResp*/); 3903 3904 // Receive last auth response with syntax error 3905 ReceivedIkePacket packet = 3906 makeDummyReceivedLastIkeFragmentPacketError( 3907 mSpyCurrentIkeSaRecord, 3908 true /*isResp*/, 3909 IkeHeader.EXCHANGE_TYPE_IKE_AUTH, 3910 mockCollectedFrags, 3911 new InvalidSyntaxException("IkeStateMachineTest")); 3912 mIkeSessionStateMachine.sendMessage(IkeSessionStateMachine.CMD_RECEIVE_IKE_PACKET, packet); 3913 mLooper.dispatchAll(); 3914 3915 // Verify Delete request is sent 3916 List<IkePayload> payloads = verifyOutInfoMsgHeaderAndGetPayloads(false /*isResp*/); 3917 assertEquals(1, payloads.size()); 3918 assertEquals(IkePayload.PAYLOAD_TYPE_DELETE, payloads.get(0).payloadType); 3919 3920 // Verify IKE Session is closed properly 3921 assertNull(mIkeSessionStateMachine.getCurrentState()); 3922 verify(mMockIkeSessionCallback).onClosedWithException(any(InvalidSyntaxException.class)); 3923 3924 // Collected response fragments are cleared 3925 assertNull(mSpyCurrentIkeSaRecord.getCollectedFragments(true /*isResp*/)); 3926 verify(mSpyCurrentIkeSaRecord).resetCollectedFragments(true /*isResp*/); 3927 } 3928 3929 @Test testRekeyIkeLocalCreateSendsRequest()3930 public void testRekeyIkeLocalCreateSendsRequest() throws Exception { 3931 setupIdleStateMachine(); 3932 3933 // Send Rekey-Create request 3934 mIkeSessionStateMachine.sendMessage( 3935 IkeSessionStateMachine.CMD_EXECUTE_LOCAL_REQ, 3936 mLocalRequestFactory.getIkeLocalRequest( 3937 IkeSessionStateMachine.CMD_LOCAL_REQUEST_REKEY_IKE)); 3938 mLooper.dispatchAll(); 3939 assertTrue( 3940 mIkeSessionStateMachine.getCurrentState() 3941 instanceof IkeSessionStateMachine.RekeyIkeLocalCreate); 3942 verifyRetransmissionStarted(); 3943 3944 // Verify outbound message 3945 IkeMessage rekeyMsg = verifyEncryptAndEncodeAndGetMessage(mSpyCurrentIkeSaRecord); 3946 3947 IkeHeader ikeHeader = rekeyMsg.ikeHeader; 3948 assertEquals(IkePayload.PAYLOAD_TYPE_SK, ikeHeader.nextPayloadType); 3949 assertEquals(IkeHeader.EXCHANGE_TYPE_CREATE_CHILD_SA, ikeHeader.exchangeType); 3950 assertEquals(mSpyCurrentIkeSaRecord.getLocalRequestMessageId(), ikeHeader.messageId); 3951 assertFalse(ikeHeader.isResponseMsg); 3952 assertTrue(ikeHeader.fromIkeInitiator); 3953 3954 // Verify SA payload & proposals 3955 IkeSaPayload saPayload = 3956 rekeyMsg.getPayloadForType(IkePayload.PAYLOAD_TYPE_SA, IkeSaPayload.class); 3957 assertFalse(saPayload.isSaResponse); 3958 assertEquals(1, saPayload.proposalList.size()); 3959 3960 IkeSaPayload.IkeProposal proposal = 3961 (IkeSaPayload.IkeProposal) saPayload.proposalList.get(0); 3962 assertEquals(1, proposal.number); // Must be 1-indexed 3963 assertEquals(IkePayload.PROTOCOL_ID_IKE, proposal.protocolId); 3964 assertEquals(IkePayload.SPI_LEN_IKE, proposal.spiSize); 3965 assertEquals(mIkeSessionStateMachine.mSaProposal, proposal.saProposal); 3966 3967 // Verify Nonce and KE payloads exist. 3968 assertNotNull( 3969 rekeyMsg.getPayloadForType(IkePayload.PAYLOAD_TYPE_NONCE, IkeNoncePayload.class)); 3970 3971 IkeKePayload kePayload = 3972 rekeyMsg.getPayloadForType(IkePayload.PAYLOAD_TYPE_KE, IkeKePayload.class); 3973 assertNotNull(kePayload); 3974 assertTrue(kePayload.isOutbound); 3975 } 3976 3977 @Test testRekeyIkeLocalCreateHandlesResponse()3978 public void testRekeyIkeLocalCreateHandlesResponse() throws Exception { 3979 setupIdleStateMachine(); 3980 3981 verifyRekeyIkeLocalCreateHandlesResponse(); 3982 } 3983 verifyRekeyIkeLocalCreateHandlesResponse()3984 private void verifyRekeyIkeLocalCreateHandlesResponse() throws Exception { 3985 // Send Rekey-Create request 3986 mIkeSessionStateMachine.sendMessage( 3987 IkeSessionStateMachine.CMD_EXECUTE_LOCAL_REQ, 3988 mLocalRequestFactory.getIkeLocalRequest( 3989 IkeSessionStateMachine.CMD_LOCAL_REQUEST_REKEY_IKE)); 3990 mLooper.dispatchAll(); 3991 verifyRetransmissionStarted(); 3992 3993 // Prepare "rekeyed" SA 3994 setupRekeyedIkeSa(mSpyLocalInitIkeSaRecord); 3995 3996 // Receive Rekey response 3997 ReceivedIkePacket dummyRekeyIkeRespReceivedPacket = makeRekeyIkeResponse(); 3998 mIkeSessionStateMachine.sendMessage( 3999 IkeSessionStateMachine.CMD_RECEIVE_IKE_PACKET, dummyRekeyIkeRespReceivedPacket); 4000 mLooper.dispatchAll(); 4001 verifyIncrementLocaReqMsgId(); 4002 verifyDecodeEncryptedMessage(mSpyCurrentIkeSaRecord, dummyRekeyIkeRespReceivedPacket); 4003 4004 // Verify in delete state, and new SA record was saved: 4005 assertTrue( 4006 mIkeSessionStateMachine.getCurrentState() 4007 instanceof IkeSessionStateMachine.RekeyIkeLocalDelete); 4008 verifyRetransmissionStarted(); 4009 assertEquals(mSpyLocalInitIkeSaRecord, mIkeSessionStateMachine.mLocalInitNewIkeSaRecord); 4010 verify(mSpyIkeConnectionCtrl.getIkeSocket()) 4011 .registerIke(eq(mSpyLocalInitIkeSaRecord.getLocalSpi()), eq(mSpyIkeConnectionCtrl)); 4012 } 4013 4014 @Test testRekeyIkeLocalCreateHandleRespWithParsingError()4015 public void testRekeyIkeLocalCreateHandleRespWithParsingError() throws Exception { 4016 setupIdleStateMachine(); 4017 4018 // Send Rekey-Create request 4019 mIkeSessionStateMachine.sendMessage( 4020 IkeSessionStateMachine.CMD_EXECUTE_LOCAL_REQ, 4021 mLocalRequestFactory.getIkeLocalRequest( 4022 IkeSessionStateMachine.CMD_LOCAL_REQUEST_REKEY_IKE)); 4023 mLooper.dispatchAll(); 4024 verifyRetransmissionStarted(); 4025 resetMockIkeMessageHelper(); 4026 4027 // Mock receiving packet with syntax error 4028 ReceivedIkePacket mockInvalidPacket = 4029 makeDummyReceivedIkePacketWithInvalidSyntax( 4030 mSpyCurrentIkeSaRecord, 4031 true /*isResp*/, 4032 IkeHeader.EXCHANGE_TYPE_CREATE_CHILD_SA); 4033 mIkeSessionStateMachine.sendMessage(CMD_RECEIVE_IKE_PACKET, mockInvalidPacket); 4034 mLooper.dispatchAll(); 4035 4036 // Verify Delete request was sent 4037 List<IkePayload> payloads = verifyOutInfoMsgHeaderAndGetPayloads(false /*isResp*/); 4038 assertEquals(1, payloads.size()); 4039 assertEquals(IkePayload.PAYLOAD_TYPE_DELETE, payloads.get(0).payloadType); 4040 4041 // Verify IKE Session is closed properly 4042 assertNull(mIkeSessionStateMachine.getCurrentState()); 4043 verify(mMockIkeSessionCallback).onClosedWithException(any(InvalidSyntaxException.class)); 4044 } 4045 4046 @Test testRekeyIkeLocalCreateHandleRespWithNonFatalErrorNotify()4047 public void testRekeyIkeLocalCreateHandleRespWithNonFatalErrorNotify() throws Exception { 4048 setupIdleStateMachine(); 4049 4050 // Send Rekey-Create request 4051 mIkeSessionStateMachine.sendMessage( 4052 IkeSessionStateMachine.CMD_EXECUTE_LOCAL_REQ, 4053 mLocalRequestFactory.getIkeLocalRequest( 4054 IkeSessionStateMachine.CMD_LOCAL_REQUEST_REKEY_IKE)); 4055 mLooper.dispatchAll(); 4056 4057 // Mock receiving packet with NO_PROPOSAL_CHOSEN 4058 ReceivedIkePacket resp = 4059 makeResponseWithErrorNotify(new IkeNotifyPayload(ERROR_TYPE_NO_PROPOSAL_CHOSEN)); 4060 mIkeSessionStateMachine.sendMessage(CMD_RECEIVE_IKE_PACKET, resp); 4061 mLooper.dispatchAll(); 4062 4063 // Verify IKE Session goes back to Idle and retry is scheduled 4064 verify(mSpyCurrentIkeSaRecord).rescheduleRekey(eq(RETRY_INTERVAL_MS)); 4065 assertTrue( 4066 mIkeSessionStateMachine.getCurrentState() instanceof IkeSessionStateMachine.Idle); 4067 } 4068 4069 @Test testRekeyIkeLocalCreateHandleRespWithFatalErrorNotify()4070 public void testRekeyIkeLocalCreateHandleRespWithFatalErrorNotify() throws Exception { 4071 setupIdleStateMachine(); 4072 4073 // Send Rekey-Create request 4074 mIkeSessionStateMachine.sendMessage( 4075 IkeSessionStateMachine.CMD_EXECUTE_LOCAL_REQ, 4076 mLocalRequestFactory.getIkeLocalRequest( 4077 IkeSessionStateMachine.CMD_LOCAL_REQUEST_REKEY_IKE)); 4078 mLooper.dispatchAll(); 4079 resetMockIkeMessageHelper(); 4080 4081 // Mock receiving packet with NO_PROPOSAL_CHOSEN 4082 ReceivedIkePacket resp = 4083 makeResponseWithErrorNotify(new IkeNotifyPayload(ERROR_TYPE_INVALID_SYNTAX)); 4084 mIkeSessionStateMachine.sendMessage(CMD_RECEIVE_IKE_PACKET, resp); 4085 mLooper.dispatchAll(); 4086 4087 // Verify no message was sent because a fatal error notification was received 4088 verifyEncryptAndEncodeNeverCalled(mSpyCurrentIkeSaRecord); 4089 4090 // Verify IKE Session is closed properly 4091 assertNull(mIkeSessionStateMachine.getCurrentState()); 4092 verify(mMockIkeSessionCallback).onClosedWithException(any(InvalidSyntaxException.class)); 4093 } 4094 4095 @Test testRekeyIkeLocalCreateSaCreationFail()4096 public void testRekeyIkeLocalCreateSaCreationFail() throws Exception { 4097 // Throw error when building new IKE SA 4098 throwExceptionWhenMakeRekeyIkeSa( 4099 new GeneralSecurityException("testRekeyIkeLocalCreateSaCreationFail")); 4100 4101 setupIdleStateMachine(); 4102 4103 // Send Rekey-Create request 4104 mIkeSessionStateMachine.sendMessage( 4105 IkeSessionStateMachine.CMD_EXECUTE_LOCAL_REQ, 4106 mLocalRequestFactory.getIkeLocalRequest( 4107 IkeSessionStateMachine.CMD_LOCAL_REQUEST_REKEY_IKE)); 4108 mLooper.dispatchAll(); 4109 resetMockIkeMessageHelper(); 4110 4111 // Receive Rekey response 4112 ReceivedIkePacket dummyRekeyIkeRespReceivedPacket = makeRekeyIkeResponse(); 4113 mIkeSessionStateMachine.sendMessage( 4114 IkeSessionStateMachine.CMD_RECEIVE_IKE_PACKET, dummyRekeyIkeRespReceivedPacket); 4115 mLooper.dispatchAll(); 4116 4117 // Verify Delete request was sent 4118 List<IkePayload> payloads = verifyOutInfoMsgHeaderAndGetPayloads(false /*isResp*/); 4119 assertEquals(1, payloads.size()); 4120 assertEquals(IkePayload.PAYLOAD_TYPE_DELETE, payloads.get(0).payloadType); 4121 4122 // Verify IKE Session is closed properly 4123 assertNull(mIkeSessionStateMachine.getCurrentState()); 4124 verify(mMockIkeSessionCallback).onClosedWithException(any(IkeInternalException.class)); 4125 } 4126 4127 @Test testRekeyIkeLocalCreateHandleReqWithNonFatalError()4128 public void testRekeyIkeLocalCreateHandleReqWithNonFatalError() throws Exception { 4129 setupIdleStateMachine(); 4130 4131 // Send Rekey-Create request 4132 mIkeSessionStateMachine.sendMessage( 4133 IkeSessionStateMachine.CMD_EXECUTE_LOCAL_REQ, 4134 mLocalRequestFactory.getIkeLocalRequest( 4135 IkeSessionStateMachine.CMD_LOCAL_REQUEST_REKEY_IKE)); 4136 mLooper.dispatchAll(); 4137 verifyRetransmissionStarted(); 4138 resetMockIkeMessageHelper(); 4139 4140 // Build protocol exception 4141 List<Integer> unsupportedPayloads = new ArrayList<>(); 4142 unsupportedPayloads.add(PAYLOAD_TYPE_UNSUPPORTED); 4143 UnsupportedCriticalPayloadException exception = 4144 new UnsupportedCriticalPayloadException(unsupportedPayloads); 4145 4146 // Mock receiving packet with unsupported critical payload 4147 ReceivedIkePacket mockInvalidPacket = 4148 makeDummyReceivedIkePacketWithDecodingError( 4149 mSpyCurrentIkeSaRecord, 4150 false /*isResp*/, 4151 IkeHeader.EXCHANGE_TYPE_CREATE_CHILD_SA, 4152 exception); 4153 mIkeSessionStateMachine.sendMessage(CMD_RECEIVE_IKE_PACKET, mockInvalidPacket); 4154 mLooper.dispatchAll(); 4155 4156 // Verify error notification was sent 4157 List<IkePayload> payloads = verifyOutInfoMsgHeaderAndGetPayloads(true /*isResp*/); 4158 assertEquals(1, payloads.size()); 4159 4160 IkePayload payload = payloads.get(0); 4161 assertEquals(IkePayload.PAYLOAD_TYPE_NOTIFY, payload.payloadType); 4162 assertEquals( 4163 ERROR_TYPE_UNSUPPORTED_CRITICAL_PAYLOAD, ((IkeNotifyPayload) payload).notifyType); 4164 4165 // Verify IKE Session stays in the same state 4166 assertTrue( 4167 mIkeSessionStateMachine.getCurrentState() 4168 instanceof IkeSessionStateMachine.RekeyIkeLocalCreate); 4169 } 4170 mockRescheduleRekey(IkeSaRecord spySaRecord)4171 private void mockRescheduleRekey(IkeSaRecord spySaRecord) { 4172 IkeLocalRequest rekeyReq = 4173 mLocalRequestFactory.getIkeLocalRequest( 4174 IkeSessionStateMachine.CMD_LOCAL_REQUEST_REKEY_IKE); 4175 doAnswer( 4176 (invocation) -> { 4177 mIkeSessionStateMachine.sendMessageDelayed( 4178 IkeSessionStateMachine.CMD_LOCAL_REQUEST_REKEY_IKE, 4179 rekeyReq, 4180 RETRY_INTERVAL_MS); 4181 return null; 4182 }) 4183 .when(spySaRecord) 4184 .rescheduleRekey(eq(RETRY_INTERVAL_MS)); 4185 } 4186 4187 @Test testRekeyIkeLocalCreateHandleRespWithTempFailure()4188 public void testRekeyIkeLocalCreateHandleRespWithTempFailure() throws Exception { 4189 setupIdleStateMachine(); 4190 4191 // Send Rekey-Create request 4192 mIkeSessionStateMachine.sendMessage( 4193 IkeSessionStateMachine.CMD_EXECUTE_LOCAL_REQ, 4194 mLocalRequestFactory.getIkeLocalRequest( 4195 IkeSessionStateMachine.CMD_LOCAL_REQUEST_REKEY_IKE)); 4196 mLooper.dispatchAll(); 4197 4198 // Mock sending TEMPORARY_FAILURE response 4199 mockRcvTempFail(); 4200 mLooper.dispatchAll(); 4201 4202 verify(mSpyCurrentIkeSaRecord).rescheduleRekey(eq(RETRY_INTERVAL_MS)); 4203 assertTrue( 4204 mIkeSessionStateMachine.getCurrentState() instanceof IkeSessionStateMachine.Idle); 4205 } 4206 mockCreateAndTransitionToRekeyDeleteLocal()4207 private void mockCreateAndTransitionToRekeyDeleteLocal() { 4208 // Seed fake rekey data and force transition to RekeyIkeLocalDelete 4209 mIkeSessionStateMachine.mLocalInitNewIkeSaRecord = mSpyLocalInitIkeSaRecord; 4210 mIkeSessionStateMachine.addIkeSaRecord(mSpyLocalInitIkeSaRecord); 4211 mIkeSessionStateMachine.sendMessage( 4212 IkeSessionStateMachine.CMD_FORCE_TRANSITION, 4213 mIkeSessionStateMachine.mRekeyIkeLocalDelete); 4214 mLooper.dispatchAll(); 4215 verifyRetransmissionStarted(); 4216 } 4217 4218 @Test testRekeyIkeLocalDeleteSendsRequest()4219 public void testRekeyIkeLocalDeleteSendsRequest() throws Exception { 4220 setupIdleStateMachine(); 4221 mockCreateAndTransitionToRekeyDeleteLocal(); 4222 4223 // Verify Rekey-Delete request 4224 assertTrue( 4225 mIkeSessionStateMachine.getCurrentState() 4226 instanceof IkeSessionStateMachine.RekeyIkeLocalDelete); 4227 verifyRetransmissionStarted(); 4228 4229 // Verify outbound message 4230 IkeMessage delMsg = verifyEncryptAndEncodeAndGetMessage(mSpyCurrentIkeSaRecord); 4231 4232 IkeHeader ikeHeader = delMsg.ikeHeader; 4233 assertEquals(mSpyCurrentIkeSaRecord.getInitiatorSpi(), ikeHeader.ikeInitiatorSpi); 4234 assertEquals(mSpyCurrentIkeSaRecord.getResponderSpi(), ikeHeader.ikeResponderSpi); 4235 assertEquals(IkePayload.PAYLOAD_TYPE_SK, ikeHeader.nextPayloadType); 4236 assertEquals(IkeHeader.EXCHANGE_TYPE_INFORMATIONAL, ikeHeader.exchangeType); 4237 assertEquals(mSpyCurrentIkeSaRecord.isLocalInit, ikeHeader.fromIkeInitiator); 4238 assertFalse(ikeHeader.isResponseMsg); 4239 4240 List<IkeDeletePayload> deletePayloadList = 4241 delMsg.getPayloadListForType( 4242 IkePayload.PAYLOAD_TYPE_DELETE, IkeDeletePayload.class); 4243 assertEquals(1, deletePayloadList.size()); 4244 4245 IkeDeletePayload deletePayload = deletePayloadList.get(0); 4246 assertEquals(IkePayload.PROTOCOL_ID_IKE, deletePayload.protocolId); 4247 assertEquals(0, deletePayload.numSpi); 4248 assertEquals(0, deletePayload.spiSize); 4249 assertArrayEquals(new int[0], deletePayload.spisToDelete); 4250 } 4251 verifyRekeyReplaceSa(IkeSaRecord newSaRecord)4252 private void verifyRekeyReplaceSa(IkeSaRecord newSaRecord) { 4253 verify(mSpyCurrentIkeSaRecord).close(); 4254 verify(mMockCurrentIkeSocket).unregisterIke(eq(mSpyCurrentIkeSaRecord.getLocalSpi())); 4255 verify(mMockCurrentIkeSocket, never()).unregisterIke(eq(newSaRecord.getLocalSpi())); 4256 4257 assertEquals(mIkeSessionStateMachine.mCurrentIkeSaRecord, newSaRecord); 4258 4259 verify(mMockChildSessionStateMachine).setSkD(newSaRecord.getSkD()); 4260 } 4261 4262 @Test testRekeyIkeLocalDeleteHandlesResponse()4263 public void testRekeyIkeLocalDeleteHandlesResponse() throws Exception { 4264 setupIdleStateMachine(); 4265 mockCreateAndTransitionToRekeyDeleteLocal(); 4266 4267 // Receive Delete response 4268 ReceivedIkePacket dummyDeleteIkeRespReceivedPacket = 4269 makeDeleteIkeResponse(mSpyCurrentIkeSaRecord); 4270 mIkeSessionStateMachine.sendMessage( 4271 IkeSessionStateMachine.CMD_RECEIVE_IKE_PACKET, dummyDeleteIkeRespReceivedPacket); 4272 mLooper.dispatchAll(); 4273 verifyIncrementLocaReqMsgId(); 4274 verifyDecodeEncryptedMessage(mSpyCurrentIkeSaRecord, dummyDeleteIkeRespReceivedPacket); 4275 4276 // Verify final state - Idle, with new SA, and old SA closed. 4277 verifyRekeyReplaceSa(mSpyLocalInitIkeSaRecord); 4278 verify(mMockIkeSessionCallback, never()).onClosed(); 4279 assertTrue( 4280 mIkeSessionStateMachine.getCurrentState() instanceof IkeSessionStateMachine.Idle); 4281 verifyRetransmissionStopped(); 4282 } 4283 4284 @Ignore disableTestRekeyIkeLocalDeleteHandlesRespWithParsingError()4285 public void disableTestRekeyIkeLocalDeleteHandlesRespWithParsingError() throws Exception { 4286 setupIdleStateMachine(); 4287 mockCreateAndTransitionToRekeyDeleteLocal(); 4288 resetMockIkeMessageHelper(); 4289 4290 // Mock receiving packet with syntax error 4291 ReceivedIkePacket mockInvalidPacket = 4292 makeDummyReceivedIkePacketWithInvalidSyntax( 4293 mSpyCurrentIkeSaRecord, 4294 true /*isResp*/, 4295 IkeHeader.EXCHANGE_TYPE_INFORMATIONAL); 4296 mIkeSessionStateMachine.sendMessage(CMD_RECEIVE_IKE_PACKET, mockInvalidPacket); 4297 mLooper.dispatchAll(); 4298 4299 // Verify no more request out 4300 verifyEncryptAndEncodeNeverCalled(mSpyCurrentIkeSaRecord); 4301 4302 // Verify final state - Idle, with new SA, and old SA closed. 4303 verifyRekeyReplaceSa(mSpyLocalInitIkeSaRecord); 4304 assertTrue( 4305 mIkeSessionStateMachine.getCurrentState() instanceof IkeSessionStateMachine.Idle); 4306 verifyRetransmissionStopped(); 4307 } 4308 4309 @Test testRekeyIkeLocalDeleteWithRequestOnNewSa()4310 public void testRekeyIkeLocalDeleteWithRequestOnNewSa() throws Exception { 4311 setupIdleStateMachine(); 4312 mockCreateAndTransitionToRekeyDeleteLocal(); 4313 4314 // Receive an empty (DPD) request on the new IKE SA 4315 mIkeSessionStateMachine.sendMessage( 4316 IkeSessionStateMachine.CMD_RECEIVE_IKE_PACKET, 4317 makeDpdIkeRequest(mSpyLocalInitIkeSaRecord)); 4318 mLooper.dispatchAll(); 4319 4320 // Verify final state - Idle, with new SA, and old SA closed. 4321 verifyRekeyReplaceSa(mSpyLocalInitIkeSaRecord); 4322 assertTrue( 4323 mIkeSessionStateMachine.getCurrentState() instanceof IkeSessionStateMachine.Idle); 4324 verifyRetransmissionStopped(); 4325 } 4326 4327 @Test testRekeyIkeLocalDeleteWithRequestFragOnNewSa()4328 public void testRekeyIkeLocalDeleteWithRequestFragOnNewSa() throws Exception { 4329 setupIdleStateMachine(); 4330 mockCreateAndTransitionToRekeyDeleteLocal(); 4331 4332 // Received IKE fragment 4333 byte[] unencryptedData = "testRekeyIkeLocalDeleteWithRequestFragOnNewSa".getBytes(); 4334 int fragNum = 1; 4335 int totalFragments = 2; 4336 IkeSkfPayload skfPayload = 4337 IkeTestUtils.makeDummySkfPayload(unencryptedData, fragNum, totalFragments); 4338 4339 ReceivedIkePacket packet = 4340 makeDummyReceivedIkeFragmentPacket( 4341 mSpyLocalInitIkeSaRecord, 4342 false /*isResp*/, 4343 IkeHeader.EXCHANGE_TYPE_CREATE_CHILD_SA, 4344 skfPayload, 4345 PAYLOAD_TYPE_SA, 4346 null /* collectedFrags*/); 4347 mIkeSessionStateMachine.sendMessage(IkeSessionStateMachine.CMD_RECEIVE_IKE_PACKET, packet); 4348 mLooper.dispatchAll(); 4349 4350 // Verify rekey is done. 4351 verifyRekeyReplaceSa(mSpyLocalInitIkeSaRecord); 4352 verifyRetransmissionStopped(); 4353 4354 // Verify the IkeSaRecord has stored the new fragment. 4355 DecodeResultPartial resultPartial = 4356 mSpyLocalInitIkeSaRecord.getCollectedFragments(false /*isResp*/); 4357 assertEquals(PAYLOAD_TYPE_SA, resultPartial.firstPayloadType); 4358 assertEquals(totalFragments, resultPartial.collectedFragsList.length); 4359 assertArrayEquals(unencryptedData, resultPartial.collectedFragsList[fragNum - 1]); 4360 assertFalse(resultPartial.isAllFragmentsReceived()); 4361 } 4362 4363 @Test testRekeyIkeRemoteDeleteWithRequestOnNewSa()4364 public void testRekeyIkeRemoteDeleteWithRequestOnNewSa() throws Exception { 4365 setupIdleStateMachine(); 4366 4367 // Seed fake rekey data and force transition to RekeyIkeRemoteDelete 4368 mIkeSessionStateMachine.mRemoteInitNewIkeSaRecord = mSpyRemoteInitIkeSaRecord; 4369 mIkeSessionStateMachine.addIkeSaRecord(mSpyRemoteInitIkeSaRecord); 4370 mIkeSessionStateMachine.sendMessage( 4371 IkeSessionStateMachine.CMD_FORCE_TRANSITION, 4372 mIkeSessionStateMachine.mRekeyIkeRemoteDelete); 4373 mLooper.dispatchAll(); 4374 4375 // Receive an empty (DPD) request on the new IKE SA 4376 mIkeSessionStateMachine.sendMessage( 4377 IkeSessionStateMachine.CMD_RECEIVE_IKE_PACKET, 4378 makeDpdIkeRequest(mSpyRemoteInitIkeSaRecord)); 4379 mLooper.dispatchAll(); 4380 4381 // Verify final state - Idle, with new SA, and old SA closed. 4382 verifyRekeyReplaceSa(mSpyRemoteInitIkeSaRecord); 4383 assertTrue( 4384 mIkeSessionStateMachine.getCurrentState() instanceof IkeSessionStateMachine.Idle); 4385 } 4386 4387 @Test testRekeyIkeRemoteCreate()4388 public void testRekeyIkeRemoteCreate() throws Exception { 4389 setupIdleStateMachine(); 4390 4391 setupRekeyedIkeSa(mSpyRemoteInitIkeSaRecord); 4392 4393 // Receive Rekey request 4394 ReceivedIkePacket dummyRekeyIkeRequestReceivedPacket = makeRekeyIkeRequest(); 4395 mIkeSessionStateMachine.sendMessage( 4396 IkeSessionStateMachine.CMD_RECEIVE_IKE_PACKET, dummyRekeyIkeRequestReceivedPacket); 4397 mLooper.dispatchAll(); 4398 verifyIncrementRemoteReqMsgId(); 4399 verifyDecodeEncryptedMessage(mSpyCurrentIkeSaRecord, dummyRekeyIkeRequestReceivedPacket); 4400 4401 // Verify SA created with correct parameters 4402 ArgumentCaptor<SaRecord.IkeSaRecordConfig> recordConfigCaptor = 4403 ArgumentCaptor.forClass(SaRecord.IkeSaRecordConfig.class); 4404 verify(mMockSaRecordHelper) 4405 .makeRekeyedIkeSaRecord(any(), any(), any(), any(), recordConfigCaptor.capture()); 4406 assertEquals(IKE_REKEY_SA_INITIATOR_SPI, recordConfigCaptor.getValue().initSpi.getSpi()); 4407 4408 // Verify outbound CREATE_CHILD_SA message 4409 IkeMessage rekeyCreateResp = 4410 verifyAndGetOutboundEncryptedResp(IkeHeader.EXCHANGE_TYPE_CREATE_CHILD_SA); 4411 assertNotNull( 4412 rekeyCreateResp.getPayloadForType(IkePayload.PAYLOAD_TYPE_SA, IkeSaPayload.class)); 4413 assertNotNull( 4414 rekeyCreateResp.getPayloadForType(IkePayload.PAYLOAD_TYPE_KE, IkeKePayload.class)); 4415 assertNotNull( 4416 rekeyCreateResp.getPayloadForType( 4417 IkePayload.PAYLOAD_TYPE_NONCE, IkeNoncePayload.class)); 4418 4419 // Verify SA, StateMachine state 4420 assertEquals(mSpyCurrentIkeSaRecord, mIkeSessionStateMachine.mIkeSaRecordAwaitingRemoteDel); 4421 assertEquals(mSpyRemoteInitIkeSaRecord, mIkeSessionStateMachine.mIkeSaRecordSurviving); 4422 assertTrue( 4423 mIkeSessionStateMachine.getCurrentState() 4424 instanceof IkeSessionStateMachine.RekeyIkeRemoteDelete); 4425 verify(mMockCurrentIkeSocket) 4426 .registerIke( 4427 eq(mSpyRemoteInitIkeSaRecord.getLocalSpi()), eq(mSpyIkeConnectionCtrl)); 4428 } 4429 4430 @Ignore disableTestRekeyIkeRemoteCreateHandlesInvalidReq()4431 public void disableTestRekeyIkeRemoteCreateHandlesInvalidReq() throws Exception { 4432 setupIdleStateMachine(); 4433 4434 // Receive Rekey request 4435 ReceivedIkePacket request = makeRekeyIkeRequestWithUnacceptableProposal(); 4436 mIkeSessionStateMachine.sendMessage(IkeSessionStateMachine.CMD_RECEIVE_IKE_PACKET, request); 4437 mLooper.dispatchAll(); 4438 4439 verifyProcessRekeyReqFailure(ERROR_TYPE_NO_PROPOSAL_CHOSEN); 4440 } 4441 4442 @Ignore disableTestRekeyIkeRemoteCreateSaCreationFailure()4443 public void disableTestRekeyIkeRemoteCreateSaCreationFailure() throws Exception { 4444 // Throw error when building new IKE SA 4445 throwExceptionWhenMakeRekeyIkeSa( 4446 new GeneralSecurityException("testRekeyIkeRemoteCreateSaCreationFailure")); 4447 setupIdleStateMachine(); 4448 4449 // Receive Rekey request 4450 ReceivedIkePacket request = makeRekeyIkeRequest(); 4451 mIkeSessionStateMachine.sendMessage(IkeSessionStateMachine.CMD_RECEIVE_IKE_PACKET, request); 4452 mLooper.dispatchAll(); 4453 4454 verifyProcessRekeyReqFailure(ERROR_TYPE_NO_PROPOSAL_CHOSEN); 4455 } 4456 4457 @Test testRekeyIkeRemoteCreateHandlesInvalidKePayload()4458 public void testRekeyIkeRemoteCreateHandlesInvalidKePayload() throws Exception { 4459 setupIdleStateMachine(); 4460 4461 // Build Rekey request 4462 // SA Payload: ENCR_AES_CBC(128)|AUTH_HMAC_SHA1_96|DH_1024_BIT_MODP|PRF_HMAC_SHA1 4463 IkePayload saPayload = 4464 IkeTestUtils.hexStringToIkePayload( 4465 IkePayload.PAYLOAD_TYPE_SA, 4466 false /*isResp*/, 4467 IKE_REKEY_SA_PAYLOAD_HEX_STRING); 4468 4469 // Unrecognized DH Group: 0x0fff 4470 String unrecognizedKePayload = 4471 "280000880fff0000b4a2faf4bb54878ae21d638512ece55d9236fc50" 4472 + "46ab6cef82220f421f3ce6361faf36564ecb6d28798a94aa" 4473 + "d7b2b4b603ddeaaa5630adb9ece8ac37534036040610ebdd" 4474 + "92f46bef84f0be7db860351843858f8acf87056e272377f7" 4475 + "0c9f2d81e29c7b0ce4f291a3a72476bb0b278fd4b7b0a4c2" 4476 + "6bbeb08214c7071376079587"; 4477 IkePayload kePayload = 4478 IkeTestUtils.hexStringToIkePayload( 4479 IkePayload.PAYLOAD_TYPE_KE, false /*isResp*/, unrecognizedKePayload); 4480 4481 IkePayload noncePayload = 4482 IkeTestUtils.hexStringToIkePayload( 4483 IkePayload.PAYLOAD_TYPE_NONCE, 4484 false /*isResp*/, 4485 NONCE_INIT_PAYLOAD_HEX_STRING); 4486 4487 ReceivedIkePacket request = 4488 makeDummyEncryptedReceivedIkePacketWithPayloadList( 4489 mSpyCurrentIkeSaRecord, 4490 IkeHeader.EXCHANGE_TYPE_CREATE_CHILD_SA, 4491 false /*isResp*/, 4492 Arrays.asList(saPayload, kePayload, noncePayload)); 4493 4494 // Receive Rekey request 4495 mIkeSessionStateMachine.sendMessage(IkeSessionStateMachine.CMD_RECEIVE_IKE_PACKET, request); 4496 mLooper.dispatchAll(); 4497 4498 verifyProcessRekeyReqFailure(ERROR_TYPE_INVALID_KE_PAYLOAD); 4499 } 4500 4501 @Test testRejectRemoteRekeyWithoutDhGroupInProposal()4502 public void testRejectRemoteRekeyWithoutDhGroupInProposal() throws Exception { 4503 setupIdleStateMachine(); 4504 4505 // Build a Rekey request that does not propose DH groups. 4506 String rekeySaPayloadWithoutDhGroup = 4507 "22000038000000340101080400000000000000FF0300000c0100000c800e0080030" 4508 + "000080300000203000008020000020000000802000002"; 4509 IkePayload saPayload = 4510 IkeTestUtils.hexStringToIkePayload( 4511 IkePayload.PAYLOAD_TYPE_SA, false /*isResp*/, rekeySaPayloadWithoutDhGroup); 4512 IkePayload kePayload = 4513 IkeTestUtils.hexStringToIkePayload( 4514 IkePayload.PAYLOAD_TYPE_KE, false /*isResp*/, KE_PAYLOAD_HEX_STRING); 4515 IkePayload noncePayload = 4516 IkeTestUtils.hexStringToIkePayload( 4517 IkePayload.PAYLOAD_TYPE_NONCE, 4518 false /*isResp*/, 4519 NONCE_INIT_PAYLOAD_HEX_STRING); 4520 ReceivedIkePacket request = 4521 makeRekeyIkeRequestWithPayloads(Arrays.asList(saPayload, kePayload, noncePayload)); 4522 4523 mIkeSessionStateMachine.sendMessage(IkeSessionStateMachine.CMD_RECEIVE_IKE_PACKET, request); 4524 mLooper.dispatchAll(); 4525 4526 verifyProcessRekeyReqFailure(ERROR_TYPE_NO_PROPOSAL_CHOSEN); 4527 } 4528 4529 @Test testRejectRemoteRekeyWithoutKePayload()4530 public void testRejectRemoteRekeyWithoutKePayload() throws Exception { 4531 setupIdleStateMachine(); 4532 4533 // Build a Rekey request that proposes DH groups but does not include a KE payload 4534 IkePayload saPayload = 4535 IkeTestUtils.hexStringToIkePayload( 4536 IkePayload.PAYLOAD_TYPE_SA, 4537 false /*isResp*/, 4538 IKE_REKEY_SA_PAYLOAD_HEX_STRING); 4539 IkePayload noncePayload = 4540 IkeTestUtils.hexStringToIkePayload( 4541 IkePayload.PAYLOAD_TYPE_NONCE, 4542 false /*isResp*/, 4543 NONCE_INIT_PAYLOAD_HEX_STRING); 4544 ReceivedIkePacket request = 4545 makeRekeyIkeRequestWithPayloads(Arrays.asList(saPayload, noncePayload)); 4546 4547 mIkeSessionStateMachine.sendMessage(IkeSessionStateMachine.CMD_RECEIVE_IKE_PACKET, request); 4548 mLooper.dispatchAll(); 4549 4550 verifyProcessRekeyReqFailure(ERROR_TYPE_INVALID_SYNTAX); 4551 } 4552 verifyProcessRekeyReqFailure(int expectedErrorCode)4553 private void verifyProcessRekeyReqFailure(int expectedErrorCode) { 4554 // Verify IKE Session is back to Idle 4555 assertTrue( 4556 mIkeSessionStateMachine.getCurrentState() instanceof IkeSessionStateMachine.Idle); 4557 4558 // Verify error notification was sent 4559 List<IkePayload> payloads = verifyOutInfoMsgHeaderAndGetPayloads(true /*isResp*/); 4560 assertEquals(1, payloads.size()); 4561 IkeNotifyPayload notify = (IkeNotifyPayload) payloads.get(0); 4562 assertEquals(expectedErrorCode, notify.notifyType); 4563 } 4564 4565 @Test testRekeyIkeRemoteDelete()4566 public void testRekeyIkeRemoteDelete() throws Exception { 4567 setupIdleStateMachine(); 4568 4569 // Seed fake rekey data and force transition to RekeyIkeLocalDelete 4570 mIkeSessionStateMachine.mRemoteInitNewIkeSaRecord = mSpyRemoteInitIkeSaRecord; 4571 mIkeSessionStateMachine.sendMessage( 4572 IkeSessionStateMachine.CMD_FORCE_TRANSITION, 4573 mIkeSessionStateMachine.mRekeyIkeRemoteDelete); 4574 mLooper.dispatchAll(); 4575 4576 // Rekey Delete request 4577 ReceivedIkePacket dummyDeleteIkeRequestReceivedPacket = 4578 makeDeleteIkeRequest(mSpyCurrentIkeSaRecord); 4579 mIkeSessionStateMachine.sendMessage( 4580 IkeSessionStateMachine.CMD_RECEIVE_IKE_PACKET, dummyDeleteIkeRequestReceivedPacket); 4581 mLooper.dispatchAll(); 4582 verifyIncrementRemoteReqMsgId(); 4583 verifyDecodeEncryptedMessage(mSpyCurrentIkeSaRecord, dummyDeleteIkeRequestReceivedPacket); 4584 4585 // Verify outbound DELETE_IKE_SA message 4586 IkeMessage rekeyDeleteResp = verifyEncryptAndEncodeAndGetMessage(mSpyCurrentIkeSaRecord); 4587 IkeHeader rekeyDeleteRespHeader = rekeyDeleteResp.ikeHeader; 4588 assertEquals(IkePayload.PAYLOAD_TYPE_SK, rekeyDeleteRespHeader.nextPayloadType); 4589 assertEquals(IkeHeader.EXCHANGE_TYPE_INFORMATIONAL, rekeyDeleteRespHeader.exchangeType); 4590 assertTrue(rekeyDeleteRespHeader.isResponseMsg); 4591 assertTrue(rekeyDeleteRespHeader.fromIkeInitiator); 4592 assertTrue(rekeyDeleteResp.ikePayloadList.isEmpty()); 4593 4594 // Verify final state - Idle, with new SA, and old SA closed. 4595 verifyRekeyReplaceSa(mSpyRemoteInitIkeSaRecord); 4596 4597 verify(mMockIkeSessionCallback, never()).onClosed(); 4598 4599 verifyDecodeEncryptedMessage(mSpyCurrentIkeSaRecord, dummyDeleteIkeRequestReceivedPacket); 4600 assertTrue( 4601 mIkeSessionStateMachine.getCurrentState() instanceof IkeSessionStateMachine.Idle); 4602 } 4603 4604 @Test testRekeyIkeRemoteDeleteExitAndRenter()4605 public void testRekeyIkeRemoteDeleteExitAndRenter() throws Exception { 4606 setupIdleStateMachine(); 4607 4608 // Seed fake rekey data and force transition to RekeyIkeLocalDelete 4609 mIkeSessionStateMachine.mRemoteInitNewIkeSaRecord = mSpyRemoteInitIkeSaRecord; 4610 mIkeSessionStateMachine.sendMessage( 4611 IkeSessionStateMachine.CMD_FORCE_TRANSITION, 4612 mIkeSessionStateMachine.mRekeyIkeRemoteDelete); 4613 mLooper.dispatchAll(); 4614 4615 // Trigger a timeout, and immediately re-enter remote-delete 4616 mLooper.moveTimeForward(IkeSessionStateMachine.REKEY_DELETE_TIMEOUT_MS / 2 + 1); 4617 mIkeSessionStateMachine.sendMessage(IkeSessionStateMachine.TIMEOUT_REKEY_REMOTE_DELETE); 4618 mIkeSessionStateMachine.sendMessage( 4619 IkeSessionStateMachine.CMD_FORCE_TRANSITION, 4620 mIkeSessionStateMachine.mRekeyIkeRemoteDelete); 4621 mLooper.dispatchAll(); 4622 4623 // Shift time forward, and assert the previous timeout was NOT fired. 4624 mLooper.moveTimeForward(IkeSessionStateMachine.REKEY_DELETE_TIMEOUT_MS / 2 + 1); 4625 mLooper.dispatchAll(); 4626 4627 // Verify no request received, or response sent. 4628 verify(mMockIkeMessageHelper, never()).decode(anyInt(), anyObject(), anyObject()); 4629 verifyEncryptAndEncodeNeverCalled(mSpyCurrentIkeSaRecord); 4630 4631 // Verify final state has not changed - signal was not sent. 4632 assertTrue( 4633 mIkeSessionStateMachine.getCurrentState() 4634 instanceof IkeSessionStateMachine.RekeyIkeRemoteDelete); 4635 } 4636 4637 @Test testRekeyIkeRemoteDeleteTimedOut()4638 public void testRekeyIkeRemoteDeleteTimedOut() throws Exception { 4639 setupIdleStateMachine(); 4640 4641 // Seed fake rekey data and force transition to RekeyIkeLocalDelete 4642 mIkeSessionStateMachine.mRemoteInitNewIkeSaRecord = mSpyRemoteInitIkeSaRecord; 4643 mIkeSessionStateMachine.sendMessage( 4644 IkeSessionStateMachine.CMD_FORCE_TRANSITION, 4645 mIkeSessionStateMachine.mRekeyIkeRemoteDelete); 4646 mLooper.dispatchAll(); 4647 4648 mLooper.moveTimeForward(IkeSessionStateMachine.REKEY_DELETE_TIMEOUT_MS); 4649 mLooper.dispatchAll(); 4650 4651 // Verify no request received, or response sent. 4652 verify(mMockIkeMessageHelper, never()).decode(anyInt(), anyObject(), anyObject()); 4653 verifyEncryptAndEncodeNeverCalled(mSpyCurrentIkeSaRecord); 4654 4655 // Verify final state - Idle, with new SA, and old SA closed. 4656 verifyRekeyReplaceSa(mSpyRemoteInitIkeSaRecord); 4657 4658 assertTrue( 4659 mIkeSessionStateMachine.getCurrentState() instanceof IkeSessionStateMachine.Idle); 4660 } 4661 4662 @Ignore disableTestSimulRekey()4663 public void disableTestSimulRekey() throws Exception { 4664 setupIdleStateMachine(); 4665 4666 // Prepare "rekeyed" SA 4667 setupRekeyedIkeSa(mSpyLocalInitIkeSaRecord); 4668 doReturn(1).when(mSpyLocalInitIkeSaRecord).compareTo(mSpyRemoteInitIkeSaRecord); 4669 4670 // Send Rekey request on mSpyCurrentIkeSaRecord 4671 mIkeSessionStateMachine.sendMessage( 4672 IkeSessionStateMachine.CMD_EXECUTE_LOCAL_REQ, 4673 mLocalRequestFactory.getIkeLocalRequest( 4674 IkeSessionStateMachine.CMD_LOCAL_REQUEST_REKEY_IKE)); 4675 4676 // Receive Rekey request on mSpyCurrentIkeSaRecord 4677 ReceivedIkePacket dummyRekeyIkeRequestReceivedPacket = makeRekeyIkeRequest(); 4678 mIkeSessionStateMachine.sendMessage( 4679 IkeSessionStateMachine.CMD_RECEIVE_IKE_PACKET, dummyRekeyIkeRequestReceivedPacket); 4680 mLooper.dispatchAll(); 4681 verifyIncrementRemoteReqMsgId(); 4682 4683 // Receive Rekey response on mSpyCurrentIkeSaRecord 4684 ReceivedIkePacket dummyRekeyIkeRespReceivedPacket = makeRekeyIkeResponse(); 4685 mIkeSessionStateMachine.sendMessage( 4686 IkeSessionStateMachine.CMD_RECEIVE_IKE_PACKET, dummyRekeyIkeRespReceivedPacket); 4687 mLooper.dispatchAll(); 4688 verifyIncrementLocaReqMsgId(); 4689 verify(mMockCurrentIkeSocket) 4690 .registerIke(eq(mSpyLocalInitIkeSaRecord.getLocalSpi()), eq(mSpyIkeConnectionCtrl)); 4691 4692 // Receive Delete response on mSpyCurrentIkeSaRecord 4693 ReceivedIkePacket dummyDeleteIkeRespReceivedPacket = 4694 makeDeleteIkeResponse(mSpyCurrentIkeSaRecord); 4695 mIkeSessionStateMachine.sendMessage( 4696 IkeSessionStateMachine.CMD_RECEIVE_IKE_PACKET, dummyDeleteIkeRespReceivedPacket); 4697 mLooper.dispatchAll(); 4698 verifyIncrementLocaReqMsgId(); 4699 4700 // Verify 4701 verifyDecodeEncryptedMessage(mSpyCurrentIkeSaRecord, dummyRekeyIkeRequestReceivedPacket); 4702 verifyDecodeEncryptedMessage(mSpyCurrentIkeSaRecord, dummyRekeyIkeRespReceivedPacket); 4703 verifyDecodeEncryptedMessage(mSpyCurrentIkeSaRecord, dummyDeleteIkeRespReceivedPacket); 4704 assertTrue( 4705 mIkeSessionStateMachine.getCurrentState() instanceof IkeSessionStateMachine.Idle); 4706 4707 verifyRekeyReplaceSa(mSpyLocalInitIkeSaRecord); 4708 verify(mMockIkeSessionCallback, never()).onClosed(); 4709 } 4710 4711 @Test testOpenIkeSession()4712 public void testOpenIkeSession() throws Exception { 4713 assertTrue( 4714 mIkeSessionStateMachine.getCurrentState() 4715 instanceof IkeSessionStateMachine.Initial); 4716 4717 mIkeSessionStateMachine.openSession(); 4718 mLooper.dispatchAll(); 4719 4720 assertTrue( 4721 mIkeSessionStateMachine.getCurrentState() 4722 instanceof IkeSessionStateMachine.CreateIkeLocalIkeInit); 4723 } 4724 4725 @Test testIkeInitSchedulesRekey()4726 public void testIkeInitSchedulesRekey() throws Exception { 4727 setupFirstIkeSa(); 4728 4729 // Send IKE INIT request 4730 mIkeSessionStateMachine.sendMessage(IkeSessionStateMachine.CMD_LOCAL_REQUEST_CREATE_IKE); 4731 4732 // Receive IKE INIT response 4733 ReceivedIkePacket dummyReceivedIkePacket = makeIkeInitResponse(); 4734 mIkeSessionStateMachine.sendMessage( 4735 IkeSessionStateMachine.CMD_RECEIVE_IKE_PACKET, dummyReceivedIkePacket); 4736 4737 // Mock IKE AUTH and transition to Idle 4738 mIkeSessionStateMachine.sendMessage( 4739 IkeSessionStateMachine.CMD_FORCE_TRANSITION, mIkeSessionStateMachine.mIdle); 4740 mLooper.dispatchAll(); 4741 mIkeSessionStateMachine.mSaProposal = buildSaProposal(); 4742 4743 // Move time forward to trigger rekey 4744 mLooper.moveTimeForward( 4745 mIkeSessionStateMachine.mIkeSessionParams.getSoftLifetimeMsInternal()); 4746 mLooper.dispatchAll(); 4747 4748 assertTrue( 4749 mIkeSessionStateMachine.getCurrentState() 4750 instanceof IkeSessionStateMachine.RekeyIkeLocalCreate); 4751 } 4752 4753 @Test testRekeyCreateIkeSchedulesRekey()4754 public void testRekeyCreateIkeSchedulesRekey() throws Exception { 4755 setupIdleStateMachine(); 4756 4757 // Send Rekey-Create request 4758 mIkeSessionStateMachine.sendMessage( 4759 IkeSessionStateMachine.CMD_EXECUTE_LOCAL_REQ, 4760 mLocalRequestFactory.getIkeLocalRequest( 4761 IkeSessionStateMachine.CMD_LOCAL_REQUEST_REKEY_IKE)); 4762 mLooper.dispatchAll(); 4763 4764 // Prepare "rekeyed" SA 4765 setupRekeyedIkeSa(mSpyLocalInitIkeSaRecord); 4766 4767 // Receive Rekey response 4768 ReceivedIkePacket dummyRekeyIkeRespReceivedPacket = makeRekeyIkeResponse(); 4769 mIkeSessionStateMachine.sendMessage( 4770 IkeSessionStateMachine.CMD_RECEIVE_IKE_PACKET, dummyRekeyIkeRespReceivedPacket); 4771 mLooper.dispatchAll(); 4772 4773 // Mock rekey delete and transition to Idle 4774 mIkeSessionStateMachine.mCurrentIkeSaRecord = mSpyLocalInitIkeSaRecord; 4775 mIkeSessionStateMachine.sendMessage( 4776 IkeSessionStateMachine.CMD_FORCE_TRANSITION, mIkeSessionStateMachine.mIdle); 4777 mLooper.dispatchAll(); 4778 4779 // Move time forward to trigger rekey 4780 mLooper.moveTimeForward( 4781 mIkeSessionStateMachine.mIkeSessionParams.getSoftLifetimeMsInternal()); 4782 mLooper.dispatchAll(); 4783 4784 assertTrue( 4785 mIkeSessionStateMachine.getCurrentState() 4786 instanceof IkeSessionStateMachine.RekeyIkeLocalCreate); 4787 } 4788 4789 @Test testBuildEncryptedInformationalMessage()4790 public void testBuildEncryptedInformationalMessage() throws Exception { 4791 IkeNotifyPayload payload = new IkeNotifyPayload(ERROR_TYPE_INVALID_SYNTAX, new byte[0]); 4792 4793 boolean isResp = false; 4794 IkeMessage generated = 4795 mIkeSessionStateMachine.buildEncryptedInformationalMessage( 4796 mSpyCurrentIkeSaRecord, new IkeInformationalPayload[] {payload}, isResp, 0); 4797 4798 assertEquals(mSpyCurrentIkeSaRecord.getInitiatorSpi(), generated.ikeHeader.ikeInitiatorSpi); 4799 assertEquals(mSpyCurrentIkeSaRecord.getResponderSpi(), generated.ikeHeader.ikeResponderSpi); 4800 assertEquals( 4801 mSpyCurrentIkeSaRecord.getLocalRequestMessageId(), generated.ikeHeader.messageId); 4802 assertEquals(isResp, generated.ikeHeader.isResponseMsg); 4803 assertEquals(IkePayload.PAYLOAD_TYPE_SK, generated.ikeHeader.nextPayloadType); 4804 4805 List<IkeNotifyPayload> generatedPayloads = 4806 generated.getPayloadListForType( 4807 IkePayload.PAYLOAD_TYPE_NOTIFY, IkeNotifyPayload.class); 4808 assertEquals(1, generatedPayloads.size()); 4809 4810 IkeNotifyPayload generatedPayload = generatedPayloads.get(0); 4811 assertArrayEquals(new byte[0], generatedPayload.notifyData); 4812 assertEquals(ERROR_TYPE_INVALID_SYNTAX, generatedPayload.notifyType); 4813 } 4814 verifyLastSentRespAllPackets(byte[][] expectedPackets, IkeSaRecord saRecord)4815 private void verifyLastSentRespAllPackets(byte[][] expectedPackets, IkeSaRecord saRecord) { 4816 if (expectedPackets == null) { 4817 assertNull(saRecord.getLastSentRespAllPackets()); 4818 return; 4819 } 4820 4821 assertEquals(expectedPackets.length, saRecord.getLastSentRespAllPackets().size()); 4822 for (int i = 0; i < expectedPackets.length; i++) { 4823 assertArrayEquals(expectedPackets[i], saRecord.getLastSentRespAllPackets().get(i)); 4824 } 4825 } 4826 4827 @Test testEncryptedRetransmitterImmediatelySendsRequest()4828 public void testEncryptedRetransmitterImmediatelySendsRequest() throws Exception { 4829 setupIdleStateMachine(); 4830 byte[][] dummyLastRespBytes = 4831 new byte[][] {"testRetransmitterSendsRequestLastResp".getBytes()}; 4832 mSpyCurrentIkeSaRecord.updateLastSentRespAllPackets( 4833 Arrays.asList(dummyLastRespBytes), 4834 mSpyCurrentIkeSaRecord.getRemoteRequestMessageId() - 1); 4835 4836 IkeMessage spyIkeReqMessage = 4837 spy( 4838 new IkeMessage( 4839 new IkeHeader( 4840 mSpyCurrentIkeSaRecord.getInitiatorSpi(), 4841 mSpyCurrentIkeSaRecord.getResponderSpi(), 4842 IkePayload.PAYLOAD_TYPE_SK, 4843 EXCHANGE_TYPE_INFORMATIONAL, 4844 false /*isResp*/, 4845 mSpyCurrentIkeSaRecord.isLocalInit, 4846 mSpyCurrentIkeSaRecord.getLocalRequestMessageId()), 4847 new ArrayList<>())); 4848 4849 // Use something unique as a sentinel value 4850 byte[][] dummyReqBytesList = 4851 new byte[][] { 4852 "testRetransmitterSendsReqFrag1".getBytes(), 4853 "testRetransmitterSendsReqFrag2".getBytes() 4854 }; 4855 4856 doReturn(dummyReqBytesList) 4857 .when(spyIkeReqMessage) 4858 .encryptAndEncode(any(), any(), eq(mSpyCurrentIkeSaRecord), anyBoolean(), anyInt()); 4859 4860 IkeSessionStateMachine.EncryptedRetransmitter retransmitter = 4861 mIkeSessionStateMachine.new EncryptedRetransmitter(spyIkeReqMessage); 4862 4863 // Verify message is sent out, and that request does not change cached retransmit-response 4864 // mLastSentIkeResp. 4865 verify(mMockCurrentIkeSocket).sendIkePacket(eq(dummyReqBytesList[0]), eq(REMOTE_ADDRESS)); 4866 verify(mMockCurrentIkeSocket).sendIkePacket(eq(dummyReqBytesList[1]), eq(REMOTE_ADDRESS)); 4867 verifyLastSentRespAllPackets(dummyLastRespBytes, mSpyCurrentIkeSaRecord); 4868 } 4869 4870 @Test testRetransmittedPacketsAreIdentical()4871 public void testRetransmittedPacketsAreIdentical() throws Exception { 4872 setupIdleStateMachine(); 4873 4874 IkeMessage mockIkeReqMsg = mock(IkeMessage.class); 4875 byte[][] dummyReqBytesList = 4876 new byte[][] {"testRetransmittedPacketsAreIdentical".getBytes()}; 4877 doReturn(dummyReqBytesList) 4878 .when(mockIkeReqMsg) 4879 .encryptAndEncode(any(), any(), eq(mSpyCurrentIkeSaRecord), anyBoolean(), anyInt()); 4880 4881 IkeSessionStateMachine.EncryptedRetransmitter retransmitter = 4882 mIkeSessionStateMachine.new EncryptedRetransmitter(mockIkeReqMsg); 4883 4884 // Packet is immediately sent out 4885 verify(mMockCurrentIkeSocket).sendIkePacket(eq(dummyReqBytesList[0]), eq(REMOTE_ADDRESS)); 4886 verify(mockIkeReqMsg) 4887 .encryptAndEncode(any(), any(), eq(mSpyCurrentIkeSaRecord), anyBoolean(), anyInt()); 4888 4889 // Retransmit packet 4890 retransmitter.retransmit(); 4891 verify(mMockCurrentIkeSocket, times(2)) 4892 .sendIkePacket(eq(dummyReqBytesList[0]), eq(REMOTE_ADDRESS)); 4893 verify(mockIkeReqMsg) 4894 .encryptAndEncode(any(), any(), eq(mSpyCurrentIkeSaRecord), anyBoolean(), anyInt()); 4895 } 4896 4897 // TODO: b/141275871 Test retransmisstions are fired for correct times within certain time. 4898 4899 @Test testCacheLastRequestAndResponse()4900 public void testCacheLastRequestAndResponse() throws Exception { 4901 setupIdleStateMachine(); 4902 mSpyCurrentIkeSaRecord.updateLastReceivedReqFirstPacket(null /*reqPacket*/); 4903 mSpyCurrentIkeSaRecord.updateLastSentRespAllPackets( 4904 null /*respPacketList*/, mSpyCurrentIkeSaRecord.getRemoteRequestMessageId() - 1); 4905 4906 byte[] dummyIkeReqFirstPacket = "testLastSentRequest".getBytes(); 4907 byte[][] dummyIkeResp = 4908 new byte[][] { 4909 "testLastSentRespFrag1".getBytes(), "testLastSentRespFrag2".getBytes() 4910 }; 4911 4912 doReturn(dummyIkeResp) 4913 .when(mMockIkeMessageHelper) 4914 .encryptAndEncode( 4915 any(), 4916 any(), 4917 eq(mSpyCurrentIkeSaRecord), 4918 any(IkeMessage.class), 4919 anyBoolean(), 4920 anyInt()); 4921 4922 // Receive a DPD request, expect to send dummyIkeResp 4923 ReceivedIkePacket dummyDpdRequest = 4924 makeDpdIkeRequest( 4925 mSpyCurrentIkeSaRecord.getRemoteRequestMessageId(), dummyIkeReqFirstPacket); 4926 mIkeSessionStateMachine.sendMessage( 4927 IkeSessionStateMachine.CMD_RECEIVE_IKE_PACKET, dummyDpdRequest); 4928 mLooper.dispatchAll(); 4929 4930 verify(mMockCurrentIkeSocket).sendIkePacket(eq(dummyIkeResp[0]), eq(REMOTE_ADDRESS)); 4931 verify(mMockCurrentIkeSocket).sendIkePacket(eq(dummyIkeResp[1]), eq(REMOTE_ADDRESS)); 4932 4933 verifyLastSentRespAllPackets(dummyIkeResp, mSpyCurrentIkeSaRecord); 4934 assertTrue(mSpyCurrentIkeSaRecord.isRetransmittedRequest(dummyIkeReqFirstPacket)); 4935 4936 assertTrue( 4937 mIkeSessionStateMachine.getCurrentState() instanceof IkeSessionStateMachine.Idle); 4938 } 4939 4940 @Test testReplyRetransmittedRequest()4941 public void testReplyRetransmittedRequest() throws Exception { 4942 setupIdleStateMachine(); 4943 4944 // Mock last sent request and response 4945 byte[] dummyIkeReqFirstPacket = "testRcvRetransmittedRequestReq".getBytes(); 4946 byte[][] dummyIkeResp = new byte[][] {"testRcvRetransmittedRequestResp".getBytes()}; 4947 4948 mSpyCurrentIkeSaRecord.updateLastReceivedReqFirstPacket(dummyIkeReqFirstPacket); 4949 mSpyCurrentIkeSaRecord.updateLastSentRespAllPackets( 4950 Arrays.asList(dummyIkeResp), 4951 mSpyCurrentIkeSaRecord.getRemoteRequestMessageId() - 1); 4952 4953 // Build request with last validated message ID 4954 ReceivedIkePacket request = 4955 makeDpdIkeRequest( 4956 mSpyCurrentIkeSaRecord.getRemoteRequestMessageId() - 1, 4957 dummyIkeReqFirstPacket); 4958 4959 mIkeSessionStateMachine.sendMessage(IkeSessionStateMachine.CMD_RECEIVE_IKE_PACKET, request); 4960 4961 mLooper.dispatchAll(); 4962 4963 verifyLastSentRespAllPackets(dummyIkeResp, mSpyCurrentIkeSaRecord); 4964 verify(mMockCurrentIkeSocket).sendIkePacket(eq(dummyIkeResp[0]), eq(REMOTE_ADDRESS)); 4965 4966 assertTrue( 4967 mIkeSessionStateMachine.getCurrentState() instanceof IkeSessionStateMachine.Idle); 4968 } 4969 4970 @Test testDiscardFakeRetransmittedRequest()4971 public void testDiscardFakeRetransmittedRequest() throws Exception { 4972 setupIdleStateMachine(); 4973 4974 // Mock last sent request and response 4975 byte[] dummyIkeReqFirstPacket = "testDiscardFakeRetransmittedRequestReq".getBytes(); 4976 byte[][] dummyIkeResp = new byte[][] {"testDiscardFakeRetransmittedRequestResp".getBytes()}; 4977 mSpyCurrentIkeSaRecord.updateLastReceivedReqFirstPacket(dummyIkeReqFirstPacket); 4978 mSpyCurrentIkeSaRecord.updateLastSentRespAllPackets( 4979 Arrays.asList(dummyIkeResp), 4980 mSpyCurrentIkeSaRecord.getRemoteRequestMessageId() - 1); 4981 4982 // Build request with last validated message ID but different bytes 4983 ReceivedIkePacket request = 4984 makeDpdIkeRequest( 4985 mSpyCurrentIkeSaRecord.getRemoteRequestMessageId() - 1, new byte[0]); 4986 4987 mIkeSessionStateMachine.sendMessage(IkeSessionStateMachine.CMD_RECEIVE_IKE_PACKET, request); 4988 4989 mLooper.dispatchAll(); 4990 4991 verifyLastSentRespAllPackets(dummyIkeResp, mSpyCurrentIkeSaRecord); 4992 verify(mMockCurrentIkeSocket, never()).sendIkePacket(any(), any()); 4993 4994 assertTrue( 4995 mIkeSessionStateMachine.getCurrentState() instanceof IkeSessionStateMachine.Idle); 4996 } 4997 4998 @Test testRcvRetransmittedRequestBeforeReplyOriginalRequest()4999 public void testRcvRetransmittedRequestBeforeReplyOriginalRequest() throws Exception { 5000 setupIdleStateMachine(); 5001 5002 // Mock last sent response 5003 byte[][] dummyIkeResp = new byte[][] {"testLastSentResponse".getBytes()}; 5004 mSpyCurrentIkeSaRecord.updateLastSentRespAllPackets( 5005 Arrays.asList(dummyIkeResp), 5006 mSpyCurrentIkeSaRecord.getRemoteRequestMessageId() - 1); 5007 5008 // Send request with next message ID 5009 IkeDeletePayload[] inboundDelPayloads = 5010 new IkeDeletePayload[] {new IkeDeletePayload(new int[] {CHILD_SPI_REMOTE})}; 5011 ReceivedIkePacket request = makeDeleteChildPacket(inboundDelPayloads, false /*isResp*/); 5012 mIkeSessionStateMachine.sendMessage(IkeSessionStateMachine.CMD_RECEIVE_IKE_PACKET, request); 5013 mLooper.dispatchAll(); 5014 5015 // Verify that no response has been sent out since we didn't configure Child Session to 5016 // respond 5017 verify(mMockCurrentIkeSocket, never()).sendIkePacket(any(), any()); 5018 assertTrue( 5019 mIkeSessionStateMachine.getCurrentState() 5020 instanceof IkeSessionStateMachine.ChildProcedureOngoing); 5021 5022 // Retransmit the request 5023 mIkeSessionStateMachine.sendMessage(IkeSessionStateMachine.CMD_RECEIVE_IKE_PACKET, request); 5024 mLooper.dispatchAll(); 5025 5026 // Verify that no response has been sent out and state machine is still in 5027 // ChildProcedureOngoing 5028 verify(mMockCurrentIkeSocket, never()).sendIkePacket(any(), any()); 5029 assertTrue( 5030 mIkeSessionStateMachine.getCurrentState() 5031 instanceof IkeSessionStateMachine.ChildProcedureOngoing); 5032 } 5033 5034 @Test testDiscardRetransmittedResponse()5035 public void testDiscardRetransmittedResponse() throws Exception { 5036 new IkeFirstAuthTestPretest().mockIkeInitAndTransitionToIkeAuth(); 5037 verifyRetransmissionStarted(); 5038 5039 // Build and send fake response with last validated message ID to IKE state machine 5040 ReceivedIkePacket resp = 5041 makeDummyEncryptedReceivedIkePacketWithPayloadList( 5042 mSpyCurrentIkeSaRecord, 5043 IkeHeader.EXCHANGE_TYPE_IKE_SA_INIT, 5044 true /*isResp*/, 5045 mSpyCurrentIkeSaRecord.getLocalRequestMessageId() - 1, 5046 new ArrayList<>(), 5047 new byte[0]); 5048 5049 mIkeSessionStateMachine.sendMessage(IkeSessionStateMachine.CMD_RECEIVE_IKE_PACKET, resp); 5050 mLooper.dispatchAll(); 5051 5052 // Verify current state does not change 5053 verifyRetransmissionStarted(); 5054 assertTrue( 5055 mIkeSessionStateMachine.getCurrentState() 5056 instanceof IkeSessionStateMachine.CreateIkeLocalIkeAuth); 5057 } 5058 5059 @Test testDeleteIkeLocalDeleteRequest()5060 public void testDeleteIkeLocalDeleteRequest() throws Exception { 5061 setupIdleStateMachine(); 5062 5063 mIkeSessionStateMachine.sendMessage( 5064 IkeSessionStateMachine.CMD_EXECUTE_LOCAL_REQ, 5065 mLocalRequestFactory.getIkeLocalRequest( 5066 IkeSessionStateMachine.CMD_LOCAL_REQUEST_DELETE_IKE)); 5067 mLooper.dispatchAll(); 5068 verifyRetransmissionStarted(); 5069 5070 // Verify outbound message 5071 IkeMessage delMsg = verifyEncryptAndEncodeAndGetMessage(mSpyCurrentIkeSaRecord); 5072 5073 IkeHeader ikeHeader = delMsg.ikeHeader; 5074 assertEquals(IkePayload.PAYLOAD_TYPE_SK, ikeHeader.nextPayloadType); 5075 assertEquals(IkeHeader.EXCHANGE_TYPE_INFORMATIONAL, ikeHeader.exchangeType); 5076 assertFalse(ikeHeader.isResponseMsg); 5077 assertTrue(ikeHeader.fromIkeInitiator); 5078 5079 List<IkeDeletePayload> deletePayloadList = 5080 delMsg.getPayloadListForType( 5081 IkePayload.PAYLOAD_TYPE_DELETE, IkeDeletePayload.class); 5082 assertEquals(1, deletePayloadList.size()); 5083 5084 IkeDeletePayload deletePayload = deletePayloadList.get(0); 5085 assertEquals(IkePayload.PROTOCOL_ID_IKE, deletePayload.protocolId); 5086 assertEquals(0, deletePayload.numSpi); 5087 assertEquals(0, deletePayload.spiSize); 5088 assertArrayEquals(new int[0], deletePayload.spisToDelete); 5089 } 5090 5091 @Test testDeleteIkeLocalDeleteResponse()5092 public void testDeleteIkeLocalDeleteResponse() throws Exception { 5093 setupIdleStateMachine(); 5094 5095 mIkeSessionStateMachine.sendMessage( 5096 IkeSessionStateMachine.CMD_EXECUTE_LOCAL_REQ, 5097 mLocalRequestFactory.getIkeLocalRequest( 5098 IkeSessionStateMachine.CMD_LOCAL_REQUEST_DELETE_IKE)); 5099 mLooper.dispatchAll(); 5100 verifyRetransmissionStarted(); 5101 5102 ReceivedIkePacket received = makeDeleteIkeResponse(mSpyCurrentIkeSaRecord); 5103 mIkeSessionStateMachine.sendMessage( 5104 IkeSessionStateMachine.CMD_RECEIVE_IKE_PACKET, received); 5105 mLooper.dispatchAll(); 5106 verifyIncrementLocaReqMsgId(); 5107 5108 verifyNotifyUserCloseSession(); 5109 5110 // Verify state machine quit properly 5111 assertNull(mIkeSessionStateMachine.getCurrentState()); 5112 } 5113 5114 @Test testDeleteIkeLocalDeleteResponseWithParsingError()5115 public void testDeleteIkeLocalDeleteResponseWithParsingError() throws Exception { 5116 setupIdleStateMachine(); 5117 5118 mIkeSessionStateMachine.sendMessage( 5119 IkeSessionStateMachine.CMD_EXECUTE_LOCAL_REQ, 5120 mLocalRequestFactory.getIkeLocalRequest( 5121 IkeSessionStateMachine.CMD_LOCAL_REQUEST_DELETE_IKE)); 5122 mLooper.dispatchAll(); 5123 verifyRetransmissionStarted(); 5124 resetMockIkeMessageHelper(); 5125 5126 // Mock receiving response with syntax error 5127 ReceivedIkePacket mockInvalidPacket = 5128 makeDummyReceivedIkePacketWithInvalidSyntax( 5129 mSpyCurrentIkeSaRecord, 5130 true /*isResp*/, 5131 IkeHeader.EXCHANGE_TYPE_INFORMATIONAL); 5132 mIkeSessionStateMachine.sendMessage(CMD_RECEIVE_IKE_PACKET, mockInvalidPacket); 5133 mLooper.dispatchAll(); 5134 5135 // Verify no more request out 5136 verifyEncryptAndEncodeNeverCalled(mSpyCurrentIkeSaRecord); 5137 5138 // Verify state machine quit properly 5139 verify(mMockIkeSessionCallback).onClosedWithException(any(InvalidSyntaxException.class)); 5140 assertNull(mIkeSessionStateMachine.getCurrentState()); 5141 } 5142 5143 @Test testDeleteIkeLocalDeleteHandlesInvalidResp()5144 public void testDeleteIkeLocalDeleteHandlesInvalidResp() throws Exception { 5145 setupIdleStateMachine(); 5146 5147 // Send delete request 5148 mIkeSessionStateMachine.sendMessage( 5149 IkeSessionStateMachine.CMD_EXECUTE_LOCAL_REQ, 5150 mLocalRequestFactory.getIkeLocalRequest( 5151 IkeSessionStateMachine.CMD_LOCAL_REQUEST_DELETE_IKE)); 5152 mLooper.dispatchAll(); 5153 5154 // Receive response with wrong exchange type 5155 ReceivedIkePacket resp = 5156 makeDummyReceivedIkePacketWithInvalidSyntax( 5157 mSpyCurrentIkeSaRecord, 5158 true /*isResp*/, 5159 IkeHeader.EXCHANGE_TYPE_CREATE_CHILD_SA); 5160 mIkeSessionStateMachine.sendMessage(CMD_RECEIVE_IKE_PACKET, resp); 5161 mLooper.dispatchAll(); 5162 5163 // Verify state machine quit properly 5164 verify(mMockIkeSessionCallback).onClosedWithException(any(InvalidSyntaxException.class)); 5165 assertNull(mIkeSessionStateMachine.getCurrentState()); 5166 } 5167 5168 @Test testDeleteIkeLocalDeleteReceivedNonDeleteRequest()5169 public void testDeleteIkeLocalDeleteReceivedNonDeleteRequest() throws Exception { 5170 setupIdleStateMachine(); 5171 5172 mIkeSessionStateMachine.sendMessage( 5173 IkeSessionStateMachine.CMD_EXECUTE_LOCAL_REQ, 5174 mLocalRequestFactory.getIkeLocalRequest( 5175 IkeSessionStateMachine.CMD_LOCAL_REQUEST_DELETE_IKE)); 5176 mLooper.dispatchAll(); 5177 verifyRetransmissionStarted(); 5178 5179 // Verify delete sent out. 5180 verifyEncryptAndEncodeAndGetMessage(mSpyCurrentIkeSaRecord); 5181 5182 resetMockIkeMessageHelper(); // Discard value. 5183 5184 ReceivedIkePacket received = makeRekeyIkeRequest(); 5185 mIkeSessionStateMachine.sendMessage( 5186 IkeSessionStateMachine.CMD_RECEIVE_IKE_PACKET, received); 5187 5188 mLooper.dispatchAll(); 5189 verifyRetransmissionStarted(); 5190 verifyIncrementRemoteReqMsgId(); 5191 5192 verifySendTempFailResponse(); 5193 } 5194 verifySendTempFailResponse()5195 private void verifySendTempFailResponse() { 5196 IkeMessage resp = verifyEncryptAndEncodeAndGetMessage(mSpyCurrentIkeSaRecord); 5197 5198 IkeHeader ikeHeader = resp.ikeHeader; 5199 assertEquals(IkePayload.PAYLOAD_TYPE_SK, ikeHeader.nextPayloadType); 5200 assertEquals(IkeHeader.EXCHANGE_TYPE_INFORMATIONAL, ikeHeader.exchangeType); 5201 assertTrue(ikeHeader.isResponseMsg); 5202 assertEquals(mSpyCurrentIkeSaRecord.isLocalInit, ikeHeader.fromIkeInitiator); 5203 5204 List<IkeNotifyPayload> notificationPayloadList = 5205 resp.getPayloadListForType(IkePayload.PAYLOAD_TYPE_NOTIFY, IkeNotifyPayload.class); 5206 assertEquals(1, notificationPayloadList.size()); 5207 5208 IkeNotifyPayload notifyPayload = notificationPayloadList.get(0); 5209 assertEquals(IkeProtocolException.ERROR_TYPE_TEMPORARY_FAILURE, notifyPayload.notifyType); 5210 } 5211 5212 @Test testDeleteIkeRemoteDelete()5213 public void testDeleteIkeRemoteDelete() throws Exception { 5214 setupIdleStateMachine(); 5215 5216 verifyIkeDeleteRequestHandled(); 5217 } 5218 verifyIkeDeleteRequestHandled()5219 private void verifyIkeDeleteRequestHandled() throws Exception { 5220 mIkeSessionStateMachine.sendMessage( 5221 IkeSessionStateMachine.CMD_RECEIVE_IKE_PACKET, 5222 makeDeleteIkeRequest(mSpyCurrentIkeSaRecord)); 5223 5224 mLooper.dispatchAll(); 5225 verifyIncrementRemoteReqMsgId(); 5226 5227 // Verify outbound message 5228 IkeMessage delMsg = verifyEncryptAndEncodeAndGetMessage(mSpyCurrentIkeSaRecord); 5229 5230 IkeHeader ikeHeader = delMsg.ikeHeader; 5231 assertEquals(IkePayload.PAYLOAD_TYPE_SK, ikeHeader.nextPayloadType); 5232 assertEquals(IkeHeader.EXCHANGE_TYPE_INFORMATIONAL, ikeHeader.exchangeType); 5233 assertTrue(ikeHeader.isResponseMsg); 5234 assertEquals(mSpyCurrentIkeSaRecord.isLocalInit, ikeHeader.fromIkeInitiator); 5235 5236 assertTrue(delMsg.ikePayloadList.isEmpty()); 5237 5238 verifyNotifyUserCloseSession(); 5239 5240 // Verify state machine quit properly 5241 assertNull(mIkeSessionStateMachine.getCurrentState()); 5242 } 5243 verifySessionKilled(boolean hasDeleteRequestSent)5244 private void verifySessionKilled(boolean hasDeleteRequestSent) { 5245 verifySessionKilledWithException(hasDeleteRequestSent, null); 5246 } 5247 verifySessionKilledWithException( boolean hasDeleteRequestSent, Exception exception)5248 private void verifySessionKilledWithException( 5249 boolean hasDeleteRequestSent, Exception exception) { 5250 verify(mSpyCurrentIkeSaRecord).close(); 5251 verify(mMockCurrentIkeSocket).unregisterIke(mSpyCurrentIkeSaRecord.getInitiatorSpi()); 5252 5253 if (exception != null) { 5254 verifyNotifyUserCloseSessionWithException(exception); 5255 } else { 5256 verifyNotifyUserCloseSession(); 5257 } 5258 5259 if (hasDeleteRequestSent) { 5260 // Verify outbound request 5261 IkeMessage req = verifyEncryptAndEncodeAndGetMessage(mSpyCurrentIkeSaRecord); 5262 IkeHeader ikeHeader = req.ikeHeader; 5263 assertEquals(IkePayload.PAYLOAD_TYPE_SK, ikeHeader.nextPayloadType); 5264 assertEquals(IkeHeader.EXCHANGE_TYPE_INFORMATIONAL, ikeHeader.exchangeType); 5265 assertFalse(ikeHeader.isResponseMsg); 5266 assertEquals(1, req.ikePayloadList.size()); 5267 assertEquals(IkePayload.PAYLOAD_TYPE_DELETE, req.ikePayloadList.get(0).payloadType); 5268 } else { 5269 // Verify no outbound request 5270 verifyEncryptAndEncodeNeverCalled(); 5271 } 5272 5273 // Verify state machine quit properly 5274 assertNull(mIkeSessionStateMachine.getCurrentState()); 5275 verify(mMockBusyWakelock).release(); 5276 } 5277 5278 @Test testKillSessionDeleteIkeRequestSent()5279 public void testKillSessionDeleteIkeRequestSent() throws Exception { 5280 setupIdleStateMachine(); 5281 5282 mIkeSessionStateMachine.killSession(); 5283 mLooper.dispatchAll(); 5284 5285 verifySessionKilled(true /* hasDeleteRequestSent */); 5286 } 5287 5288 @Test testKillSessionNoDeleteIkeRequestSent()5289 public void testKillSessionNoDeleteIkeRequestSent() throws Exception { 5290 setupIdleStateMachine(); 5291 5292 // Transition to state that does not send IKE delete requests 5293 InitialSetupData initialSetupData = 5294 new InitialSetupData( 5295 mChildSessionParams, 5296 mMockChildSessionCallback, 5297 SaProposal.DH_GROUP_1024_BIT_MODP); 5298 mIkeSessionStateMachine.mCreateIkeLocalIkeInit.setIkeSetupData(initialSetupData); 5299 mIkeSessionStateMachine.sendMessage( 5300 IkeSessionStateMachine.CMD_FORCE_TRANSITION, 5301 mIkeSessionStateMachine.mCreateIkeLocalIkeInit); 5302 mLooper.dispatchAll(); 5303 5304 mIkeSessionStateMachine.killSession(); 5305 mLooper.dispatchAll(); 5306 5307 verifySessionKilled(false /* hasDeleteRequestSent */); 5308 } 5309 5310 @Test testOnFatalIkeSessionErrorFromChild()5311 public void testOnFatalIkeSessionErrorFromChild() throws Exception { 5312 setupIdleStateMachine(); 5313 5314 transitionToChildProcedureOngoing(); 5315 5316 Exception exception = new IkeInternalException("IkeStateMachineTest"); 5317 mDummyChildSmCallback.onFatalIkeSessionError(exception); 5318 mLooper.dispatchAll(); 5319 5320 verifySessionKilledWithException(false /* hasDeleteRequestSent */, exception); 5321 } 5322 5323 @Test testScheduleDpd()5324 public void testScheduleDpd() throws Exception { 5325 setupIdleStateMachine(); 5326 5327 ArgumentCaptor<IkeAlarmConfig> captor = ArgumentCaptor.forClass(IkeAlarmConfig.class); 5328 verify(mSpyDeps).newExactAndAllowWhileIdleAlarm(captor.capture()); 5329 assertEquals( 5330 TimeUnit.SECONDS.toMillis( 5331 mIkeSessionStateMachine.mIkeSessionParams.getDpdDelaySeconds()), 5332 captor.getValue().delayMs); 5333 } 5334 5335 @Test testDisableDpd()5336 public void testDisableDpd() throws Exception { 5337 mIkeSessionStateMachine.quitNow(); 5338 mLooper.dispatchAll(); 5339 5340 // Clear the wakelock call in quitNow() for setupIdleStateMachine() to pass 5341 reset(mMockBusyWakelock); 5342 5343 // Restart IKE Session with DPD disabled 5344 IkeSessionParams ikeSessionParams = 5345 buildIkeSessionParamsCommon() 5346 .setAuthPsk(mPsk) 5347 .setDpdDelaySeconds(Integer.MAX_VALUE) 5348 .build(); 5349 mIkeSessionStateMachine = makeAndStartIkeSession(ikeSessionParams); 5350 setupIdleStateMachine(); 5351 5352 verify(mSpyDeps, never()).newExactAndAllowWhileIdleAlarm(any()); 5353 } 5354 verifyAndGetOutboundEncryptedResp(int exchangeType)5355 private IkeMessage verifyAndGetOutboundEncryptedResp(int exchangeType) { 5356 IkeMessage resp = verifyEncryptAndEncodeAndGetMessage(mSpyCurrentIkeSaRecord); 5357 IkeHeader ikeHeader = resp.ikeHeader; 5358 assertEquals(IkePayload.PAYLOAD_TYPE_SK, ikeHeader.nextPayloadType); 5359 assertEquals(exchangeType, ikeHeader.exchangeType); 5360 assertTrue(ikeHeader.isResponseMsg); 5361 assertEquals(mSpyCurrentIkeSaRecord.isLocalInit, ikeHeader.fromIkeInitiator); 5362 return resp; 5363 } 5364 verifyAndGetOutboundInformationalResp()5365 private IkeMessage verifyAndGetOutboundInformationalResp() { 5366 return verifyAndGetOutboundEncryptedResp(IkeHeader.EXCHANGE_TYPE_INFORMATIONAL); 5367 } 5368 5369 @Test testReceiveDpd()5370 public void testReceiveDpd() throws Exception { 5371 setupIdleStateMachine(); 5372 5373 // Receive a DPD request, expect to stay in IDLE state 5374 ReceivedIkePacket dummyDpdRequest = makeDpdIkeRequest(mSpyCurrentIkeSaRecord); 5375 mIkeSessionStateMachine.sendMessage( 5376 IkeSessionStateMachine.CMD_RECEIVE_IKE_PACKET, dummyDpdRequest); 5377 mLooper.dispatchAll(); 5378 assertTrue( 5379 mIkeSessionStateMachine.getCurrentState() instanceof IkeSessionStateMachine.Idle); 5380 5381 verifyDecodeEncryptedMessage(mSpyCurrentIkeSaRecord, dummyDpdRequest); 5382 5383 // Verify outbound response 5384 IkeMessage resp = verifyAndGetOutboundInformationalResp(); 5385 assertTrue(resp.ikePayloadList.isEmpty()); 5386 } 5387 5388 @Test testReceiveDpdNonIdle()5389 public void testReceiveDpdNonIdle() throws Exception { 5390 setupIdleStateMachine(); 5391 5392 // Move to a non-idle state. Use RekeyIkeRemoteDelete, as it doesn't send out any requests. 5393 mIkeSessionStateMachine.sendMessage( 5394 IkeSessionStateMachine.CMD_FORCE_TRANSITION, 5395 mIkeSessionStateMachine.mRekeyIkeRemoteDelete); 5396 mLooper.dispatchAll(); 5397 5398 // In a rekey state, receiving (and handling) a DPD should not result in a change of states 5399 ReceivedIkePacket dummyDpdRequest = makeDpdIkeRequest(mSpyCurrentIkeSaRecord); 5400 mIkeSessionStateMachine.sendMessage( 5401 IkeSessionStateMachine.CMD_RECEIVE_IKE_PACKET, dummyDpdRequest); 5402 mLooper.dispatchAll(); 5403 assertTrue( 5404 mIkeSessionStateMachine.getCurrentState() 5405 instanceof IkeSessionStateMachine.RekeyIkeRemoteDelete); 5406 5407 verifyDecodeEncryptedMessage(mSpyCurrentIkeSaRecord, dummyDpdRequest); 5408 5409 // Verify outbound response 5410 IkeMessage resp = verifyAndGetOutboundInformationalResp(); 5411 assertTrue(resp.ikePayloadList.isEmpty()); 5412 } 5413 executeAndVerifySendLocalDPD()5414 private void executeAndVerifySendLocalDPD() throws Exception { 5415 setupIdleStateMachine(); 5416 5417 mIkeSessionStateMachine.sendMessage( 5418 CMD_FORCE_TRANSITION, mIkeSessionStateMachine.mDpdIkeLocalInfo); 5419 mLooper.dispatchAll(); 5420 5421 verifyEmptyInformationalSent(1, false /* expectedResp*/); 5422 resetMockIkeMessageHelper(); 5423 } 5424 5425 @Test testDpdIkeLocalInfoRcvDpdReq()5426 public void testDpdIkeLocalInfoRcvDpdReq() throws Exception { 5427 executeAndVerifySendLocalDPD(); 5428 mIkeSessionStateMachine.sendMessage( 5429 CMD_RECEIVE_IKE_PACKET, makeDpdIkeRequest(mSpyCurrentIkeSaRecord)); 5430 mLooper.dispatchAll(); 5431 5432 verifyEmptyInformationalSent(1, true /* expectedResp*/); 5433 assertTrue( 5434 mIkeSessionStateMachine.getCurrentState() 5435 instanceof IkeSessionStateMachine.DpdIkeLocalInfo); 5436 } 5437 5438 @Test testDpdIkeLocalInfoRcvDeleteIkeReq()5439 public void testDpdIkeLocalInfoRcvDeleteIkeReq() throws Exception { 5440 executeAndVerifySendLocalDPD(); 5441 mIkeSessionStateMachine.sendMessage( 5442 CMD_RECEIVE_IKE_PACKET, makeDeleteIkeRequest(mSpyCurrentIkeSaRecord)); 5443 mLooper.dispatchAll(); 5444 5445 verifyEmptyInformationalSent(1, true /* expectedResp*/); 5446 assertNull(mIkeSessionStateMachine.getCurrentState()); 5447 } 5448 5449 @Test testDpdIkeLocalInfoRcvRekeyIkeReq()5450 public void testDpdIkeLocalInfoRcvRekeyIkeReq() throws Exception { 5451 executeAndVerifySendLocalDPD(); 5452 mIkeSessionStateMachine.sendMessage(CMD_RECEIVE_IKE_PACKET, makeRekeyIkeRequest()); 5453 mLooper.dispatchAll(); 5454 5455 verifySendTempFailResponse(); 5456 assertTrue( 5457 mIkeSessionStateMachine.getCurrentState() 5458 instanceof IkeSessionStateMachine.DpdIkeLocalInfo); 5459 } 5460 5461 @Test testIdleTriggersNewRequests()5462 public void testIdleTriggersNewRequests() throws Exception { 5463 setupIdleStateMachine(); 5464 5465 mIkeSessionStateMachine.sendMessage( 5466 IkeSessionStateMachine.CMD_EXECUTE_LOCAL_REQ, 5467 mLocalRequestFactory.getIkeLocalRequest( 5468 IkeSessionStateMachine.CMD_LOCAL_REQUEST_REKEY_IKE)); 5469 mLooper.dispatchAll(); 5470 5471 // Verify that the command is executed, and the state machine transitions to the right state 5472 assertTrue( 5473 mIkeSessionStateMachine.getCurrentState() 5474 instanceof IkeSessionStateMachine.RekeyIkeLocalCreate); 5475 verifyRetransmissionStarted(); 5476 } 5477 5478 @Test testNonIdleStateDoesNotTriggerNewRequests()5479 public void testNonIdleStateDoesNotTriggerNewRequests() throws Exception { 5480 setupIdleStateMachine(); 5481 5482 // Force ourselves into a non-idle state 5483 mIkeSessionStateMachine.sendMessage( 5484 IkeSessionStateMachine.CMD_FORCE_TRANSITION, mIkeSessionStateMachine.mReceiving); 5485 mLooper.dispatchAll(); 5486 verifyEncryptAndEncodeNeverCalled(); 5487 5488 // Queue a local request, and expect that it is not run (yet) 5489 mIkeSessionStateMachine.sendMessage( 5490 IkeSessionStateMachine.CMD_LOCAL_REQUEST_REKEY_IKE, 5491 mLocalRequestFactory.getIkeLocalRequest( 5492 IkeSessionStateMachine.CMD_LOCAL_REQUEST_REKEY_IKE)); 5493 mLooper.dispatchAll(); 5494 5495 // Verify that the state machine is still in the Receiving state 5496 verifyEncryptAndEncodeNeverCalled(); 5497 assertTrue( 5498 mIkeSessionStateMachine.getCurrentState() 5499 instanceof IkeSessionStateMachine.Receiving); 5500 5501 // Go back to Idle, and expect to immediately transition to RekeyIkeLocalCreate from the 5502 // queued request 5503 mIkeSessionStateMachine.sendMessage( 5504 IkeSessionStateMachine.CMD_FORCE_TRANSITION, mIkeSessionStateMachine.mIdle); 5505 mLooper.dispatchAll(); 5506 assertTrue( 5507 mIkeSessionStateMachine.getCurrentState() 5508 instanceof IkeSessionStateMachine.RekeyIkeLocalCreate); 5509 verifyEncryptAndEncodeAndGetMessage(mSpyCurrentIkeSaRecord); 5510 } 5511 5512 @Test testOpenChildSessionValidatesArgs()5513 public void testOpenChildSessionValidatesArgs() throws Exception { 5514 setupIdleStateMachine(); 5515 5516 // Expect failure - no callbacks provided 5517 try { 5518 mIkeSessionStateMachine.openChildSession(mChildSessionParams, null); 5519 fail("Expected to fail due to missing ChildSessionCallback"); 5520 } catch (IllegalArgumentException expected) { 5521 } 5522 5523 // Expect failure - callbacks already registered 5524 try { 5525 mIkeSessionStateMachine.openChildSession( 5526 mChildSessionParams, mMockChildSessionCallback); 5527 fail("Expected to fail due to invalid ChildSessionCallback"); 5528 } catch (IllegalArgumentException expected) { 5529 } 5530 } 5531 5532 @Test testOpenChildSession()5533 public void testOpenChildSession() throws Exception { 5534 setupIdleStateMachine(); 5535 5536 ChildSessionCallback cb = mock(ChildSessionCallback.class); 5537 mIkeSessionStateMachine.openChildSession(mChildSessionParams, cb); 5538 5539 // Test that inserting the same cb returns an error, even before the state 5540 // machine has a chance to process it. 5541 try { 5542 mIkeSessionStateMachine.openChildSession(mChildSessionParams, cb); 5543 fail("Expected to fail due to invalid ChildSessionCallback"); 5544 } catch (IllegalArgumentException expected) { 5545 } 5546 5547 verifyMakeChildAndReturnChildSmCb(cb); 5548 5549 // Verify state in IkeSessionStateMachine 5550 mLooper.dispatchAll(); 5551 assertTrue( 5552 mIkeSessionStateMachine.getCurrentState() 5553 instanceof IkeSessionStateMachine.ChildProcedureOngoing); 5554 5555 synchronized (mIkeSessionStateMachine.mChildCbToSessions) { 5556 assertTrue(mIkeSessionStateMachine.mChildCbToSessions.containsKey(cb)); 5557 } 5558 } 5559 5560 @Test(expected = IllegalArgumentException.class) 5561 @SdkSuppress(minSdkVersion = 31, codeName = "S") testOpenChildSessionWithMobikeAndTransport()5562 public void testOpenChildSessionWithMobikeAndTransport() throws Exception { 5563 mIkeSessionStateMachine = restartStateMachineWithRfcMobikeConfigured(); 5564 5565 mIkeSessionStateMachine.openChildSession( 5566 mock(TransportModeChildSessionParams.class), mock(ChildSessionCallback.class)); 5567 } 5568 5569 @Test testCloseChildSessionValidatesArgs()5570 public void testCloseChildSessionValidatesArgs() throws Exception { 5571 setupIdleStateMachine(); 5572 5573 // Expect failure - callbacks not registered 5574 try { 5575 mIkeSessionStateMachine.closeChildSession(mock(ChildSessionCallback.class)); 5576 fail("Expected to fail since callback is not registered"); 5577 } catch (IllegalArgumentException expected) { 5578 } 5579 } 5580 5581 @Test testCloseChildSession()5582 public void testCloseChildSession() throws Exception { 5583 setupIdleStateMachine(); 5584 5585 mIkeSessionStateMachine.closeChildSession(mMockChildSessionCallback); 5586 mLooper.dispatchAll(); 5587 5588 assertTrue( 5589 mIkeSessionStateMachine.getCurrentState() 5590 instanceof IkeSessionStateMachine.ChildProcedureOngoing); 5591 } 5592 5593 @Test testCloseImmediatelyAfterOpenChildSession()5594 public void testCloseImmediatelyAfterOpenChildSession() throws Exception { 5595 setupIdleStateMachine(); 5596 5597 ChildSessionCallback cb = mock(ChildSessionCallback.class); 5598 mIkeSessionStateMachine.openChildSession(mChildSessionParams, cb); 5599 5600 // Verify that closing the session immediately still picks up the child callback 5601 // even before the looper has a chance to run. 5602 mIkeSessionStateMachine.closeChildSession(mMockChildSessionCallback); 5603 } 5604 5605 @Test testOnChildSessionClosed()5606 public void testOnChildSessionClosed() throws Exception { 5607 setupIdleStateMachine(); 5608 5609 mDummyChildSmCallback.onChildSessionClosed(mMockChildSessionCallback); 5610 5611 synchronized (mIkeSessionStateMachine.mChildCbToSessions) { 5612 assertFalse( 5613 mIkeSessionStateMachine.mChildCbToSessions.containsKey( 5614 mMockChildSessionCallback)); 5615 } 5616 } 5617 5618 @Test testHandleUnexpectedExceptionInEnterState()5619 public void testHandleUnexpectedExceptionInEnterState() throws Exception { 5620 Log spyIkeLog = TestUtils.makeSpyLogDoLogErrorForWtf(TAG); 5621 IkeManager.setIkeLog(spyIkeLog); 5622 5623 IkeSessionParams mockSessionParams = mock(IkeSessionParams.class); 5624 when(mockSessionParams.getServerHostname()).thenReturn(REMOTE_HOSTNAME); 5625 5626 RuntimeException cause = new RuntimeException(); 5627 when(mockSessionParams.getSaProposalsInternal()).thenThrow(cause); 5628 5629 DhGroupTransform dhGroupTransform = new DhGroupTransform(SaProposal.DH_GROUP_2048_BIT_MODP); 5630 IkeSaProposal mockSaProposal = mock(IkeSaProposal.class); 5631 when(mockSaProposal.getDhGroupTransforms()) 5632 .thenReturn(new DhGroupTransform[] {dhGroupTransform}); 5633 when(mockSessionParams.getSaProposals()).thenReturn(Arrays.asList(mockSaProposal)); 5634 5635 mIkeSessionStateMachine.quitNow(); 5636 mIkeSessionStateMachine = makeAndStartIkeSession(mockSessionParams); 5637 5638 // Send IKE INIT request 5639 mIkeSessionStateMachine.sendMessage(IkeSessionStateMachine.CMD_LOCAL_REQUEST_CREATE_IKE); 5640 mLooper.dispatchAll(); 5641 5642 assertNull(mIkeSessionStateMachine.getCurrentState()); 5643 verify(mSpyUserCbExecutor).execute(any(Runnable.class)); 5644 verify(spyIkeLog).wtf(anyString(), anyString(), any(RuntimeException.class)); 5645 5646 ArgumentCaptor<IkeInternalException> internalExceptionCaptor = 5647 ArgumentCaptor.forClass(IkeInternalException.class); 5648 verify(mMockIkeSessionCallback).onClosedWithException(internalExceptionCaptor.capture()); 5649 IkeInternalException internalException = internalExceptionCaptor.getValue(); 5650 5651 // Verify that the Exception which caused the IkeSessionStateMachine to close is the same 5652 // one mocked for IkeSessionParams#getSaProposalsInternal 5653 assertSame(cause, internalException.getCause()); 5654 } 5655 5656 @Test testHandleUnexpectedExceptionInProcessStateMsg()5657 public void testHandleUnexpectedExceptionInProcessStateMsg() throws Exception { 5658 Log spyIkeLog = TestUtils.makeSpyLogDoLogErrorForWtf(TAG); 5659 IkeManager.setIkeLog(spyIkeLog); 5660 5661 setupIdleStateMachine(); 5662 mIkeSessionStateMachine.sendMessage( 5663 IkeSessionStateMachine.CMD_RECEIVE_IKE_PACKET, null /*receivedIkePacket*/); 5664 mLooper.dispatchAll(); 5665 5666 assertNull(mIkeSessionStateMachine.getCurrentState()); 5667 verify(mSpyUserCbExecutor).execute(any(Runnable.class)); 5668 verify(mMockIkeSessionCallback).onClosedWithException(any(IkeInternalException.class)); 5669 verify(spyIkeLog).wtf(anyString(), anyString(), any(RuntimeException.class)); 5670 } 5671 5672 @Test testCreateIkeLocalIkeInitRcvErrorNotify()5673 public void testCreateIkeLocalIkeInitRcvErrorNotify() throws Exception { 5674 // Send IKE INIT request 5675 mIkeSessionStateMachine.sendMessage(IkeSessionStateMachine.CMD_LOCAL_REQUEST_CREATE_IKE); 5676 mLooper.dispatchAll(); 5677 verifyRetransmissionStarted(); 5678 5679 // Receive IKE INIT response with erro notification. 5680 List<IkePayload> payloads = new ArrayList<>(); 5681 payloads.add(new IkeNotifyPayload(IkeProtocolException.ERROR_TYPE_NO_PROPOSAL_CHOSEN)); 5682 ReceivedIkePacket resp = 5683 makeDummyUnencryptedReceivedIkePacket( 5684 1L /*initiator SPI*/, 5685 2L /*respodner SPI*/, 5686 IkeHeader.EXCHANGE_TYPE_IKE_SA_INIT, 5687 true /*isResp*/, 5688 false /*fromIkeInit*/, 5689 payloads); 5690 5691 mIkeSessionStateMachine.sendMessage(IkeSessionStateMachine.CMD_RECEIVE_IKE_PACKET, resp); 5692 mLooper.dispatchAll(); 5693 5694 // Fires user error callbacks 5695 verify(mMockIkeSessionCallback) 5696 .onClosedWithException( 5697 argThat(err -> err instanceof NoValidProposalChosenException)); 5698 // Verify state machine quit properly 5699 assertNull(mIkeSessionStateMachine.getCurrentState()); 5700 } 5701 mockSendRekeyChildReq()5702 private void mockSendRekeyChildReq() throws Exception { 5703 setupIdleStateMachine(); 5704 5705 ChildLocalRequest childLocalRequest = 5706 mLocalRequestFactory.getChildLocalRequest( 5707 IkeSessionStateMachine.CMD_LOCAL_REQUEST_REKEY_CHILD, 5708 mMockChildSessionCallback, 5709 null /*childParams*/); 5710 5711 mIkeSessionStateMachine.sendMessage( 5712 IkeSessionStateMachine.CMD_EXECUTE_LOCAL_REQ, childLocalRequest); 5713 mLooper.dispatchAll(); 5714 5715 assertTrue( 5716 mIkeSessionStateMachine.getCurrentState() 5717 instanceof IkeSessionStateMachine.ChildProcedureOngoing); 5718 verify(mMockChildSessionStateMachine).rekeyChildSession(); 5719 5720 // Mocking sending request 5721 mDummyChildSmCallback.onOutboundPayloadsReady( 5722 IkeHeader.EXCHANGE_TYPE_CREATE_CHILD_SA, 5723 false /*isResp*/, 5724 new ArrayList<>(), 5725 mMockChildSessionStateMachine); 5726 mLooper.dispatchAll(); 5727 } 5728 mockRcvTempFail()5729 private void mockRcvTempFail() throws Exception { 5730 ReceivedIkePacket resp = 5731 makeResponseWithErrorNotify(new IkeNotifyPayload(ERROR_TYPE_TEMPORARY_FAILURE)); 5732 5733 mIkeSessionStateMachine.sendMessage(IkeSessionStateMachine.CMD_RECEIVE_IKE_PACKET, resp); 5734 mIkeSessionStateMachine.sendMessage( 5735 IkeSessionStateMachine.CMD_FORCE_TRANSITION, mIkeSessionStateMachine.mIdle); 5736 mLooper.dispatchAll(); 5737 } 5738 5739 @Ignore disableTestTempFailureHandlerTimeout()5740 public void disableTestTempFailureHandlerTimeout() throws Exception { 5741 long currentTime = 0; 5742 int retryCnt = 0; 5743 5744 mockSendRekeyChildReq(); 5745 5746 while (currentTime + RETRY_INTERVAL_MS < TEMP_FAILURE_RETRY_TIMEOUT_MS) { 5747 mockRcvTempFail(); 5748 5749 mLooper.moveTimeForward(RETRY_INTERVAL_MS); 5750 currentTime += RETRY_INTERVAL_MS; 5751 mLooper.dispatchAll(); 5752 5753 retryCnt++; 5754 verify(mMockChildSessionStateMachine, times(1 + retryCnt)).rekeyChildSession(); 5755 } 5756 5757 mLooper.moveTimeForward(RETRY_INTERVAL_MS); 5758 mLooper.dispatchAll(); 5759 5760 assertNull(mIkeSessionStateMachine.getCurrentState()); 5761 verify(mMockIkeSessionCallback).onClosedWithException(any(IkeInternalException.class)); 5762 } 5763 5764 @Test testTempFailureHandlerCancelTimer()5765 public void testTempFailureHandlerCancelTimer() throws Exception { 5766 mockRescheduleRekey(mSpyCurrentIkeSaRecord); 5767 setupIdleStateMachine(); 5768 5769 // Send Rekey-Create request 5770 mIkeSessionStateMachine.sendMessage( 5771 IkeSessionStateMachine.CMD_EXECUTE_LOCAL_REQ, 5772 mLocalRequestFactory.getIkeLocalRequest( 5773 IkeSessionStateMachine.CMD_LOCAL_REQUEST_REKEY_IKE)); 5774 mLooper.dispatchAll(); 5775 verifyRetransmissionStarted(); 5776 5777 // Mock sending TEMPORARY_FAILURE response 5778 mockRcvTempFail(); 5779 mLooper.dispatchAll(); 5780 verify(mSpyCurrentIkeSaRecord).rescheduleRekey(eq(RETRY_INTERVAL_MS)); 5781 assertTrue( 5782 mIkeSessionStateMachine.getCurrentState() instanceof IkeSessionStateMachine.Idle); 5783 5784 // Move time forward to trigger retry 5785 mLooper.moveTimeForward(IkeSessionStateMachine.RETRY_INTERVAL_MS); 5786 mLooper.dispatchAll(); 5787 assertTrue( 5788 mIkeSessionStateMachine.getCurrentState() 5789 instanceof IkeSessionStateMachine.RekeyIkeLocalCreate); 5790 5791 // Prepare "rekeyed" SA 5792 setupRekeyedIkeSa(mSpyLocalInitIkeSaRecord); 5793 5794 // Receive valid Rekey-Create response 5795 ReceivedIkePacket dummyRekeyIkeRespReceivedPacket = makeRekeyIkeResponse(); 5796 mIkeSessionStateMachine.sendMessage( 5797 IkeSessionStateMachine.CMD_RECEIVE_IKE_PACKET, dummyRekeyIkeRespReceivedPacket); 5798 mLooper.dispatchAll(); 5799 5800 // Receive Delete response 5801 ReceivedIkePacket dummyDeleteIkeRespReceivedPacket = 5802 makeDeleteIkeResponse(mSpyCurrentIkeSaRecord); 5803 mIkeSessionStateMachine.sendMessage( 5804 IkeSessionStateMachine.CMD_RECEIVE_IKE_PACKET, dummyDeleteIkeRespReceivedPacket); 5805 mLooper.dispatchAll(); 5806 assertTrue( 5807 mIkeSessionStateMachine.getCurrentState() instanceof IkeSessionStateMachine.Idle); 5808 5809 // Move time forward 5810 mLooper.moveTimeForward(IkeSessionStateMachine.TEMP_FAILURE_RETRY_TIMEOUT_MS); 5811 mLooper.dispatchAll(); 5812 5813 // Validate IKE Session is not closed 5814 assertTrue( 5815 mIkeSessionStateMachine.getCurrentState() instanceof IkeSessionStateMachine.Idle); 5816 } 5817 5818 @Ignore disableTestIdleReceiveRequestWithFatalError()5819 public void disableTestIdleReceiveRequestWithFatalError() throws Exception { 5820 setupIdleStateMachine(); 5821 5822 // Mock receiving packet with syntax error 5823 ReceivedIkePacket mockInvalidPacket = 5824 makeDummyReceivedIkePacketWithInvalidSyntax( 5825 mSpyCurrentIkeSaRecord, 5826 false /*isResp*/, 5827 IkeHeader.EXCHANGE_TYPE_CREATE_CHILD_SA); 5828 mIkeSessionStateMachine.sendMessage(CMD_RECEIVE_IKE_PACKET, mockInvalidPacket); 5829 mLooper.dispatchAll(); 5830 5831 // Verify Delete request was sent 5832 List<IkePayload> payloads = verifyOutInfoMsgHeaderAndGetPayloads(true /*isResp*/); 5833 assertEquals(1, payloads.size()); 5834 5835 IkePayload payload = payloads.get(0); 5836 assertEquals(IkePayload.PAYLOAD_TYPE_NOTIFY, payload.payloadType); 5837 assertEquals(ERROR_TYPE_INVALID_SYNTAX, ((IkeNotifyPayload) payload).notifyType); 5838 5839 // Verify IKE Session is closed properly 5840 assertNull(mIkeSessionStateMachine.getCurrentState()); 5841 verify(mMockIkeSessionCallback).onClosedWithException(any(InvalidSyntaxException.class)); 5842 } 5843 5844 @Test testHandlesInvalidRequest()5845 public void testHandlesInvalidRequest() throws Exception { 5846 setupIdleStateMachine(); 5847 5848 mIkeSessionStateMachine.sendMessage( 5849 IkeSessionStateMachine.CMD_FORCE_TRANSITION, 5850 mIkeSessionStateMachine.mChildProcedureOngoing); 5851 5852 // Receive an IKE AUTH request 5853 ReceivedIkePacket request = 5854 makeDummyEncryptedReceivedIkePacketWithPayloadList( 5855 mSpyCurrentIkeSaRecord, 5856 IkeHeader.EXCHANGE_TYPE_IKE_AUTH, 5857 false /*isResp*/, 5858 new ArrayList<IkePayload>()); 5859 mIkeSessionStateMachine.sendMessage(IkeSessionStateMachine.CMD_RECEIVE_IKE_PACKET, request); 5860 mLooper.dispatchAll(); 5861 5862 // Verify error notification was sent 5863 List<IkePayload> ikePayloadList = verifyOutInfoMsgHeaderAndGetPayloads(true /*isResp*/); 5864 assertEquals(1, ikePayloadList.size()); 5865 assertEquals( 5866 ERROR_TYPE_INVALID_SYNTAX, ((IkeNotifyPayload) ikePayloadList.get(0)).notifyType); 5867 5868 // Verify IKE Session has quit 5869 assertNull(mIkeSessionStateMachine.getCurrentState()); 5870 verify(mMockIkeSessionCallback).onClosedWithException(any(InvalidSyntaxException.class)); 5871 } 5872 5873 @Test testIdleHandlesDecryptPacketFailed()5874 public void testIdleHandlesDecryptPacketFailed() throws Exception { 5875 setupIdleStateMachine(); 5876 5877 ReceivedIkePacket packet = 5878 makeDummyReceivedIkePacketWithUnprotectedError( 5879 mSpyCurrentIkeSaRecord, 5880 false /*isResp*/, 5881 EXCHANGE_TYPE_INFORMATIONAL, 5882 mock(IkeException.class)); 5883 mIkeSessionStateMachine.sendMessage(IkeSessionStateMachine.CMD_RECEIVE_IKE_PACKET, packet); 5884 mLooper.dispatchAll(); 5885 5886 assertTrue( 5887 mIkeSessionStateMachine.getCurrentState() instanceof IkeSessionStateMachine.Idle); 5888 } 5889 5890 @Test testHandlesUnencryptedPacket()5891 public void testHandlesUnencryptedPacket() throws Exception { 5892 setupIdleStateMachine(); 5893 IkeMessage.setIkeMessageHelper(new IkeMessageHelper()); 5894 5895 ReceivedIkePacket packet = 5896 makeDummyUnencryptedReceivedIkePacket( 5897 mSpyCurrentIkeSaRecord.getLocalSpi(), 5898 mSpyCurrentIkeSaRecord.getRemoteSpi(), 5899 IkeHeader.EXCHANGE_TYPE_INFORMATIONAL, 5900 false /*isResp*/, 5901 false /*fromIkeInit*/, 5902 new ArrayList<>()); 5903 5904 mIkeSessionStateMachine.sendMessage(IkeSessionStateMachine.CMD_RECEIVE_IKE_PACKET, packet); 5905 mLooper.dispatchAll(); 5906 5907 assertTrue( 5908 mIkeSessionStateMachine.getCurrentState() instanceof IkeSessionStateMachine.Idle); 5909 5910 // Reset the IkeMessageHelper to be a mock. This is needed for #killSession (called in 5911 // #tearDown), which attempts to notify the remote about the IKE session dying in the Idle 5912 // state. 5913 IkeMessage.setIkeMessageHelper(mMockIkeMessageHelper); 5914 resetMockIkeMessageHelper(); 5915 } 5916 5917 @Test testEapOnlyOption()5918 public void testEapOnlyOption() throws Exception { 5919 mIkeSessionStateMachine.quitNow(); 5920 IkeSessionParams ikeSessionParams = 5921 buildIkeSessionParamsCommon() 5922 .setAuthEap(mRootCertificate, mEapSessionConfig) 5923 .addIkeOption(IKE_OPTION_EAP_ONLY_AUTH) 5924 .build(); 5925 5926 verifyIkeAuthWithNotifyPayload(ikeSessionParams, NOTIFY_TYPE_EAP_ONLY_AUTHENTICATION); 5927 } 5928 5929 @Test testInitialContact()5930 public void testInitialContact() throws Exception { 5931 mIkeSessionStateMachine.quitNow(); 5932 IkeSessionParams ikeSessionParams = 5933 buildIkeSessionParamsWithIkeOptions(IkeSessionParams.IKE_OPTION_INITIAL_CONTACT); 5934 5935 verifyIkeAuthWithNotifyPayload(ikeSessionParams, NOTIFY_TYPE_INITIAL_CONTACT); 5936 } 5937 verifyIkeAuthWithNotifyPayload( IkeSessionParams ikeSessionParams, int expectedNotifyType)5938 private void verifyIkeAuthWithNotifyPayload( 5939 IkeSessionParams ikeSessionParams, int expectedNotifyType) throws Exception { 5940 mIkeSessionStateMachine.quitNow(); 5941 mIkeSessionStateMachine = makeAndStartIkeSession(ikeSessionParams); 5942 new IkeFirstAuthTestPretest().mockIkeInitAndTransitionToIkeAuth(); 5943 5944 IkeMessage ikeAuthReqMessage = verifyAuthReqAndGetMsg(); 5945 List<IkeNotifyPayload> notifyPayloads = 5946 ikeAuthReqMessage.getPayloadListForType( 5947 IkePayload.PAYLOAD_TYPE_NOTIFY, IkeNotifyPayload.class); 5948 assertTrue(hasExpectedNotifyPayload(notifyPayloads, expectedNotifyType)); 5949 } 5950 makeConfigPayload()5951 private IkeConfigPayload makeConfigPayload() throws Exception { 5952 return (IkeConfigPayload) 5953 IkeTestUtils.hexStringToIkePayload( 5954 IkePayload.PAYLOAD_TYPE_CP, true /*isResp*/, CP_PAYLOAD_HEX_STRING); 5955 } 5956 hasExpectedNotifyPayload( List<IkeNotifyPayload> notifyPayloads, int expectedNotifyType)5957 private boolean hasExpectedNotifyPayload( 5958 List<IkeNotifyPayload> notifyPayloads, int expectedNotifyType) { 5959 for (IkeNotifyPayload payload : notifyPayloads) { 5960 if (payload.notifyType == expectedNotifyType) { 5961 return true; 5962 } 5963 } 5964 5965 return false; 5966 } 5967 5968 @Test testAcquireAndReleaseLocalReqWakeLock()5969 public void testAcquireAndReleaseLocalReqWakeLock() throws Exception { 5970 setupIdleStateMachine(); 5971 5972 ChildSessionCallback cb = mock(ChildSessionCallback.class); 5973 mIkeSessionStateMachine.openChildSession(mChildSessionParams, cb); 5974 5975 mLooper.dispatchAll(); 5976 assertTrue( 5977 mIkeSessionStateMachine.getCurrentState() 5978 instanceof IkeSessionStateMachine.ChildProcedureOngoing); 5979 verify(mMockLocalRequestWakelock).acquire(); 5980 verify(mMockLocalRequestWakelock).release(); 5981 } 5982 5983 @Test testQuitClearAllLocalReqWakeLocks()5984 public void testQuitClearAllLocalReqWakeLocks() throws Exception { 5985 final int localReqCnt = 3; 5986 setupIdleStateMachine(); 5987 5988 // Leave a Idle state so that the LocalRequest won't be executed 5989 mIkeSessionStateMachine.sendMessage( 5990 IkeSessionStateMachine.CMD_FORCE_TRANSITION, mIkeSessionStateMachine.mReceiving); 5991 mLooper.dispatchAll(); 5992 5993 // Only in test that all local requests will get the same WakeLock instance but in function 5994 // code each local request will have a separate WakeLock. 5995 for (int i = 0; i < localReqCnt; i++) { 5996 mIkeSessionStateMachine.openChildSession( 5997 mChildSessionParams, mock(ChildSessionCallback.class)); 5998 } 5999 mLooper.dispatchAll(); 6000 verify(mMockLocalRequestWakelock, times(localReqCnt)).acquire(); 6001 6002 mIkeSessionStateMachine.killSession(); 6003 mLooper.dispatchAll(); 6004 verify(mMockLocalRequestWakelock, times(localReqCnt)).release(); 6005 } 6006 6007 @Test testIkeAuthWithN1Mode()6008 public void testIkeAuthWithN1Mode() throws Exception { 6009 verifyIkeAuthWith3gppEnabled( 6010 makeN1ModeInformationPayload(), 1 /* ike3gppDataListenerInvocations */); 6011 6012 verifyN1ModeReceived(); 6013 } 6014 verifyIkeAuthWith3gppEnabled( IkePayload ike3gppPayload, int ike3gppDataListenerInvocations)6015 private void verifyIkeAuthWith3gppEnabled( 6016 IkePayload ike3gppPayload, int ike3gppDataListenerInvocations) throws Exception { 6017 // Quit and restart IKE Session with N1 Mode Capability params 6018 mIkeSessionStateMachine.quitNow(); 6019 mIkeSessionStateMachine = 6020 makeAndStartIkeSession(buildIkeSessionParamsIke3gppExtension(PDU_SESSION_ID)); 6021 new IkeFirstAuthTestPretest().mockIkeInitAndTransitionToIkeAuth(); 6022 6023 // Build IKE AUTH response with Auth-PSK, ID-Responder and config payloads. 6024 List<IkePayload> authRelatedPayloads = new ArrayList<>(); 6025 authRelatedPayloads.add(ike3gppPayload); 6026 IkeAuthPskPayload spyAuthPayload = makeSpyRespPskPayload(); 6027 authRelatedPayloads.add(spyAuthPayload); 6028 6029 IkeIdPayload respIdPayload = makeRespIdPayload(); 6030 authRelatedPayloads.add(respIdPayload); 6031 authRelatedPayloads.add(makeConfigPayload()); 6032 6033 verifySharedKeyAuthentication( 6034 spyAuthPayload, 6035 respIdPayload, 6036 authRelatedPayloads, 6037 true /*hasChildPayloads*/, 6038 true /*hasConfigPayloadInResp*/, 6039 false /* isMobikeEnabled */, 6040 true /* isIpv4 */, 6041 ike3gppDataListenerInvocations); 6042 verifyRetransmissionStopped(); 6043 } 6044 makeN1ModeInformationPayload()6045 private IkeNotifyPayload makeN1ModeInformationPayload() { 6046 ByteBuffer n1ModeInformationBuffer = ByteBuffer.allocate(SNSSAI.length + 1); 6047 n1ModeInformationBuffer.put((byte) SNSSAI.length); 6048 n1ModeInformationBuffer.put(SNSSAI); 6049 return new IkeNotifyPayload( 6050 NOTIFY_TYPE_N1_MODE_INFORMATION, n1ModeInformationBuffer.array()); 6051 } 6052 verifyN1ModeReceived()6053 private void verifyN1ModeReceived() { 6054 ArgumentCaptor<List<Ike3gppData>> ike3gppDataCaptor = ArgumentCaptor.forClass(List.class); 6055 verify(mMockIke3gppDataListener).onIke3gppDataReceived(ike3gppDataCaptor.capture()); 6056 6057 Ike3gppN1ModeInformation n1ModeInformation = null; 6058 for (Ike3gppData payload : ike3gppDataCaptor.getValue()) { 6059 if (payload.getDataType() == Ike3gppData.DATA_TYPE_NOTIFY_N1_MODE_INFORMATION) { 6060 n1ModeInformation = (Ike3gppN1ModeInformation) payload; 6061 } 6062 } 6063 6064 assertNotNull(n1ModeInformation); 6065 assertArrayEquals(SNSSAI, n1ModeInformation.getSnssai()); 6066 } 6067 6068 @Test testIkeAuthWithBackoffTimerNetworkError()6069 public void testIkeAuthWithBackoffTimerNetworkError() throws Exception { 6070 verifyIkeAuthWithBackoffTimer(ERROR_TYPE_NETWORK_FAILURE); 6071 } 6072 6073 @Test testIkeAuthWithBackoffTimerNoApnSubscription()6074 public void testIkeAuthWithBackoffTimerNoApnSubscription() throws Exception { 6075 verifyIkeAuthWithBackoffTimer(ERROR_TYPE_NO_APN_SUBSCRIPTION); 6076 } 6077 verifyIkeAuthWithBackoffTimer(int expectedNotifyErrorCause)6078 private void verifyIkeAuthWithBackoffTimer(int expectedNotifyErrorCause) throws Exception { 6079 // Quit and restart IKE Session with N1 Mode Capability params 6080 mIkeSessionStateMachine.quitNow(); 6081 mIkeSessionStateMachine = 6082 makeAndStartIkeSession(buildIkeSessionParamsIke3gppExtension(PDU_SESSION_ID)); 6083 new IkeFirstAuthTestPretest().mockIkeInitAndTransitionToIkeAuth(); 6084 6085 // Build IKE AUTH response with BackoffTimer and Error-Notify 6086 IkeNotifyPayload backoffTimerPayload = 6087 new IkeNotifyPayload(NOTIFY_TYPE_BACKOFF_TIMER, BACKOFF_TIMER_DATA); 6088 IkeNotifyPayload errorNotify = new IkeNotifyPayload(expectedNotifyErrorCause); 6089 6090 ReceivedIkePacket mockBackoffTimerResponsePacket = 6091 makeIkeAuthRespWithoutChildPayloads( 6092 Arrays.asList(backoffTimerPayload, errorNotify)); 6093 mIkeSessionStateMachine.sendMessage(CMD_RECEIVE_IKE_PACKET, mockBackoffTimerResponsePacket); 6094 mLooper.dispatchAll(); 6095 6096 // Verify IKE Session is closed properly 6097 assertNull(mIkeSessionStateMachine.getCurrentState()); 6098 verify(mMockIkeSessionCallback) 6099 .onClosedWithException(any(UnrecognizedIkeProtocolException.class)); 6100 6101 verifyBackoffTimer(expectedNotifyErrorCause); 6102 } 6103 verifyBackoffTimer(int expectedNotifyErrorCause)6104 private void verifyBackoffTimer(int expectedNotifyErrorCause) { 6105 ArgumentCaptor<List<Ike3gppData>> ike3gppDataCaptor = ArgumentCaptor.forClass(List.class); 6106 verify(mMockIke3gppDataListener).onIke3gppDataReceived(ike3gppDataCaptor.capture()); 6107 6108 Ike3gppBackoffTimer backoffTimer = null; 6109 for (Ike3gppData payload : ike3gppDataCaptor.getValue()) { 6110 if (payload.getDataType() == Ike3gppData.DATA_TYPE_NOTIFY_BACKOFF_TIMER) { 6111 backoffTimer = (Ike3gppBackoffTimer) payload; 6112 } 6113 } 6114 6115 assertNotNull(backoffTimer); 6116 assertEquals(BACKOFF_TIMER, backoffTimer.getBackoffTimer()); 6117 assertEquals(expectedNotifyErrorCause, backoffTimer.getBackoffCause()); 6118 } 6119 6120 @Test testIkeAuthWithBackoffTimerWithoutError()6121 public void testIkeAuthWithBackoffTimerWithoutError() throws Exception { 6122 verifyIkeAuthWith3gppEnabled( 6123 new IkeNotifyPayload(NOTIFY_TYPE_BACKOFF_TIMER, BACKOFF_TIMER_DATA), 6124 0 /* ike3gppDataListenerInvocations */); 6125 6126 // BackoffTimer should be ignored 6127 verify(mMockIke3gppDataListener, never()).onIke3gppDataReceived(any()); 6128 } 6129 6130 @Test(expected = IllegalArgumentException.class) testIke3gppReuseCallback()6131 public void testIke3gppReuseCallback() throws Exception { 6132 mIkeSessionStateMachine = 6133 makeAndStartIkeSession(buildIkeSessionParamsIke3gppExtension(PDU_SESSION_ID)); 6134 makeAndStartIkeSession(buildIkeSessionParamsIke3gppExtension(PDU_SESSION_ID)); 6135 } 6136 6137 @Test 6138 @SdkSuppress(minSdkVersion = 31, codeName = "S") testOnlyRfcMobikeEnabled()6139 public void testOnlyRfcMobikeEnabled() throws Exception { 6140 verifyRfcMobikeEnabled(true /* doesPeerSupportMobike */); 6141 6142 killSessionAndVerifyNetworkCallback(); 6143 } 6144 6145 @Test 6146 @SdkSuppress(minSdkVersion = 31, codeName = "S") testOnlyRfcMobikeEnabledPeerUnsupported()6147 public void testOnlyRfcMobikeEnabledPeerUnsupported() throws Exception { 6148 verifyRfcMobikeEnabled(false /* doesPeerSupportMobike */); 6149 6150 killSessionAndVerifyNetworkCallback(); 6151 } 6152 6153 @Test 6154 @SdkSuppress(minSdkVersion = 31, codeName = "S") testOnlyRekeyMobilityEnabled()6155 public void testOnlyRekeyMobilityEnabled() throws Exception { 6156 verifyOnlyRekeyMobilityEnabled(); 6157 6158 killSessionAndVerifyNetworkCallback(); 6159 } 6160 6161 @Test 6162 @SdkSuppress(minSdkVersion = 31, codeName = "S") testMobikeRekeyMobilityEnabled()6163 public void testMobikeRekeyMobilityEnabled() throws Exception { 6164 verifyMobikeRekeyMobilityEnabled(true /* doesPeerSupportMobike */); 6165 6166 killSessionAndVerifyNetworkCallback(); 6167 } 6168 6169 @Test 6170 @SdkSuppress(minSdkVersion = 31, codeName = "S") testMobikeRekeyMobilityEnabledPeerUnsupported()6171 public void testMobikeRekeyMobilityEnabledPeerUnsupported() throws Exception { 6172 verifyMobikeRekeyMobilityEnabled(false /* doesPeerSupportMobike */); 6173 6174 killSessionAndVerifyNetworkCallback(); 6175 } 6176 6177 @Test 6178 @SdkSuppress(minSdkVersion = 31, codeName = "S") testMobikeEnabledWithEap()6179 public void testMobikeEnabledWithEap() throws Exception { 6180 List<IkePayload> authRelatedPayloads = new ArrayList<>(); 6181 authRelatedPayloads.add(new IkeNotifyPayload(NOTIFY_TYPE_MOBIKE_SUPPORTED)); 6182 6183 verifyCreateIkeLocalIkeAuthPostEap( 6184 buildIkeSessionParamsWithIkeOptions(IKE_OPTION_MOBIKE), 6185 authRelatedPayloads, 6186 true /* isMobikeEnabled */); 6187 assertTrue(mIkeSessionStateMachine.mEnabledExtensions.contains(EXTENSION_TYPE_MOBIKE)); 6188 } 6189 6190 @Test 6191 @SdkSuppress(minSdkVersion = 31, codeName = "S") testMobikeEnabledNattSupportedIpv4()6192 public void testMobikeEnabledNattSupportedIpv4() throws Exception { 6193 verifyMobikeEnabled(true /* doesPeerSupportNatt */, true /* isIpv4 */); 6194 6195 killSessionAndVerifyNetworkCallback(); 6196 } 6197 6198 @Test 6199 @SdkSuppress(minSdkVersion = 31, codeName = "S") testMobikeEnabledNattUnsupportedIpv4()6200 public void testMobikeEnabledNattUnsupportedIpv4() throws Exception { 6201 verifyMobikeEnabled(false /* doesPeerSupportNatt */, true /* isIpv4 */); 6202 6203 killSessionAndVerifyNetworkCallback(); 6204 } 6205 6206 @Test 6207 @SdkSuppress(minSdkVersion = 31, codeName = "S") testMobikeEnabledNattUnsupportedIpv6()6208 public void testMobikeEnabledNattUnsupportedIpv6() throws Exception { 6209 verifyMobikeEnabled(false /* doesPeerSupportNatt */, false /* isIpv4 */); 6210 6211 killSessionAndVerifyNetworkCallback(); 6212 } 6213 6214 /** 6215 * Restarts the IkeSessionStateMachine with MOBIKE enabled. If doesPeerSupportMobike, MOBIKE 6216 * will be active for the Session. 6217 * 6218 * @return the registered IkeDefaultNetworkCallack is returned if MOBIKE is active, else null 6219 */ 6220 @Nullable verifyRfcMobikeEnabled(boolean doesPeerSupportMobike)6221 private IkeDefaultNetworkCallback verifyRfcMobikeEnabled(boolean doesPeerSupportMobike) 6222 throws Exception { 6223 // Can cast to IkeDefaultNetworkCallback because no Network is specified 6224 return (IkeDefaultNetworkCallback) 6225 verifyMobikeEnabled(doesPeerSupportMobike, null /* configuredNetwork */); 6226 } 6227 6228 @Nullable verifyMobikeRekeyMobilityEnabled( boolean doesPeerSupportMobike)6229 private IkeDefaultNetworkCallback verifyMobikeRekeyMobilityEnabled( 6230 boolean doesPeerSupportMobike) throws Exception { 6231 // Can cast to IkeDefaultNetworkCallback because no Network is specified 6232 return (IkeDefaultNetworkCallback) 6233 verifyMobikeEnabled( 6234 doesPeerSupportMobike, 6235 true /* doesPeerSupportNatt */, 6236 true /* isIpv4 */, 6237 false /* isEnforcePort4500*/, 6238 null /* configuredNetwork */, 6239 true /* mobikeEnabled */, 6240 true /* rekeyMobilityEnabled */); 6241 } 6242 6243 @Nullable verifyOnlyRekeyMobilityEnabled()6244 private IkeDefaultNetworkCallback verifyOnlyRekeyMobilityEnabled() throws Exception { 6245 // Can cast to IkeDefaultNetworkCallback because no Network is specified 6246 return (IkeDefaultNetworkCallback) 6247 verifyMobikeEnabled( 6248 false /* doesPeerSupportMobike */, 6249 true /* doesPeerSupportNatt */, 6250 true /* isIpv4 */, 6251 false /* isEnforcePort4500*/, 6252 null /* configuredNetwork */, 6253 false /* mobikeEnabled */, 6254 true /* rekeyMobilityEnabled */); 6255 } 6256 6257 @Nullable verifyMobikeEnabled( boolean doesPeerSupportMobike, Network configuredNetwork)6258 private IkeNetworkCallbackBase verifyMobikeEnabled( 6259 boolean doesPeerSupportMobike, Network configuredNetwork) throws Exception { 6260 return verifyMobikeEnabled( 6261 doesPeerSupportMobike, 6262 true /* doesPeerSupportNatt */, 6263 true /* isIpv4 */, 6264 false /* isEnforcePort4500*/, 6265 configuredNetwork, 6266 true /* mobikeEnabled */, 6267 false /* rekeyMobilityEnabled */); 6268 } 6269 6270 @Nullable verifyMobikeEnabled( boolean doesPeerSupportNatt, boolean isIpv4)6271 private IkeDefaultNetworkCallback verifyMobikeEnabled( 6272 boolean doesPeerSupportNatt, boolean isIpv4) throws Exception { 6273 // Can cast to IkeDefaultNetworkCallback because no Network is specified 6274 return (IkeDefaultNetworkCallback) 6275 verifyMobikeEnabled( 6276 true /* doesPeerSupportMobike */, 6277 doesPeerSupportNatt, 6278 isIpv4, 6279 false /* isEnforcePort4500*/, 6280 null /* configuredNetwork */, 6281 true /* mobikeEnabled */, 6282 false /* rekeyMobilityEnabled */); 6283 } 6284 6285 /** Returns the expected IkeSocket type when MOBIKE is supported by both sides */ getExpectedSocketType( boolean doesPeerSupportNatt, boolean isEnforcePort4500, boolean isIpv4)6286 private Class<? extends IkeSocket> getExpectedSocketType( 6287 boolean doesPeerSupportNatt, boolean isEnforcePort4500, boolean isIpv4) { 6288 if (doesPeerSupportNatt || isEnforcePort4500) { 6289 if (isIpv4) { 6290 return IkeUdpEncapSocket.class; 6291 } else { 6292 return IkeUdp6WithEncapPortSocket.class; 6293 } 6294 } else { 6295 if (isIpv4) { 6296 return IkeUdp4Socket.class; 6297 } else { 6298 return IkeUdp6Socket.class; 6299 } 6300 } 6301 } 6302 6303 @Nullable verifyMobikeEnabled( boolean doesPeerSupportMobike, boolean doesPeerSupportNatt, boolean isIpv4, boolean isEnforcePort4500, Network configuredNetwork, boolean mobikeEnabled, boolean rekeyMobilityEnabled)6304 private IkeNetworkCallbackBase verifyMobikeEnabled( 6305 boolean doesPeerSupportMobike, 6306 boolean doesPeerSupportNatt, 6307 boolean isIpv4, 6308 boolean isEnforcePort4500, 6309 Network configuredNetwork, 6310 boolean mobikeEnabled, 6311 boolean rekeyMobilityEnabled) 6312 throws Exception { 6313 mIkeSessionStateMachine = 6314 restartStateMachineWithMobikeConfigured( 6315 configuredNetwork, 6316 isEnforcePort4500, 6317 isIpv4, 6318 mobikeEnabled, 6319 rekeyMobilityEnabled); 6320 new IkeFirstAuthTestPretest().mockIkeInitAndTransitionToIkeAuth(); 6321 6322 // Enable force_udp_encap under IPv4 network because the kernel cannot process both 6323 // UDP-encap and non-UDP-encap ESP packets for a single SA 6324 boolean doesEnableForceUdpEncap = isIpv4; 6325 6326 if (isIpv4) { 6327 if (doesPeerSupportNatt || doesEnableForceUdpEncap) { 6328 // Either NAT detected or not detected won't affect the test since both cases 6329 // indicate the server support NAT-T 6330 mSpyIkeConnectionCtrl.handleNatDetectionResultInIkeInit( 6331 true /* isNatDetected */, mSpyCurrentIkeSaRecord.getLocalSpi()); 6332 } else { 6333 mSpyIkeConnectionCtrl.markSeverNattUnsupported(); 6334 } 6335 } else { 6336 // IKE client does not support IPv6 NAT-T and will not check if the server supports 6337 // NAT-T when using IPv6 for IKE Session setup. 6338 mSpyIkeConnectionCtrl.resetSeverNattSupport(); 6339 } 6340 6341 // Build IKE AUTH response. Include MOBIKE_SUPPORTED if doesPeerSupportMobike is true 6342 List<IkePayload> authRelatedPayloads = new ArrayList<>(); 6343 IkeAuthPskPayload spyAuthPayload = makeSpyRespPskPayload(); 6344 authRelatedPayloads.add(spyAuthPayload); 6345 6346 IkeIdPayload respIdPayload = makeRespIdPayload(); 6347 authRelatedPayloads.add(respIdPayload); 6348 authRelatedPayloads.add(makeConfigPayload()); 6349 6350 if (doesPeerSupportMobike) { 6351 authRelatedPayloads.add(new IkeNotifyPayload(NOTIFY_TYPE_MOBIKE_SUPPORTED)); 6352 } 6353 6354 IkeMessage ikeAuthReqMessage = 6355 verifySharedKeyAuthentication( 6356 spyAuthPayload, 6357 respIdPayload, 6358 authRelatedPayloads, 6359 true /* hasChildPayloads */, 6360 true /* hasConfigPayloadInResp */, 6361 doesPeerSupportMobike, 6362 isIpv4, 6363 0 /* ike3gppDataListenerInvocations */); 6364 verifyRetransmissionStopped(); 6365 6366 boolean isMobikeSupportIndicated = false; 6367 List<IkeNotifyPayload> reqNotifyPayloads = 6368 ikeAuthReqMessage.getPayloadListForType( 6369 PAYLOAD_TYPE_NOTIFY, IkeNotifyPayload.class); 6370 for (IkeNotifyPayload notifyPayload : reqNotifyPayloads) { 6371 if (notifyPayload.notifyType == NOTIFY_TYPE_MOBIKE_SUPPORTED) { 6372 isMobikeSupportIndicated = true; 6373 break; 6374 } 6375 } 6376 6377 assertEquals(mobikeEnabled, isMobikeSupportIndicated); 6378 6379 assertEquals( 6380 doesPeerSupportMobike, 6381 mIkeSessionStateMachine.mEnabledExtensions.contains(EXTENSION_TYPE_MOBIKE)); 6382 6383 if (rekeyMobilityEnabled || doesPeerSupportMobike) { 6384 assertTrue(mSpyIkeConnectionCtrl.isMobilityEnabled()); 6385 assertTrue( 6386 getExpectedSocketType( 6387 doesPeerSupportNatt || doesEnableForceUdpEncap, 6388 isEnforcePort4500, 6389 isIpv4) 6390 .isInstance(mSpyIkeConnectionCtrl.getIkeSocket())); 6391 } else { 6392 assertFalse(mSpyIkeConnectionCtrl.isMobilityEnabled()); 6393 } 6394 6395 ArgumentCaptor<IkeNetworkCallbackBase> networkCallbackCaptor = 6396 ArgumentCaptor.forClass(IkeNetworkCallbackBase.class); 6397 // Expect different NetworkCallback registrations if there is a caller-configured 6398 // Network 6399 if (configuredNetwork == null) { 6400 verify(mMockConnectManager) 6401 .registerDefaultNetworkCallback(networkCallbackCaptor.capture(), any()); 6402 } else { 6403 verify(mMockConnectManager) 6404 .registerNetworkCallback(any(), networkCallbackCaptor.capture(), any()); 6405 } 6406 6407 IkeNetworkCallbackBase networkCallback = networkCallbackCaptor.getValue(); 6408 Class<? extends IkeNetworkCallbackBase> expectedCallbackType = 6409 configuredNetwork == null 6410 ? IkeDefaultNetworkCallback.class 6411 : IkeSpecificNetworkCallback.class; 6412 assertTrue(expectedCallbackType.isInstance(networkCallback)); 6413 return networkCallback; 6414 } 6415 killSessionAndVerifyNetworkCallback()6416 private void killSessionAndVerifyNetworkCallback() { 6417 mIkeSessionStateMachine.killSession(); 6418 mLooper.dispatchAll(); 6419 6420 verify(mMockConnectManager).unregisterNetworkCallback(any(IkeDefaultNetworkCallback.class)); 6421 } 6422 6423 /** Restarts the IkeSessionStateMachine with MOBIKE configured in the IkeSessionParams. */ restartStateMachineWithRfcMobikeConfigured()6424 private IkeSessionStateMachine restartStateMachineWithRfcMobikeConfigured() throws Exception { 6425 return restartStateMachineWithMobikeConfigured( 6426 null /* network */, 6427 false /* isEnforcePort4500*/, 6428 true /* isIpv4 */, 6429 true /* mobikeEnabled */, 6430 false /* rekeyMobilityEnabled */); 6431 } 6432 restartStateMachineWithMobikeConfigured( @ullable Network configuredNetwork, boolean isEnforcePort4500, boolean isIpv4, boolean mobikeEnabled, boolean rekeyMobilityEnabled)6433 private IkeSessionStateMachine restartStateMachineWithMobikeConfigured( 6434 @Nullable Network configuredNetwork, 6435 boolean isEnforcePort4500, 6436 boolean isIpv4, 6437 boolean mobikeEnabled, 6438 boolean rekeyMobilityEnabled) 6439 throws Exception { 6440 mIkeSessionStateMachine.quitNow(); 6441 mLooper.dispatchAll(); 6442 6443 // Clear ConnectivityManager#getActiveNetwork (#makeAndStartIkeSession() expects no use of 6444 // ConnectivityManager#getActiveNetwork when there is a configured Network) and the network 6445 // callback registration call in #setUp(). 6446 resetMockConnectManager(); 6447 6448 // Set local and remote address 6449 Network network = configuredNetwork == null ? mMockDefaultNetwork : configuredNetwork; 6450 InetAddress localAddress = isIpv4 ? LOCAL_ADDRESS : LOCAL_ADDRESS_V6; 6451 InetAddress remoteAddress = isIpv4 ? REMOTE_ADDRESS : REMOTE_ADDRESS_V6; 6452 setupLocalAddressForNetwork(network, localAddress); 6453 setupRemoteAddressForNetwork(network, remoteAddress); 6454 6455 IkeSessionParams.Builder ikeSessionParamsBuilder = 6456 buildIkeSessionParamsCommon().setAuthPsk(mPsk); 6457 6458 if (mobikeEnabled) { 6459 ikeSessionParamsBuilder.addIkeOption(IKE_OPTION_MOBIKE); 6460 } 6461 6462 if (rekeyMobilityEnabled) { 6463 ikeSessionParamsBuilder.addIkeOptionInternal(IKE_OPTION_REKEY_MOBILITY); 6464 } else { 6465 // IKE_OPTION_REKEY_MOBILITY will be automatically added with IKE_OPTION_MOBIKE. So 6466 // explicitly remove it here 6467 ikeSessionParamsBuilder.removeIkeOption(IKE_OPTION_REKEY_MOBILITY); 6468 } 6469 6470 if (isEnforcePort4500) { 6471 ikeSessionParamsBuilder.addIkeOption(IKE_OPTION_FORCE_PORT_4500); 6472 } 6473 if (configuredNetwork != null) { 6474 ikeSessionParamsBuilder.setNetwork(configuredNetwork); 6475 } 6476 return makeAndStartIkeSession(ikeSessionParamsBuilder.build(), localAddress, remoteAddress); 6477 } 6478 verifyHandleNetworkChange()6479 private void verifyHandleNetworkChange() throws Exception { 6480 if (SdkLevel.isAtLeastT()) { 6481 verify(mMockIkeSessionCallback).onClosedWithException(any(IkeException.class)); 6482 assertNull(mIkeSessionStateMachine.getCurrentState()); 6483 } else { 6484 verify(mMockIkeSessionCallback).onError(any(IkeException.class)); 6485 assertNotNull(mIkeSessionStateMachine.getCurrentState()); 6486 } 6487 } 6488 6489 @Test 6490 @SdkSuppress(minSdkVersion = 31, codeName = "S") testMobilityDisabledNetworkDies()6491 public void testMobilityDisabledNetworkDies() throws Exception { 6492 IkeDefaultNetworkCallback callback = 6493 verifyRfcMobikeEnabled(false /* doesPeerSupportMobike */); 6494 callback.onLost(mMockDefaultNetwork); 6495 mLooper.dispatchAll(); 6496 6497 verifyHandleNetworkChange(); 6498 } 6499 6500 @Test 6501 @SdkSuppress(minSdkVersion = 31, codeName = "S") testMobilityDisabledNetworkUpdates()6502 public void testMobilityDisabledNetworkUpdates() throws Exception { 6503 IkeDefaultNetworkCallback callback = 6504 verifyRfcMobikeEnabled(false /* doesPeerSupportMobike */); 6505 Network newNetwork = mock(Network.class); 6506 callback.onAvailable(newNetwork); 6507 callback.onCapabilitiesChanged(newNetwork, mock(NetworkCapabilities.class)); 6508 callback.onLinkPropertiesChanged(newNetwork, mock(LinkProperties.class)); 6509 6510 mLooper.dispatchAll(); 6511 6512 verifyHandleNetworkChange(); 6513 } 6514 6515 @Test 6516 @SdkSuppress(minSdkVersion = 31, codeName = "S") testMobikeEnabledNetworkDies()6517 public void testMobikeEnabledNetworkDies() throws Exception { 6518 IkeDefaultNetworkCallback callback = 6519 verifyRfcMobikeEnabled(true /* doesPeerSupportMobike */); 6520 callback.onLost(mMockDefaultNetwork); 6521 6522 ArgumentCaptor<IkeException> exceptionCaptor = ArgumentCaptor.forClass(IkeException.class); 6523 verify(mMockIkeSessionCallback).onError(exceptionCaptor.capture()); 6524 IkeNetworkLostException cause = (IkeNetworkLostException) exceptionCaptor.getValue(); 6525 assertEquals(mMockDefaultNetwork, cause.getNetwork()); 6526 } 6527 verifyMobikeActiveMobilityEvent(boolean isEnforcePort4500)6528 private void verifyMobikeActiveMobilityEvent(boolean isEnforcePort4500) throws Exception { 6529 IkeDefaultNetworkCallback callback = 6530 (IkeDefaultNetworkCallback) 6531 verifyMobikeEnabled( 6532 true /* doesPeerSupportMobike */, 6533 false /* doesPeerSupportNatt */, 6534 true /* isIpv4 */, 6535 isEnforcePort4500, 6536 null /* configuredNetwork */, 6537 true /* mobikeEnabled */, 6538 false /* rekeyMobilityEnabled */); 6539 6540 Network newNetwork = mockNewNetworkAndAddress(true /* isIpv4 */); 6541 6542 callback.onAvailable(newNetwork); 6543 callback.onCapabilitiesChanged(newNetwork, mock(NetworkCapabilities.class)); 6544 callback.onLinkPropertiesChanged( 6545 newNetwork, mMockConnectManager.getLinkProperties(newNetwork)); 6546 mLooper.dispatchAll(); 6547 6548 verifyNetworkAndLocalAddressUpdated( 6549 newNetwork, UPDATED_LOCAL_ADDRESS, REMOTE_ADDRESS, callback); 6550 verify(mMockIkeLocalAddressGenerator) 6551 .generateLocalAddress( 6552 eq(newNetwork), eq(true /* isIpv4 */), eq(REMOTE_ADDRESS), anyInt()); 6553 } 6554 6555 @Test 6556 @SdkSuppress(minSdkVersion = 31, codeName = "S") testMobikeActiveMobilityEvent()6557 public void testMobikeActiveMobilityEvent() throws Exception { 6558 verifyMobikeActiveMobilityEvent(false /* isEnforcePort4500 */); 6559 assertTrue(mSpyIkeConnectionCtrl.getIkeSocket() instanceof IkeUdpEncapSocket); 6560 } 6561 6562 @Test 6563 @SdkSuppress(minSdkVersion = 31, codeName = "S") testMobikeActiveMobilityEventWithEnforcePort4500()6564 public void testMobikeActiveMobilityEventWithEnforcePort4500() throws Exception { 6565 verifyMobikeActiveMobilityEvent(true /* isEnforcePort4500 */); 6566 assertTrue(mSpyIkeConnectionCtrl.getIkeSocket() instanceof IkeUdpEncapSocket); 6567 } 6568 mockNewNetworkAndAddress(boolean isIpv4)6569 private Network mockNewNetworkAndAddress(boolean isIpv4) throws Exception { 6570 InetAddress expectedRemoteAddress; 6571 InetAddress injectedLocalAddress; 6572 if (isIpv4) { 6573 expectedRemoteAddress = REMOTE_ADDRESS; 6574 injectedLocalAddress = UPDATED_LOCAL_ADDRESS; 6575 } else { 6576 expectedRemoteAddress = REMOTE_ADDRESS_V6; 6577 injectedLocalAddress = UPDATED_LOCAL_ADDRESS_V6; 6578 } 6579 6580 return mockNewNetworkAndAddress(isIpv4, injectedLocalAddress, expectedRemoteAddress); 6581 } 6582 mockNewNetworkAndAddress( boolean isIpv4, InetAddress localAddress, InetAddress remoteAddress)6583 private Network mockNewNetworkAndAddress( 6584 boolean isIpv4, InetAddress localAddress, InetAddress remoteAddress) throws Exception { 6585 return mockNewNetworkAndAddress(isIpv4, localAddress, remoteAddress, 1 /* dnsLookups */); 6586 } 6587 mockNewNetworkAndAddress( boolean isIpv4, InetAddress localAddress, InetAddress remoteAddress, int dnsLookups)6588 private Network mockNewNetworkAndAddress( 6589 boolean isIpv4, InetAddress localAddress, InetAddress remoteAddress, int dnsLookups) 6590 throws Exception { 6591 Network newNetwork = mock(Network.class); 6592 6593 mSpyIkeConnectionCtrl.addRemoteAddress(remoteAddress); 6594 6595 LinkAddress linkAddress = mock(LinkAddress.class); 6596 when(linkAddress.getAddress()).thenReturn(localAddress); 6597 6598 LinkProperties linkProperties = new LinkProperties(); 6599 linkProperties.addLinkAddress(linkAddress); 6600 when(mMockConnectManager.getLinkProperties(eq(newNetwork))).thenReturn(linkProperties); 6601 6602 if (!isIpv4) { 6603 when(linkAddress.isGlobalPreferred()).thenReturn(true); 6604 } 6605 6606 setupDnsResolutionForNetwork(newNetwork, dnsLookups, remoteAddress); 6607 setupLocalAddressForNetwork(newNetwork, localAddress); 6608 6609 return newNetwork; 6610 } 6611 verifyNetworkAndLocalAddressUpdated( Network underlyingNetwork, InetAddress localAddress, InetAddress remoteAddress, IkeNetworkCallbackBase networkCallback)6612 private void verifyNetworkAndLocalAddressUpdated( 6613 Network underlyingNetwork, 6614 InetAddress localAddress, 6615 InetAddress remoteAddress, 6616 IkeNetworkCallbackBase networkCallback) 6617 throws Exception { 6618 assertEquals(underlyingNetwork, mSpyIkeConnectionCtrl.getNetwork()); 6619 assertEquals(underlyingNetwork, mSpyIkeConnectionCtrl.getNetwork()); 6620 assertEquals(localAddress, mSpyIkeConnectionCtrl.getLocalAddress()); 6621 assertEquals(remoteAddress, mSpyIkeConnectionCtrl.getRemoteAddress()); 6622 6623 verifyIkeSaAddresses( 6624 mIkeSessionStateMachine.mCurrentIkeSaRecord, localAddress, remoteAddress); 6625 6626 verify(underlyingNetwork, atLeastOnce()).getAllByName(REMOTE_HOSTNAME); 6627 6628 assertEquals(underlyingNetwork, networkCallback.getNetwork()); 6629 assertEquals(localAddress, networkCallback.getAddress()); 6630 } 6631 verifyIkeSaAddresses( IkeSaRecord saRecord, InetAddress localAddress, InetAddress remoteAddress)6632 private void verifyIkeSaAddresses( 6633 IkeSaRecord saRecord, InetAddress localAddress, InetAddress remoteAddress) { 6634 assertEquals( 6635 localAddress, saRecord.getInitiatorIkeSecurityParameterIndex().getSourceAddress()); 6636 assertEquals( 6637 remoteAddress, saRecord.getResponderIkeSecurityParameterIndex().getSourceAddress()); 6638 } 6639 6640 // TODO : this should be NullPointerException 6641 @Test(expected = IllegalArgumentException.class) testSetNetworkNull()6642 public void testSetNetworkNull() throws Exception { 6643 mIkeSessionStateMachine.setNetwork(null, 6644 IkeSessionParams.ESP_IP_VERSION_AUTO, 6645 IkeSessionParams.ESP_ENCAP_TYPE_AUTO, 6646 IkeSessionParams.NATT_KEEPALIVE_INTERVAL_AUTO); 6647 } 6648 6649 @Test(expected = IllegalStateException.class) testSetNetworkMobikeNotActive()6650 public void testSetNetworkMobikeNotActive() throws Exception { 6651 Network newNetwork = mock(Network.class); 6652 6653 mIkeSessionStateMachine.setNetwork(newNetwork, 6654 IkeSessionParams.ESP_IP_VERSION_AUTO, 6655 IkeSessionParams.ESP_ENCAP_TYPE_AUTO, 6656 IkeSessionParams.NATT_KEEPALIVE_INTERVAL_AUTO); 6657 } 6658 6659 @Test(expected = IllegalStateException.class) 6660 @SdkSuppress(minSdkVersion = 31, codeName = "S") testSetNetworkMobikeActiveNetworkNotSpecified()6661 public void testSetNetworkMobikeActiveNetworkNotSpecified() throws Exception { 6662 Network newNetwork = mock(Network.class); 6663 6664 verifyRfcMobikeEnabled(true /* doesPeerSupportMobike */); 6665 6666 mIkeSessionStateMachine.setNetwork(newNetwork, 6667 IkeSessionParams.ESP_IP_VERSION_AUTO, 6668 IkeSessionParams.ESP_ENCAP_TYPE_AUTO, 6669 IkeSessionParams.NATT_KEEPALIVE_INTERVAL_AUTO); 6670 } 6671 verifySetNetwork( IkeNetworkCallbackBase callback, IkeSaRecord rekeySaRecord, State expectedState)6672 private void verifySetNetwork( 6673 IkeNetworkCallbackBase callback, IkeSaRecord rekeySaRecord, State expectedState) 6674 throws Exception { 6675 verifySetNetwork(callback, rekeySaRecord, expectedState, true /* isIpv4 */); 6676 } 6677 verifySetNetwork( IkeNetworkCallbackBase callback, IkeSaRecord rekeySaRecord, State expectedState, boolean isIpv4)6678 private void verifySetNetwork( 6679 IkeNetworkCallbackBase callback, 6680 IkeSaRecord rekeySaRecord, 6681 State expectedState, 6682 boolean isIpv4) 6683 throws Exception { 6684 Network newNetwork = mockNewNetworkAndAddress(isIpv4); 6685 6686 mIkeSessionStateMachine.setNetwork(newNetwork, 6687 IkeSessionParams.ESP_IP_VERSION_AUTO, 6688 IkeSessionParams.ESP_ENCAP_TYPE_AUTO, 6689 IkeSessionParams.NATT_KEEPALIVE_INTERVAL_AUTO); 6690 mLooper.dispatchAll(); 6691 6692 InetAddress expectedUpdatedLocalAddress = 6693 isIpv4 ? UPDATED_LOCAL_ADDRESS : UPDATED_LOCAL_ADDRESS_V6; 6694 InetAddress expectedRemoteAddress = isIpv4 ? REMOTE_ADDRESS : REMOTE_ADDRESS_V6; 6695 6696 verifyNetworkAndLocalAddressUpdated( 6697 newNetwork, expectedUpdatedLocalAddress, expectedRemoteAddress, callback); 6698 verify(mMockIkeLocalAddressGenerator) 6699 .generateLocalAddress( 6700 eq(newNetwork), eq(isIpv4), eq(expectedRemoteAddress), anyInt()); 6701 6702 verify(mSpyIkeConnectionCtrl.getIkeSocket()) 6703 .registerIke( 6704 mIkeSessionStateMachine.mCurrentIkeSaRecord.getLocalSpi(), 6705 mSpyIkeConnectionCtrl); 6706 6707 if (rekeySaRecord != null) { 6708 verifyIkeSaAddresses(rekeySaRecord, expectedUpdatedLocalAddress, expectedRemoteAddress); 6709 verify(mSpyIkeConnectionCtrl.getIkeSocket()) 6710 .registerIke(rekeySaRecord.getLocalSpi(), mSpyIkeConnectionCtrl); 6711 } 6712 6713 assertEquals(expectedState, mIkeSessionStateMachine.getCurrentState()); 6714 } 6715 setupIdleStateMachineWithMobike()6716 private IkeNetworkCallbackBase setupIdleStateMachineWithMobike() throws Exception { 6717 return setupIdleStateMachineWithMobike(true /* doesPeerSupportNatt */, true /* isIpv4 */); 6718 } 6719 setupIdleStateMachineWithMobike( boolean doesPeerSupportNatt, boolean isIpv4)6720 private IkeNetworkCallbackBase setupIdleStateMachineWithMobike( 6721 boolean doesPeerSupportNatt, boolean isIpv4) throws Exception { 6722 IkeNetworkCallbackBase callback = 6723 verifyMobikeEnabled( 6724 true /* doesPeerSupportMobike */, 6725 doesPeerSupportNatt, 6726 isIpv4, 6727 false /* isEnforcePort4500*/, 6728 mMockDefaultNetwork, 6729 true /* mobikeEnabled */, 6730 false /* rekeyMobilityEnabled */); 6731 6732 // reset IkeMessageHelper to make verifying outbound req easier 6733 resetMockIkeMessageHelper(); 6734 6735 mDummyChildSmCallback = 6736 createChildAndGetChildSessionSmCallback( 6737 mMockChildSessionStateMachine, CHILD_SPI_REMOTE, mMockChildSessionCallback); 6738 6739 mIkeSessionStateMachine.sendMessage( 6740 IkeSessionStateMachine.CMD_FORCE_TRANSITION, mIkeSessionStateMachine.mIdle); 6741 mLooper.dispatchAll(); 6742 6743 return callback; 6744 } 6745 verifySetNetworkInIdleState( boolean doesPeerSupportNatt, boolean isIpv4BeforeNetworkChange, boolean isIpv4AfterNetworkChange)6746 private void verifySetNetworkInIdleState( 6747 boolean doesPeerSupportNatt, 6748 boolean isIpv4BeforeNetworkChange, 6749 boolean isIpv4AfterNetworkChange) 6750 throws Exception { 6751 IkeNetworkCallbackBase callback = 6752 setupIdleStateMachineWithMobike(doesPeerSupportNatt, isIpv4BeforeNetworkChange); 6753 6754 verifySetNetwork( 6755 callback, 6756 null /* rekeySaRecord */, 6757 mIkeSessionStateMachine.mMobikeLocalInfo, 6758 isIpv4AfterNetworkChange); 6759 assertTrue( 6760 getExpectedSocketType( 6761 doesPeerSupportNatt 6762 || isIpv4AfterNetworkChange /* force UDP-encap */, 6763 false /* isEnforcePort4500*/, 6764 isIpv4AfterNetworkChange) 6765 .isInstance(mSpyIkeConnectionCtrl.getIkeSocket())); 6766 } 6767 6768 @Test 6769 @SdkSuppress(minSdkVersion = 31, codeName = "S") testSetNetworkInIdleStateNattSupportedIpv4ToIpv6()6770 public void testSetNetworkInIdleStateNattSupportedIpv4ToIpv6() throws Exception { 6771 verifySetNetworkInIdleState( 6772 true /* doesPeerSupportNatt */, 6773 true /* isIpv4BeforeNetworkChange */, 6774 false /* isIpv4AfterNetworkChange */); 6775 } 6776 6777 @Test 6778 @SdkSuppress(minSdkVersion = 31, codeName = "S") testSetNetworkInIdleStateNattSupportedIpv6ToIpv4()6779 public void testSetNetworkInIdleStateNattSupportedIpv6ToIpv4() throws Exception { 6780 verifySetNetworkInIdleState( 6781 true /* doesPeerSupportNatt */, 6782 true /* isIpv4BeforeNetworkChange */, 6783 false /* isIpv4AfterNetworkChange */); 6784 } 6785 6786 @Test 6787 @SdkSuppress(minSdkVersion = 31, codeName = "S") testSetNetworkInIdleStateNattSupportedIpv4ToIpv4()6788 public void testSetNetworkInIdleStateNattSupportedIpv4ToIpv4() throws Exception { 6789 verifySetNetworkInIdleState( 6790 true /* doesPeerSupportNatt */, 6791 true /* isIpv4BeforeNetworkChange */, 6792 true /* isIpv4AfterNetworkChange */); 6793 } 6794 6795 @Test 6796 @SdkSuppress(minSdkVersion = 31, codeName = "S") testSetNetworkInIdleStateNattUnsupportedIpv4ToIpv4()6797 public void testSetNetworkInIdleStateNattUnsupportedIpv4ToIpv4() throws Exception { 6798 verifySetNetworkInIdleState( 6799 false /* doesPeerSupportNatt */, 6800 true /* isIpv4BeforeNetworkChange */, 6801 true /* isIpv4AfterNetworkChange */); 6802 } 6803 6804 @Test 6805 @SdkSuppress(minSdkVersion = 31, codeName = "S") testSetNetworkInIdleStateNattUnsupportedIpv6ToIpv6()6806 public void testSetNetworkInIdleStateNattUnsupportedIpv6ToIpv6() throws Exception { 6807 verifySetNetworkInIdleState( 6808 false /* doesPeerSupportNatt */, 6809 false /* isIpv4BeforeNetworkChange */, 6810 false /* isIpv4AfterNetworkChange */); 6811 } 6812 6813 @Test 6814 @SdkSuppress(minSdkVersion = 31, codeName = "S") testSetNetworkLocalRekeyState()6815 public void testSetNetworkLocalRekeyState() throws Exception { 6816 // Start IKE Session + transition to Idle 6817 IkeNetworkCallbackBase callback = 6818 verifyMobikeEnabled(true /* doesPeerSupportMobike */, mMockDefaultNetwork); 6819 mIkeSessionStateMachine.sendMessage( 6820 IkeSessionStateMachine.CMD_FORCE_TRANSITION, mIkeSessionStateMachine.mIdle); 6821 6822 verifyRekeyIkeLocalCreateHandlesResponse(); 6823 6824 verifySetNetwork( 6825 callback, 6826 mIkeSessionStateMachine.mLocalInitNewIkeSaRecord, 6827 mIkeSessionStateMachine.mRekeyIkeLocalDelete); 6828 } 6829 6830 @Test 6831 @SdkSuppress(minSdkVersion = 31, codeName = "S") testSetNetworkRemoteRekeyState()6832 public void testSetNetworkRemoteRekeyState() throws Exception { 6833 // Start IKE Session + transition to remote rekey 6834 IkeNetworkCallbackBase callback = 6835 verifyMobikeEnabled(true /* doesPeerSupportMobike */, mMockDefaultNetwork); 6836 6837 mIkeSessionStateMachine.mRemoteInitNewIkeSaRecord = mSpyRemoteInitIkeSaRecord; 6838 mIkeSessionStateMachine.addIkeSaRecord(mSpyRemoteInitIkeSaRecord); 6839 mIkeSessionStateMachine.sendMessage( 6840 IkeSessionStateMachine.CMD_FORCE_TRANSITION, 6841 mIkeSessionStateMachine.mRekeyIkeRemoteDelete); 6842 mLooper.dispatchAll(); 6843 6844 verifySetNetwork( 6845 callback, 6846 mIkeSessionStateMachine.mRemoteInitNewIkeSaRecord, 6847 mIkeSessionStateMachine.mRekeyIkeRemoteDelete); 6848 } 6849 verifyRcvDeviceIdentityCheckReqAndReply()6850 private void verifyRcvDeviceIdentityCheckReqAndReply() throws Exception { 6851 // Receive a Information req with DEVICE_IDENTITY payload 6852 ReceivedIkePacket dummyRequest = makeDeviceIdentityIkeRequest(); 6853 mIkeSessionStateMachine.sendMessage( 6854 IkeSessionStateMachine.CMD_RECEIVE_IKE_PACKET, dummyRequest); 6855 mLooper.dispatchAll(); 6856 6857 IkeMessage resp = verifyAndGetOutboundInformationalResp(); 6858 6859 List<IkeNotifyPayload> notifyPayloads = 6860 resp.getPayloadListForType(PAYLOAD_TYPE_NOTIFY, IkeNotifyPayload.class); 6861 assertEquals(1, notifyPayloads.size()); 6862 IkeNotifyPayload deviceIdentity = notifyPayloads.get(0); 6863 assertEquals(NOTIFY_TYPE_DEVICE_IDENTITY, deviceIdentity.notifyType); 6864 assertArrayEquals(DEVICE_IDENTITY_PAYLOAD_IMEI, deviceIdentity.notifyData); 6865 } 6866 verifyRcvRoutabilityCheckReqAndReply()6867 private void verifyRcvRoutabilityCheckReqAndReply() throws Exception { 6868 // Receive a routability check request 6869 ReceivedIkePacket dummyRequest = makeRoutabilityCheckIkeRequest(); 6870 mIkeSessionStateMachine.sendMessage( 6871 IkeSessionStateMachine.CMD_RECEIVE_IKE_PACKET, dummyRequest); 6872 mLooper.dispatchAll(); 6873 6874 IkeMessage resp = verifyAndGetOutboundInformationalResp(); 6875 6876 List<IkeNotifyPayload> notifyPayloads = 6877 resp.getPayloadListForType(PAYLOAD_TYPE_NOTIFY, IkeNotifyPayload.class); 6878 assertEquals(1, notifyPayloads.size()); 6879 IkeNotifyPayload cookie2 = notifyPayloads.get(0); 6880 assertEquals(NOTIFY_TYPE_COOKIE2, cookie2.notifyType); 6881 assertArrayEquals(COOKIE2_DATA, cookie2.notifyData); 6882 } 6883 6884 @Test testRcvRoutabilityCheckReqInIdle()6885 public void testRcvRoutabilityCheckReqInIdle() throws Exception { 6886 setupIdleStateMachine(); 6887 6888 verifyRcvRoutabilityCheckReqAndReply(); 6889 assertTrue( 6890 mIkeSessionStateMachine.getCurrentState() instanceof IkeSessionStateMachine.Idle); 6891 } 6892 6893 @Test testRcvRoutabilityCheckReqInDpd()6894 public void testRcvRoutabilityCheckReqInDpd() throws Exception { 6895 executeAndVerifySendLocalDPD(); 6896 verifyRcvRoutabilityCheckReqAndReply(); 6897 assertTrue( 6898 mIkeSessionStateMachine.getCurrentState() 6899 instanceof IkeSessionStateMachine.DpdIkeLocalInfo); 6900 } 6901 6902 @Test testRcvRoutabilityCheckReqInChildProcedureOngoing()6903 public void testRcvRoutabilityCheckReqInChildProcedureOngoing() throws Exception { 6904 setupIdleStateMachine(); 6905 6906 mIkeSessionStateMachine.sendMessage( 6907 IkeSessionStateMachine.CMD_EXECUTE_LOCAL_REQ, 6908 mLocalRequestFactory.getChildLocalRequest( 6909 IkeSessionStateMachine.CMD_LOCAL_REQUEST_DELETE_CHILD, 6910 mMockChildSessionCallback, 6911 null /*childParams*/)); 6912 mLooper.dispatchAll(); 6913 6914 // For conveniency to verify outbound routability check response, reset IkeMessageHelper to 6915 // forget sending Delete Child request 6916 resetMockIkeMessageHelper(); 6917 6918 verifyRcvRoutabilityCheckReqAndReply(); 6919 assertTrue( 6920 mIkeSessionStateMachine.getCurrentState() 6921 instanceof IkeSessionStateMachine.ChildProcedureOngoing); 6922 } 6923 6924 @Test testRcvRoutabilityCheckReqInLocalRekeyIkeCreate()6925 public void testRcvRoutabilityCheckReqInLocalRekeyIkeCreate() throws Exception { 6926 setupIdleStateMachine(); 6927 6928 // Send Rekey-Create request 6929 mIkeSessionStateMachine.sendMessage( 6930 IkeSessionStateMachine.CMD_EXECUTE_LOCAL_REQ, 6931 mLocalRequestFactory.getIkeLocalRequest( 6932 IkeSessionStateMachine.CMD_LOCAL_REQUEST_REKEY_IKE)); 6933 mLooper.dispatchAll(); 6934 6935 // For conveniency to verify outbound routability check response, reset IkeMessageHelper to 6936 // forget sending Rekey Create request 6937 resetMockIkeMessageHelper(); 6938 6939 verifyRcvRoutabilityCheckReqAndReply(); 6940 assertTrue( 6941 mIkeSessionStateMachine.getCurrentState() 6942 instanceof IkeSessionStateMachine.RekeyIkeLocalCreate); 6943 } 6944 verifyMobikeLocalInfoSendsRequest( boolean migrateToIpv4, boolean natSupported, boolean natDetected, boolean expectNatDetection)6945 private void verifyMobikeLocalInfoSendsRequest( 6946 boolean migrateToIpv4, 6947 boolean natSupported, 6948 boolean natDetected, 6949 boolean expectNatDetection) 6950 throws Exception { 6951 // IKE Session is set up with IPv4 address and with NAT detected 6952 setupIdleStateMachineWithMobike(); 6953 6954 if (natSupported) { 6955 mSpyIkeConnectionCtrl.setNatDetected(natDetected); 6956 } else { 6957 mSpyIkeConnectionCtrl.markSeverNattUnsupported(); 6958 } 6959 6960 if (!migrateToIpv4) { 6961 mSpyIkeConnectionCtrl.setLocalAddress(LOCAL_ADDRESS_V6); 6962 mSpyIkeConnectionCtrl.setRemoteAddress(REMOTE_ADDRESS_V6); 6963 } 6964 6965 mIkeSessionStateMachine.sendMessage( 6966 CMD_FORCE_TRANSITION, mIkeSessionStateMachine.mMobikeLocalInfo); 6967 mLooper.dispatchAll(); 6968 6969 verifyUpdateSaAddressesReq(expectNatDetection); 6970 } 6971 6972 @Test 6973 @SdkSuppress(minSdkVersion = 31, codeName = "S") testMobikeLocalInfoSendsRequestNatDetectedIpv4()6974 public void testMobikeLocalInfoSendsRequestNatDetectedIpv4() throws Exception { 6975 verifyMobikeLocalInfoSendsRequest( 6976 true /* migrateToIpv4 */, 6977 true /* natSupported */, 6978 true /* natDetected */, 6979 true /* expectNatDetection */); 6980 } 6981 6982 @Test 6983 @SdkSuppress(minSdkVersion = 31, codeName = "S") testMobikeLocalInfoSendsRequestNatNotDetectedIpv4()6984 public void testMobikeLocalInfoSendsRequestNatNotDetectedIpv4() throws Exception { 6985 verifyMobikeLocalInfoSendsRequest( 6986 true /* migrateToIpv4 */, 6987 true /* natSupported */, 6988 false /* natDetected */, 6989 true /* expectNatDetection */); 6990 } 6991 6992 @Test 6993 @SdkSuppress(minSdkVersion = 31, codeName = "S") testMobikeLocalInfoSendsRequestNattUnsupportedIpv4()6994 public void testMobikeLocalInfoSendsRequestNattUnsupportedIpv4() throws Exception { 6995 verifyMobikeLocalInfoSendsRequest( 6996 true /* migrateToIpv4 */, 6997 false /* natSupported */, 6998 false /* natDetected */, 6999 false /* expectNatDetection */); 7000 } 7001 7002 @Test 7003 @SdkSuppress(minSdkVersion = 31, codeName = "S") testMobikeLocalInfoSendsRequestNatDetectedIpv6()7004 public void testMobikeLocalInfoSendsRequestNatDetectedIpv6() throws Exception { 7005 verifyMobikeLocalInfoSendsRequest( 7006 false /* migrateToIpv4 */, 7007 true /* natSupported */, 7008 true /* natDetected */, 7009 true /* expectNatDetection */); 7010 } 7011 7012 @Test 7013 @SdkSuppress(minSdkVersion = 31, codeName = "S") testMobikeLocalInfoSendsRequestNatNotDetectedIpv6()7014 public void testMobikeLocalInfoSendsRequestNatNotDetectedIpv6() throws Exception { 7015 verifyMobikeLocalInfoSendsRequest( 7016 false /* migrateToIpv4 */, 7017 true /* natSupported */, 7018 false /* natDetected */, 7019 false /* expectNatDetection */); 7020 } 7021 7022 @Test 7023 @SdkSuppress(minSdkVersion = 31, codeName = "S") testMobikeLocalInfoSendsRequestNattUnsupportedIpv6()7024 public void testMobikeLocalInfoSendsRequestNattUnsupportedIpv6() throws Exception { 7025 verifyMobikeLocalInfoSendsRequest( 7026 false /* migrateToIpv4 */, 7027 false /* natSupported */, 7028 false /* natDetected */, 7029 false /* expectNatDetection */); 7030 } 7031 7032 @Test 7033 @SdkSuppress(minSdkVersion = 31, codeName = "S") testMobikeLocalInfoHandlesResponseWithNatDetection()7034 public void testMobikeLocalInfoHandlesResponseWithNatDetection() throws Exception { 7035 setupIdleStateMachineWithMobike(); 7036 7037 mIkeSessionStateMachine.sendMessage( 7038 CMD_FORCE_TRANSITION, mIkeSessionStateMachine.mMobikeLocalInfo); 7039 mLooper.dispatchAll(); 7040 7041 verifyUpdateSaAddressesResp( 7042 true /* expectNatDetected */, 7043 mSpyIkeConnectionCtrl.getNetwork(), 7044 mSpyIkeConnectionCtrl.getLocalAddress(), 7045 mSpyIkeConnectionCtrl.getRemoteAddress()); 7046 } 7047 7048 @Test 7049 @SdkSuppress(minSdkVersion = 31, codeName = "S") testMobikeLocalInfoHandlesResponseWithoutNatDetection()7050 public void testMobikeLocalInfoHandlesResponseWithoutNatDetection() throws Exception { 7051 setupIdleStateMachineWithMobike(); 7052 mSpyIkeConnectionCtrl.markSeverNattUnsupported(); 7053 7054 mIkeSessionStateMachine.sendMessage( 7055 CMD_FORCE_TRANSITION, mIkeSessionStateMachine.mMobikeLocalInfo); 7056 mLooper.dispatchAll(); 7057 7058 verifyUpdateSaAddressesResp( 7059 false /* expectNatDetected */, 7060 mSpyIkeConnectionCtrl.getNetwork(), 7061 mSpyIkeConnectionCtrl.getLocalAddress(), 7062 mSpyIkeConnectionCtrl.getRemoteAddress()); 7063 } 7064 7065 @Test 7066 @SdkSuppress(minSdkVersion = 31, codeName = "S") testMobikeLocalInfoHandlesResponseWithNatDetectedIpv6()7067 public void testMobikeLocalInfoHandlesResponseWithNatDetectedIpv6() throws Exception { 7068 setupIdleStateMachineWithMobike(); 7069 7070 // Migrate to Ipv6 7071 mSpyIkeConnectionCtrl.setLocalAddress(LOCAL_ADDRESS_V6); 7072 mSpyIkeConnectionCtrl.setRemoteAddress(REMOTE_ADDRESS_V6); 7073 7074 mIkeSessionStateMachine.sendMessage( 7075 CMD_FORCE_TRANSITION, mIkeSessionStateMachine.mMobikeLocalInfo); 7076 mLooper.dispatchAll(); 7077 7078 // Send response with NAT_DETECTION payloads 7079 List<Integer> respPayloadTypeList = new ArrayList<>(); 7080 List<String> respPayloadHexStringList = new ArrayList<>(); 7081 respPayloadTypeList.add(PAYLOAD_TYPE_NOTIFY); 7082 respPayloadTypeList.add(PAYLOAD_TYPE_NOTIFY); 7083 respPayloadHexStringList.add(NAT_DETECTION_SOURCE_PAYLOAD_HEX_STRING); 7084 respPayloadHexStringList.add(NAT_DETECTION_DESTINATION_PAYLOAD_HEX_STRING); 7085 7086 ReceivedIkePacket respIkePacket = 7087 makeDummyEncryptedReceivedIkePacket( 7088 mSpyCurrentIkeSaRecord, 7089 EXCHANGE_TYPE_INFORMATIONAL, 7090 true /* isResp */, 7091 respPayloadTypeList, 7092 respPayloadHexStringList); 7093 mIkeSessionStateMachine.sendMessage(CMD_RECEIVE_IKE_PACKET, respIkePacket); 7094 mLooper.dispatchAll(); 7095 7096 // Verify IKE Session was closed properly 7097 assertNull(mIkeSessionStateMachine.getCurrentState()); 7098 verify(mMockIkeSessionCallback).onClosedWithException(any(IkeInternalException.class)); 7099 } 7100 verifyUpdateSaAddressesReq(boolean expectNatDetection)7101 private void verifyUpdateSaAddressesReq(boolean expectNatDetection) throws Exception { 7102 List<IkePayload> reqPayloadList = verifyOutInfoMsgHeaderAndGetPayloads(false /* isResp */); 7103 int expectedPayloads = expectNatDetection ? 3 : 1; 7104 assertEquals(expectedPayloads, reqPayloadList.size()); 7105 assertTrue(isNotifyExist(reqPayloadList, NOTIFY_TYPE_UPDATE_SA_ADDRESSES)); 7106 7107 if (expectNatDetection) { 7108 assertTrue(isNotifyExist(reqPayloadList, NOTIFY_TYPE_NAT_DETECTION_SOURCE_IP)); 7109 assertTrue(isNotifyExist(reqPayloadList, NOTIFY_TYPE_NAT_DETECTION_DESTINATION_IP)); 7110 } 7111 } 7112 verifyUpdateSaAddressesResp( boolean expectNatDetected, Network expectedNetwork, InetAddress expectedLocalAddr, InetAddress expectedRemoteAddr)7113 private void verifyUpdateSaAddressesResp( 7114 boolean expectNatDetected, 7115 Network expectedNetwork, 7116 InetAddress expectedLocalAddr, 7117 InetAddress expectedRemoteAddr) 7118 throws Exception { 7119 List<Integer> respPayloadTypeList = new ArrayList<>(); 7120 List<String> respPayloadHexStringList = new ArrayList<>(); 7121 7122 // For simplicity, if the test tries to verify a case when there is not NAT detected, just 7123 // do not include NAT Detection payload in the response 7124 if (!expectNatDetected) { 7125 respPayloadTypeList.add(PAYLOAD_TYPE_NOTIFY); 7126 respPayloadHexStringList.add(NAT_DETECTION_SOURCE_PAYLOAD_HEX_STRING); 7127 7128 respPayloadTypeList.add(PAYLOAD_TYPE_NOTIFY); 7129 respPayloadHexStringList.add(NAT_DETECTION_DESTINATION_PAYLOAD_HEX_STRING); 7130 } 7131 7132 ReceivedIkePacket respIkePacket = 7133 makeDummyEncryptedReceivedIkePacket( 7134 mSpyCurrentIkeSaRecord, 7135 EXCHANGE_TYPE_INFORMATIONAL, 7136 true /* isResp */, 7137 respPayloadTypeList, 7138 respPayloadHexStringList); 7139 mIkeSessionStateMachine.sendMessage(CMD_RECEIVE_IKE_PACKET, respIkePacket); 7140 mLooper.dispatchAll(); 7141 7142 int expectedNatStatus = expectNatDetected ? NAT_DETECTED : NAT_TRAVERSAL_UNSUPPORTED; 7143 assertEquals(expectedNatStatus, mSpyIkeConnectionCtrl.getNatStatus()); 7144 7145 ArgumentCaptor<IkeSessionConnectionInfo> connectionInfoCaptor = 7146 ArgumentCaptor.forClass(IkeSessionConnectionInfo.class); 7147 verify(mMockIkeSessionCallback) 7148 .onIkeSessionConnectionInfoChanged(connectionInfoCaptor.capture()); 7149 7150 IkeSessionConnectionInfo newConnectionInfo = connectionInfoCaptor.getValue(); 7151 assertEquals(expectedNetwork, newConnectionInfo.getNetwork()); 7152 assertEquals(expectedLocalAddr, newConnectionInfo.getLocalAddress()); 7153 assertEquals(expectedRemoteAddr, newConnectionInfo.getRemoteAddress()); 7154 7155 // TODO(b/172015298): verify IPsec SAs migrated instead of rekey when kernel supports it 7156 7157 // Verify that Child Rekey (MOBIKE) initiated after successful UPDATE_SA_ADDRESSES resp 7158 assertTrue( 7159 mIkeSessionStateMachine.getCurrentState() 7160 instanceof IkeSessionStateMachine.ChildProcedureOngoing); 7161 verify(mMockChildSessionStateMachine) 7162 .performMigration(eq(expectedLocalAddr), eq(expectedRemoteAddr), any()); 7163 } 7164 7165 @Test 7166 @SdkSuppress(minSdkVersion = 31, codeName = "S") testNattKeepaliveStoppedDuringMobilityEvent()7167 public void testNattKeepaliveStoppedDuringMobilityEvent() throws Exception { 7168 // IKE Session established with IPv4 address and a NAT detected 7169 IkeNetworkCallbackBase callback = setupIdleStateMachineWithMobike(); 7170 7171 verifySetNetwork( 7172 callback, 7173 null /* rekeySaRecord */, 7174 mIkeSessionStateMachine.mMobikeLocalInfo, 7175 false /* isIpv4 */); 7176 7177 // Keepalive for the old UDP encap socket stopped 7178 verify(mMockIkeNattKeepalive).stop(); 7179 7180 // Keepalive is no longer needed since IKE Session switches to IPv6 7181 assertNull(mSpyIkeConnectionCtrl.getIkeNattKeepalive()); 7182 } 7183 7184 @Test 7185 @SdkSuppress(minSdkVersion = 31, codeName = "S") testMobikeLocalInfoHandlesDeleteRequest()7186 public void testMobikeLocalInfoHandlesDeleteRequest() throws Exception { 7187 setupIdleStateMachineWithMobike(); 7188 7189 mIkeSessionStateMachine.sendMessage( 7190 CMD_FORCE_TRANSITION, mIkeSessionStateMachine.mMobikeLocalInfo); 7191 mLooper.dispatchAll(); 7192 7193 // Reset to ignore UPDATE_SA_ADDRESSES req sent when entering MobikeLocalInfo 7194 resetMockIkeMessageHelper(); 7195 7196 // Reset to ignore IkeSessionCallback#onOpened from setting up the state machine 7197 resetSpyUserCbExecutor(); 7198 7199 verifyIkeDeleteRequestHandled(); 7200 } 7201 7202 @Test 7203 @SdkSuppress(minSdkVersion = 31, codeName = "S") testMobikeLocalInfoHandlesNonDeleteRequest()7204 public void testMobikeLocalInfoHandlesNonDeleteRequest() throws Exception { 7205 setupIdleStateMachineWithMobike(); 7206 7207 mIkeSessionStateMachine.sendMessage( 7208 CMD_FORCE_TRANSITION, mIkeSessionStateMachine.mMobikeLocalInfo); 7209 mLooper.dispatchAll(); 7210 7211 // Reset to ignore UPDATE_SA_ADDRESSES req sent when entering MobikeLocalInfo 7212 resetMockIkeMessageHelper(); 7213 7214 mIkeSessionStateMachine.sendMessage( 7215 CMD_RECEIVE_IKE_PACKET, makeRoutabilityCheckIkeRequest()); 7216 mLooper.dispatchAll(); 7217 7218 verifyIncrementRemoteReqMsgId(); 7219 7220 List<IkePayload> respPayloads = verifyOutInfoMsgHeaderAndGetPayloads(true /* isResp */); 7221 assertEquals(1, respPayloads.size()); 7222 IkeNotifyPayload notifyPayload = (IkeNotifyPayload) respPayloads.get(0); 7223 assertEquals(ERROR_TYPE_TEMPORARY_FAILURE, notifyPayload.notifyType); 7224 7225 assertEquals( 7226 mIkeSessionStateMachine.mMobikeLocalInfo, 7227 mIkeSessionStateMachine.getCurrentState()); 7228 } 7229 setupAndVerifyDnsLookupsOnSetNetwork( int dnsLookupsForSuccess, int expectedDnsLookups, boolean expectSessionClosed)7230 private void setupAndVerifyDnsLookupsOnSetNetwork( 7231 int dnsLookupsForSuccess, int expectedDnsLookups, boolean expectSessionClosed) 7232 throws Exception { 7233 final IkeNetworkCallbackBase callback = setupIdleStateMachineWithMobike(); 7234 7235 final Network newNetwork = 7236 mockNewNetworkAndAddress( 7237 false /* isIpv4 */, 7238 UPDATED_LOCAL_ADDRESS_V6, 7239 REMOTE_ADDRESS_V6, 7240 dnsLookupsForSuccess); 7241 7242 mIkeSessionStateMachine.setNetwork(newNetwork, 7243 IkeSessionParams.ESP_IP_VERSION_AUTO, 7244 IkeSessionParams.ESP_ENCAP_TYPE_AUTO, 7245 IkeSessionParams.NATT_KEEPALIVE_INTERVAL_AUTO); 7246 mLooper.dispatchAll(); 7247 7248 verify(newNetwork, times(expectedDnsLookups)).getAllByName(REMOTE_HOSTNAME); 7249 if (expectSessionClosed) { 7250 assertNull(mIkeSessionStateMachine.getCurrentState()); 7251 verifyFireCallbackOnDnsFailure(mMockIkeSessionCallback); 7252 } else { 7253 assertTrue(mSpyIkeConnectionCtrl.getAllRemoteIpv4Addresses().isEmpty()); 7254 assertEquals( 7255 Arrays.asList(REMOTE_ADDRESS_V6), 7256 mSpyIkeConnectionCtrl.getAllRemoteIpv6Addresses()); 7257 verifyNetworkAndLocalAddressUpdated( 7258 newNetwork, UPDATED_LOCAL_ADDRESS_V6, REMOTE_ADDRESS_V6, callback); 7259 } 7260 } 7261 7262 @Test 7263 @SdkSuppress(minSdkVersion = 31, codeName = "S") testDnsLookupOnSetNetwork()7264 public void testDnsLookupOnSetNetwork() throws Exception { 7265 setupAndVerifyDnsLookupsOnSetNetwork( 7266 1 /* dnsLookupsForSuccess */, 7267 1 /* expectedDnsLookups */, 7268 false /* expectSessionClosed */); 7269 } 7270 7271 @Test 7272 @SdkSuppress(minSdkVersion = 31, codeName = "S") testDnsLookupOnSetNetworkWithDnsRetries()7273 public void testDnsLookupOnSetNetworkWithDnsRetries() throws Exception { 7274 setupAndVerifyDnsLookupsOnSetNetwork( 7275 2 /* dnsLookupsForSuccess */, 7276 2 /* expectedDnsLookups */, 7277 false /* expectSessionClosed */); 7278 } 7279 7280 @Test 7281 @SdkSuppress(minSdkVersion = 31, codeName = "S") testDnsLookupOnSetNetworkWithDnsFailure()7282 public void testDnsLookupOnSetNetworkWithDnsFailure() throws Exception { 7283 // Require more lookups for successful DNS than IKE allows to force failure 7284 setupAndVerifyDnsLookupsOnSetNetwork( 7285 4 /* dnsLookupsForSuccess */, 7286 3 /* expectedDnsLookups */, 7287 true /* expectSessionClosed */); 7288 } 7289 7290 @Test testNattKeepaliveStarts()7291 public void testNattKeepaliveStarts() throws Exception { 7292 IkeSessionParams sessionParams = 7293 buildIkeSessionParamsCommon() 7294 .setAuthPsk(mPsk) 7295 .build(); 7296 7297 // Restart IkeSessionStateMachine with NATT Keepalive delay configured 7298 setupFirstIkeSa(); 7299 mIkeSessionStateMachine.quitNow(); 7300 7301 mIkeSessionStateMachine = makeAndStartIkeSession(sessionParams); 7302 mIkeSessionStateMachine.openSession(); 7303 mLooper.dispatchAll(); 7304 7305 mIkeSessionStateMachine.sendMessage(CMD_RECEIVE_IKE_PACKET, makeIkeInitResponse()); 7306 mLooper.dispatchAll(); 7307 7308 verify(mMockIkeNattKeepalive).start(); 7309 } 7310 7311 @Test testHandleRetransmissionTimeout()7312 public void testHandleRetransmissionTimeout() throws Exception { 7313 mIkeSessionStateMachine.sendMessage(IkeSessionStateMachine.CMD_LOCAL_REQUEST_CREATE_IKE); 7314 7315 for (long delay : 7316 mIkeSessionStateMachine.mIkeSessionParams.getRetransmissionTimeoutsMillis()) { 7317 mLooper.dispatchAll(); 7318 mLooper.moveTimeForward(delay); 7319 } 7320 7321 mLooper.dispatchAll(); 7322 assertNull(mIkeSessionStateMachine.getCurrentState()); 7323 7324 if (SdkLevel.isAtLeastT()) { 7325 verify(mMockIkeSessionCallback).onClosedWithException( 7326 argThat(e -> e instanceof IkeIOException 7327 && e.getCause() instanceof IkeTimeoutException)); 7328 } else { 7329 verify(mMockIkeSessionCallback).onClosedWithException( 7330 argThat(e -> e instanceof IkeInternalException 7331 && e.getCause() instanceof IOException)); 7332 } 7333 } 7334 } 7335