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