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