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.ike;
18 
19 import static android.net.ipsec.ike.IkeSessionConfiguration.EXTENSION_TYPE_FRAGMENTATION;
20 import static android.net.ipsec.ike.IkeSessionParams.IKE_OPTION_EAP_ONLY_AUTH;
21 import static android.net.ipsec.ike.exceptions.IkeProtocolException.ERROR_TYPE_AUTHENTICATION_FAILED;
22 import static android.net.ipsec.ike.exceptions.IkeProtocolException.ERROR_TYPE_CHILD_SA_NOT_FOUND;
23 import static android.net.ipsec.ike.exceptions.IkeProtocolException.ERROR_TYPE_INTERNAL_ADDRESS_FAILURE;
24 import static android.net.ipsec.ike.exceptions.IkeProtocolException.ERROR_TYPE_INVALID_SYNTAX;
25 import static android.net.ipsec.ike.exceptions.IkeProtocolException.ERROR_TYPE_NO_ADDITIONAL_SAS;
26 import static android.net.ipsec.ike.exceptions.IkeProtocolException.ERROR_TYPE_NO_PROPOSAL_CHOSEN;
27 import static android.net.ipsec.ike.exceptions.IkeProtocolException.ERROR_TYPE_TEMPORARY_FAILURE;
28 import static android.net.ipsec.ike.exceptions.IkeProtocolException.ERROR_TYPE_UNSUPPORTED_CRITICAL_PAYLOAD;
29 import static android.system.OsConstants.AF_INET;
30 import static android.system.OsConstants.AF_INET6;
31 
32 import static com.android.internal.net.TestUtils.createMockRandomFactory;
33 import static com.android.internal.net.ipsec.ike.AbstractSessionStateMachine.RETRY_INTERVAL_MS;
34 import static com.android.internal.net.ipsec.ike.IkeSessionStateMachine.CMD_FORCE_TRANSITION;
35 import static com.android.internal.net.ipsec.ike.IkeSessionStateMachine.CMD_RECEIVE_IKE_PACKET;
36 import static com.android.internal.net.ipsec.ike.IkeSessionStateMachine.IKE_EXCHANGE_SUBTYPE_DELETE_CHILD;
37 import static com.android.internal.net.ipsec.ike.IkeSessionStateMachine.IKE_EXCHANGE_SUBTYPE_REKEY_CHILD;
38 import static com.android.internal.net.ipsec.ike.IkeSessionStateMachine.RETRY_INTERVAL_MS;
39 import static com.android.internal.net.ipsec.ike.IkeSessionStateMachine.TEMP_FAILURE_RETRY_TIMEOUT_MS;
40 import static com.android.internal.net.ipsec.ike.message.IkeConfigPayload.CONFIG_ATTR_APPLICATION_VERSION;
41 import static com.android.internal.net.ipsec.ike.message.IkeConfigPayload.CONFIG_ATTR_INTERNAL_IP4_ADDRESS;
42 import static com.android.internal.net.ipsec.ike.message.IkeConfigPayload.CONFIG_ATTR_INTERNAL_IP4_NETMASK;
43 import static com.android.internal.net.ipsec.ike.message.IkeConfigPayload.CONFIG_ATTR_INTERNAL_IP6_ADDRESS;
44 import static com.android.internal.net.ipsec.ike.message.IkeConfigPayload.CONFIG_ATTR_IP4_PCSCF;
45 import static com.android.internal.net.ipsec.ike.message.IkeConfigPayload.CONFIG_ATTR_IP6_PCSCF;
46 import static com.android.internal.net.ipsec.ike.message.IkeHeader.EXCHANGE_TYPE_CREATE_CHILD_SA;
47 import static com.android.internal.net.ipsec.ike.message.IkeHeader.EXCHANGE_TYPE_INFORMATIONAL;
48 import static com.android.internal.net.ipsec.ike.message.IkeNotifyPayload.NOTIFY_TYPE_EAP_ONLY_AUTHENTICATION;
49 import static com.android.internal.net.ipsec.ike.message.IkeNotifyPayload.NOTIFY_TYPE_IKEV2_FRAGMENTATION_SUPPORTED;
50 import static com.android.internal.net.ipsec.ike.message.IkeNotifyPayload.NOTIFY_TYPE_NAT_DETECTION_DESTINATION_IP;
51 import static com.android.internal.net.ipsec.ike.message.IkeNotifyPayload.NOTIFY_TYPE_NAT_DETECTION_SOURCE_IP;
52 import static com.android.internal.net.ipsec.ike.message.IkeNotifyPayload.NOTIFY_TYPE_SIGNATURE_HASH_ALGORITHMS;
53 import static com.android.internal.net.ipsec.ike.message.IkePayload.PAYLOAD_TYPE_AUTH;
54 import static com.android.internal.net.ipsec.ike.message.IkePayload.PAYLOAD_TYPE_NOTIFY;
55 import static com.android.internal.net.ipsec.ike.message.IkePayload.PAYLOAD_TYPE_SA;
56 
57 import static org.junit.Assert.assertArrayEquals;
58 import static org.junit.Assert.assertEquals;
59 import static org.junit.Assert.assertFalse;
60 import static org.junit.Assert.assertNotEquals;
61 import static org.junit.Assert.assertNotNull;
62 import static org.junit.Assert.assertNull;
63 import static org.junit.Assert.assertTrue;
64 import static org.junit.Assert.fail;
65 import static org.mockito.Matchers.any;
66 import static org.mockito.Matchers.anyBoolean;
67 import static org.mockito.Matchers.anyInt;
68 import static org.mockito.Matchers.anyLong;
69 import static org.mockito.Matchers.anyObject;
70 import static org.mockito.Matchers.anyString;
71 import static org.mockito.Matchers.argThat;
72 import static org.mockito.Matchers.eq;
73 import static org.mockito.Mockito.doAnswer;
74 import static org.mockito.Mockito.doNothing;
75 import static org.mockito.Mockito.doReturn;
76 import static org.mockito.Mockito.doThrow;
77 import static org.mockito.Mockito.mock;
78 import static org.mockito.Mockito.never;
79 import static org.mockito.Mockito.reset;
80 import static org.mockito.Mockito.spy;
81 import static org.mockito.Mockito.times;
82 import static org.mockito.Mockito.verify;
83 import static org.mockito.Mockito.when;
84 
85 import android.app.AlarmManager;
86 import android.content.Context;
87 import android.net.eap.EapSessionConfig;
88 import android.net.ipsec.ike.ChildSaProposal;
89 import android.net.ipsec.ike.ChildSessionCallback;
90 import android.net.ipsec.ike.ChildSessionParams;
91 import android.net.ipsec.ike.IkeFqdnIdentification;
92 import android.net.ipsec.ike.IkeIdentification;
93 import android.net.ipsec.ike.IkeIpv4AddrIdentification;
94 import android.net.ipsec.ike.IkeManager;
95 import android.net.ipsec.ike.IkeSaProposal;
96 import android.net.ipsec.ike.IkeSessionCallback;
97 import android.net.ipsec.ike.IkeSessionConfiguration;
98 import android.net.ipsec.ike.IkeSessionConnectionInfo;
99 import android.net.ipsec.ike.IkeSessionParams;
100 import android.net.ipsec.ike.SaProposal;
101 import android.net.ipsec.ike.TunnelModeChildSessionParams;
102 import android.net.ipsec.ike.exceptions.IkeException;
103 import android.net.ipsec.ike.exceptions.IkeInternalException;
104 import android.net.ipsec.ike.exceptions.IkeProtocolException;
105 import android.os.Looper;
106 import android.os.test.TestLooper;
107 import android.telephony.TelephonyManager;
108 
109 import com.android.internal.net.TestUtils;
110 import com.android.internal.net.eap.EapAuthenticator;
111 import com.android.internal.net.eap.IEapCallback;
112 import com.android.internal.net.ipsec.ike.ChildSessionStateMachine.IChildSessionSmCallback;
113 import com.android.internal.net.ipsec.ike.ChildSessionStateMachineFactory.ChildSessionFactoryHelper;
114 import com.android.internal.net.ipsec.ike.ChildSessionStateMachineFactory.IChildSessionFactoryHelper;
115 import com.android.internal.net.ipsec.ike.IkeLocalRequestScheduler.ChildLocalRequest;
116 import com.android.internal.net.ipsec.ike.IkeLocalRequestScheduler.IkeLocalRequest;
117 import com.android.internal.net.ipsec.ike.IkeSessionStateMachine.ReceivedIkePacket;
118 import com.android.internal.net.ipsec.ike.SaRecord.ISaRecordHelper;
119 import com.android.internal.net.ipsec.ike.SaRecord.IkeSaRecord;
120 import com.android.internal.net.ipsec.ike.SaRecord.IkeSaRecordConfig;
121 import com.android.internal.net.ipsec.ike.SaRecord.SaLifetimeAlarmScheduler;
122 import com.android.internal.net.ipsec.ike.SaRecord.SaRecordHelper;
123 import com.android.internal.net.ipsec.ike.crypto.IkeCipher;
124 import com.android.internal.net.ipsec.ike.crypto.IkeMacIntegrity;
125 import com.android.internal.net.ipsec.ike.crypto.IkeMacPrf;
126 import com.android.internal.net.ipsec.ike.exceptions.AuthenticationFailedException;
127 import com.android.internal.net.ipsec.ike.exceptions.InvalidSyntaxException;
128 import com.android.internal.net.ipsec.ike.exceptions.NoValidProposalChosenException;
129 import com.android.internal.net.ipsec.ike.exceptions.UnsupportedCriticalPayloadException;
130 import com.android.internal.net.ipsec.ike.message.IkeAuthDigitalSignPayload;
131 import com.android.internal.net.ipsec.ike.message.IkeAuthPayload;
132 import com.android.internal.net.ipsec.ike.message.IkeAuthPskPayload;
133 import com.android.internal.net.ipsec.ike.message.IkeCertX509CertPayload;
134 import com.android.internal.net.ipsec.ike.message.IkeConfigPayload;
135 import com.android.internal.net.ipsec.ike.message.IkeDeletePayload;
136 import com.android.internal.net.ipsec.ike.message.IkeEapPayload;
137 import com.android.internal.net.ipsec.ike.message.IkeHeader;
138 import com.android.internal.net.ipsec.ike.message.IkeIdPayload;
139 import com.android.internal.net.ipsec.ike.message.IkeInformationalPayload;
140 import com.android.internal.net.ipsec.ike.message.IkeKePayload;
141 import com.android.internal.net.ipsec.ike.message.IkeMessage;
142 import com.android.internal.net.ipsec.ike.message.IkeMessage.DecodeResult;
143 import com.android.internal.net.ipsec.ike.message.IkeMessage.DecodeResultOk;
144 import com.android.internal.net.ipsec.ike.message.IkeMessage.DecodeResultPartial;
145 import com.android.internal.net.ipsec.ike.message.IkeMessage.DecodeResultProtectedError;
146 import com.android.internal.net.ipsec.ike.message.IkeMessage.DecodeResultUnprotectedError;
147 import com.android.internal.net.ipsec.ike.message.IkeMessage.IIkeMessageHelper;
148 import com.android.internal.net.ipsec.ike.message.IkeMessage.IkeMessageHelper;
149 import com.android.internal.net.ipsec.ike.message.IkeNoncePayload;
150 import com.android.internal.net.ipsec.ike.message.IkeNotifyPayload;
151 import com.android.internal.net.ipsec.ike.message.IkePayload;
152 import com.android.internal.net.ipsec.ike.message.IkeSaPayload;
153 import com.android.internal.net.ipsec.ike.message.IkeSaPayload.DhGroupTransform;
154 import com.android.internal.net.ipsec.ike.message.IkeSaPayload.EncryptionTransform;
155 import com.android.internal.net.ipsec.ike.message.IkeSaPayload.IntegrityTransform;
156 import com.android.internal.net.ipsec.ike.message.IkeSaPayload.PrfTransform;
157 import com.android.internal.net.ipsec.ike.message.IkeSkfPayload;
158 import com.android.internal.net.ipsec.ike.message.IkeTestUtils;
159 import com.android.internal.net.ipsec.ike.message.IkeTsPayload;
160 import com.android.internal.net.ipsec.ike.testmode.DeterministicSecureRandom;
161 import com.android.internal.net.ipsec.ike.testutils.CertUtils;
162 import com.android.internal.net.ipsec.ike.utils.IkeSecurityParameterIndex;
163 import com.android.internal.net.ipsec.ike.utils.IkeSpiGenerator;
164 import com.android.internal.net.ipsec.ike.utils.IpSecSpiGenerator;
165 import com.android.internal.net.ipsec.ike.utils.RandomnessFactory;
166 import com.android.internal.net.ipsec.ike.utils.State;
167 import com.android.internal.net.utils.Log;
168 
169 import org.junit.After;
170 import org.junit.Before;
171 import org.junit.Ignore;
172 import org.junit.Test;
173 import org.mockito.ArgumentCaptor;
174 import org.mockito.invocation.InvocationOnMock;
175 
176 import java.io.IOException;
177 import java.net.Inet4Address;
178 import java.net.InetAddress;
179 import java.security.GeneralSecurityException;
180 import java.security.PrivateKey;
181 import java.security.SecureRandom;
182 import java.security.cert.X509Certificate;
183 import java.util.Arrays;
184 import java.util.Collections;
185 import java.util.HashMap;
186 import java.util.LinkedList;
187 import java.util.List;
188 import java.util.Map;
189 import java.util.concurrent.Executor;
190 
191 public final class IkeSessionStateMachineTest extends IkeSessionTestBase {
192     private static final String TAG = "IkeSessionStateMachineTest";
193 
194     private static final String IKE_INIT_RESP_HEX_STRING =
195             "5f54bf6d8b48e6e1909232b3d1edcb5c21202220000000000000014c220000300000"
196                     + "002c010100040300000c0100000c800e008003000008030000020300000802000002"
197                     + "00000008040000022800008800020000fe014fefed55a4229928bfa3dad1ea6ffaca"
198                     + "abfb5f5bdd71790e99a192530e3f849d3a3d96dc6e0a7a10ff6f72a6162103ac573c"
199                     + "acd41d08b7a034cad8f5eab09c14ced5a9e4af5692dff028f21c1119dd75226b6af6"
200                     + "b2f009245369c9892cc5742e5c94a254ebff052470771fb2cb4f29a35d8953e18a1a"
201                     + "6c6fbc56acc188a5290000249756112ca539f5c25abacc7ee92b73091942a9c06950"
202                     + "f98848f1af1694c4ddff2900001c00004004c53f054b976a25d75fde72dbf1c7b6c8"
203                     + "c9aa9ca12900001c00004005b16d79b21c1bc89ca7350f42de805be0227e2ed62b00"
204                     + "00080000401400000014882fe56d6fd20dbc2251613b2ebe5beb";
205     private static final String IKE_SA_PAYLOAD_HEX_STRING =
206             "220000300000002c010100040300000c0100000c800e00800300000803000002030"
207                     + "00008020000020000000804000002";
208     private static final String IKE_REKEY_SA_PAYLOAD_HEX_STRING =
209             "22000038000000340101080400000000000000FF0300000c0100000c800e0080030"
210                     + "000080300000203000008020000020000000804000002";
211     private static final String IKE_REKEY_UNACCEPTABLE_SA_PAYLOAD_HEX_STRING =
212             "22000038000000340101080400000000000000FF0300000c0100000c800e0080030"
213                     + "00008030000020300000802000002000000080400000e";
214     private static final int IKE_REKEY_SA_INITIATOR_SPI = 0xff;
215     private static final String KE_PAYLOAD_HEX_STRING =
216             "2800008800020000b4a2faf4bb54878ae21d638512ece55d9236fc50"
217                     + "46ab6cef82220f421f3ce6361faf36564ecb6d28798a94aa"
218                     + "d7b2b4b603ddeaaa5630adb9ece8ac37534036040610ebdd"
219                     + "92f46bef84f0be7db860351843858f8acf87056e272377f7"
220                     + "0c9f2d81e29c7b0ce4f291a3a72476bb0b278fd4b7b0a4c2"
221                     + "6bbeb08214c7071376079587";
222     private static final String INVALID_KE_PAYLOAD_HEX_STRING = "0000000a00000011000e";
223     private static final String NONCE_INIT_PAYLOAD_HEX_STRING =
224             "29000024c39b7f368f4681b89fa9b7be6465abd7c5f68b6ed5d3b4c72cb4240eb5c46412";
225     private static final String NONCE_RESP_PAYLOAD_HEX_STRING =
226             "290000249756112ca539f5c25abacc7ee92b73091942a9c06950f98848f1af1694c4ddff";
227     private static final String NONCE_INIT_HEX_STRING =
228             "c39b7f368f4681b89fa9b7be6465abd7c5f68b6ed5d3b4c72cb4240eb5c46412";
229     private static final String NONCE_RESP_HEX_STRING =
230             "9756112ca539f5c25abacc7ee92b73091942a9c06950f98848f1af1694c4ddff";
231     private static final String NAT_DETECTION_SOURCE_PAYLOAD_HEX_STRING =
232             "2900001c00004004e54f73b7d83f6beb881eab2051d8663f421d10b0";
233     private static final String NAT_DETECTION_DESTINATION_PAYLOAD_HEX_STRING =
234             "2900001c00004005d915368ca036004cb578ae3e3fb268509aeab190";
235     private static final String FRAGMENTATION_SUPPORTED_PAYLOAD_HEX_STRING = "290000080000402e";
236     private static final String SIGNATURE_HASH_SUPPORTED_PAYLOAD_HEX_STRING =
237             "2b00000F0000402f0001000200030004";
238     private static final String DELETE_IKE_PAYLOAD_HEX_STRING = "0000000801000000";
239     private static final String NOTIFY_REKEY_IKE_PAYLOAD_HEX_STRING = "2100000800004009";
240     private static final String ID_PAYLOAD_INITIATOR_HEX_STRING =
241             "290000180200000031313233343536373839414243444546";
242     private static final String ID_PAYLOAD_RESPONDER_HEX_STRING = "2700000c010000007f000001";
243     private static final String ID_PAYLOAD_RESPONDER_FQDN_HEX_STRING =
244             "2700001702000000696B652E616E64726F69642E6E6574";
245     private static final String PSK_AUTH_RESP_PAYLOAD_HEX_STRING =
246             "2100001c0200000058f36412e9b7b38df817a9f7779b7a008dacdd25";
247     private static final String GENERIC_DIGITAL_SIGN_AUTH_RESP_HEX_STRING =
248             "300000580e0000000f300d06092a864886f70d01010b05006f76af4150d653c5d413"
249                     + "6b9f69d905849bf075c563e6d14ccda42361ec3e7d12c72e2dece5711ea1d952f7b8e"
250                     + "12c5d982aa4efdaeac36a02b222aa96242cc424";
251     private static final String CHILD_SA_PAYLOAD_HEX_STRING =
252             "2c00002c0000002801030403cae7019f0300000c0100000c800e008003000008030"
253                     + "000020000000805000000";
254     private static final String TS_INIT_PAYLOAD_HEX_STRING =
255             "2d00001801000000070000100000ffff00000000ffffffff";
256     private static final String TS_RESP_PAYLOAD_HEX_STRING =
257             "2900001801000000070000100000ffff000000000fffffff";
258     private static final String VENDOR_ID_PAYLOAD_HEX_STRING =
259             "0000001852656d6f74652056656e646f72204944204f6e65";
260 
261     private static final String PSK_HEX_STRING = "6A756E69706572313233";
262 
263     private static final String PRF_KEY_INIT_HEX_STRING =
264             "094787780EE466E2CB049FA327B43908BC57E485";
265     private static final String PRF_KEY_RESP_HEX_STRING =
266             "A30E6B08BE56C0E6BFF4744143C75219299E1BEB";
267 
268     private static final String CP_PAYLOAD_HEX_STRING =
269             "210000810200000000080011260010111067a17d000000000a"
270                     + "f68e8640000a0010200148880067ff000643000d000000000"
271                     + "00a0010200148880066ff000645000d0000000000150010200"
272                     + "148880006713a00f10104000000050015001020014888000671"
273                     + "3a00f101040000008900150010200148880005713a00e00104000000c9";
274     private static final String PCSCF_IPV6_ADDRESS1 = "2001:4888:6:713a:f1:104:0:5";
275     private static final String PCSCF_IPV6_ADDRESS2 = "2001:4888:6:713a:f1:104:0:89";
276     private static final String PCSCF_IPV6_ADDRESS3 = "2001:4888:5:713a:e0:104:0:c9";
277 
278     private static final byte[] EAP_DUMMY_MSG = "EAP Message".getBytes();
279     private static final byte[] REMOTE_VENDOR_ID_ONE = "Remote Vendor ID One".getBytes();
280     private static final byte[] REMOTE_VENDOR_ID_TWO = "Remote Vendor ID Two".getBytes();
281 
282     private static final IkeIdentification LOCAL_ID_IPV4 =
283             new IkeIpv4AddrIdentification((Inet4Address) LOCAL_ADDRESS);
284     private static final IkeIdentification REMOTE_ID_FQDN =
285             new IkeFqdnIdentification("server.test.android.net");
286     private static final IkeIdentification REMOTE_ID_IPV4 =
287             new IkeIpv4AddrIdentification((Inet4Address) REMOTE_ADDRESS);
288 
289     private static final int KEY_LEN_IKE_INTE = 20;
290     private static final int KEY_LEN_IKE_ENCR = 16;
291     private static final int KEY_LEN_IKE_PRF = 20;
292     private static final int KEY_LEN_IKE_SKD = KEY_LEN_IKE_PRF;
293 
294     private static final int CHILD_SPI_LOCAL = 0x2ad4c0a2;
295     private static final int CHILD_SPI_REMOTE = 0xcae7019f;
296 
297     private static final int EAP_SIM_SUB_ID = 1;
298 
299     private static final int PAYLOAD_TYPE_UNSUPPORTED = 127;
300 
301     private static final long RETRANSMIT_BACKOFF_TIMEOUT_MS = 5000L;
302 
303     private static final IkeSpiGenerator IKE_SPI_GENERATOR =
304             new IkeSpiGenerator(createMockRandomFactory());
305 
306     private IkeUdpEncapSocket mSpyIkeUdpEncapSocket;
307     private IkeUdp4Socket mSpyIkeUdp4Socket;
308     private IkeUdp6Socket mSpyIkeUdp6Socket;
309     private IkeSocket mSpyCurrentIkeSocket;
310 
311     private TestLooper mLooper;
312     private IkeSessionStateMachine mIkeSessionStateMachine;
313 
314     private byte[] mPsk;
315 
316     private ChildSessionParams mChildSessionParams;
317 
318     private Executor mSpyUserCbExecutor;
319     private IkeSessionCallback mMockIkeSessionCallback;
320     private ChildSessionCallback mMockChildSessionCallback;
321 
322     private EncryptionTransform mIkeEncryptionTransform;
323     private IntegrityTransform mIkeIntegrityTransform;
324     private PrfTransform mIkePrfTransform;
325     private DhGroupTransform mIkeDhGroupTransform;
326 
327     private IIkeMessageHelper mMockIkeMessageHelper;
328     private ISaRecordHelper mMockSaRecordHelper;
329 
330     private ChildSessionStateMachine mMockChildSessionStateMachine;
331     private IChildSessionFactoryHelper mMockChildSessionFactoryHelper;
332     private IChildSessionSmCallback mDummyChildSmCallback;
333 
334     private IkeSaRecord mSpyCurrentIkeSaRecord;
335     private IkeSaRecord mSpyLocalInitIkeSaRecord;
336     private IkeSaRecord mSpyRemoteInitIkeSaRecord;
337 
338     private Log mSpyIkeLog;
339 
340     private int mExpectedCurrentSaLocalReqMsgId;
341     private int mExpectedCurrentSaRemoteReqMsgId;
342 
343     private EapSessionConfig mEapSessionConfig;
344     private IkeEapAuthenticatorFactory mMockEapAuthenticatorFactory;
345     private EapAuthenticator mMockEapAuthenticator;
346 
347     private X509Certificate mRootCertificate;
348     private X509Certificate mServerEndCertificate;
349     private PrivateKey mUserPrivateKey;
350     private X509Certificate mUserEndCert;
351 
352     private ArgumentCaptor<IkeMessage> mIkeMessageCaptor =
353             ArgumentCaptor.forClass(IkeMessage.class);
354     private ArgumentCaptor<IkeSaRecordConfig> mIkeSaRecordConfigCaptor =
355             ArgumentCaptor.forClass(IkeSaRecordConfig.class);
356     private ArgumentCaptor<IChildSessionSmCallback> mChildSessionSmCbCaptor =
357             ArgumentCaptor.forClass(IChildSessionSmCallback.class);
358     private ArgumentCaptor<List<IkePayload>> mPayloadListCaptor =
359             ArgumentCaptor.forClass(List.class);
360 
makeDummyReceivedIkeInitRespPacket( long initiatorSpi, long responderSpi, @IkeHeader.ExchangeType int eType, boolean isResp, boolean fromIkeInit, List<Integer> payloadTypeList, List<String> payloadHexStringList)361     private ReceivedIkePacket makeDummyReceivedIkeInitRespPacket(
362             long initiatorSpi,
363             long responderSpi,
364             @IkeHeader.ExchangeType int eType,
365             boolean isResp,
366             boolean fromIkeInit,
367             List<Integer> payloadTypeList,
368             List<String> payloadHexStringList)
369             throws Exception {
370 
371         List<IkePayload> payloadList =
372                 hexStrListToIkePayloadList(payloadTypeList, payloadHexStringList, isResp);
373         // Build a remotely generated NAT_DETECTION_SOURCE_IP payload to mock a remote node's
374         // network that is not behind NAT.
375         IkePayload sourceNatPayload =
376                 new IkeNotifyPayload(
377                         NOTIFY_TYPE_NAT_DETECTION_SOURCE_IP,
378                         IkeNotifyPayload.generateNatDetectionData(
379                                 initiatorSpi,
380                                 responderSpi,
381                                 REMOTE_ADDRESS,
382                                 IkeSocket.SERVER_PORT_UDP_ENCAPSULATED));
383         payloadList.add(sourceNatPayload);
384         return makeDummyUnencryptedReceivedIkePacket(
385                 initiatorSpi, responderSpi, eType, isResp, fromIkeInit, payloadList);
386     }
387 
makeDummyUnencryptedReceivedIkePacket( long initiatorSpi, long responderSpi, @IkeHeader.ExchangeType int eType, boolean isResp, boolean fromIkeInit, List<IkePayload> payloadList)388     private ReceivedIkePacket makeDummyUnencryptedReceivedIkePacket(
389             long initiatorSpi,
390             long responderSpi,
391             @IkeHeader.ExchangeType int eType,
392             boolean isResp,
393             boolean fromIkeInit,
394             List<IkePayload> payloadList)
395             throws Exception {
396         IkeMessage dummyIkeMessage =
397                 makeDummyIkeMessageForTest(
398                         initiatorSpi,
399                         responderSpi,
400                         eType,
401                         isResp,
402                         fromIkeInit,
403                         0,
404                         false /*isEncrypted*/,
405                         payloadList);
406 
407         byte[] dummyIkePacketBytes = new byte[0];
408         doReturn(new DecodeResultOk(dummyIkeMessage, dummyIkePacketBytes))
409                 .when(mMockIkeMessageHelper)
410                 .decode(0, dummyIkeMessage.ikeHeader, dummyIkePacketBytes);
411 
412         return new ReceivedIkePacket(dummyIkeMessage.ikeHeader, dummyIkePacketBytes);
413     }
414 
makeDummyEncryptedReceivedIkePacket( IkeSaRecord ikeSaRecord, @IkeHeader.ExchangeType int eType, boolean isResp, List<Integer> payloadTypeList, List<String> payloadHexStringList)415     private ReceivedIkePacket makeDummyEncryptedReceivedIkePacket(
416             IkeSaRecord ikeSaRecord,
417             @IkeHeader.ExchangeType int eType,
418             boolean isResp,
419             List<Integer> payloadTypeList,
420             List<String> payloadHexStringList)
421             throws Exception {
422         List<IkePayload> payloadList =
423                 hexStrListToIkePayloadList(payloadTypeList, payloadHexStringList, isResp);
424         return makeDummyEncryptedReceivedIkePacketWithPayloadList(
425                 ikeSaRecord, eType, isResp, payloadList);
426     }
427 
makeDummyEncryptedReceivedIkePacketWithPayloadList( IkeSaRecord ikeSaRecord, @IkeHeader.ExchangeType int eType, boolean isResp, List<IkePayload> payloadList)428     private ReceivedIkePacket makeDummyEncryptedReceivedIkePacketWithPayloadList(
429             IkeSaRecord ikeSaRecord,
430             @IkeHeader.ExchangeType int eType,
431             boolean isResp,
432             List<IkePayload> payloadList)
433             throws Exception {
434         return makeDummyEncryptedReceivedIkePacketWithPayloadList(
435                 ikeSaRecord,
436                 eType,
437                 isResp,
438                 isResp
439                         ? ikeSaRecord.getLocalRequestMessageId()
440                         : ikeSaRecord.getRemoteRequestMessageId(),
441                 payloadList,
442                 new byte[0] /*dummyIkePacketBytes*/);
443     }
444 
makeDummyEncryptedReceivedIkePacketWithPayloadList( IkeSaRecord ikeSaRecord, @IkeHeader.ExchangeType int eType, boolean isResp, int msgId, List<IkePayload> payloadList, byte[] dummyIkePacketBytes)445     private ReceivedIkePacket makeDummyEncryptedReceivedIkePacketWithPayloadList(
446             IkeSaRecord ikeSaRecord,
447             @IkeHeader.ExchangeType int eType,
448             boolean isResp,
449             int msgId,
450             List<IkePayload> payloadList,
451             byte[] dummyIkePacketBytes)
452             throws Exception {
453         boolean fromIkeInit = !ikeSaRecord.isLocalInit;
454         IkeMessage dummyIkeMessage =
455                 makeDummyIkeMessageForTest(
456                         ikeSaRecord.getInitiatorSpi(),
457                         ikeSaRecord.getResponderSpi(),
458                         eType,
459                         isResp,
460                         fromIkeInit,
461                         msgId,
462                         true /*isEncyprted*/,
463                         payloadList);
464 
465         setDecodeEncryptedPacketResult(
466                 ikeSaRecord,
467                 dummyIkeMessage.ikeHeader,
468                 null /*collectedFrags*/,
469                 new DecodeResultOk(dummyIkeMessage, dummyIkePacketBytes));
470 
471         return new ReceivedIkePacket(dummyIkeMessage.ikeHeader, dummyIkePacketBytes);
472     }
473 
makeDummyReceivedIkePacketWithInvalidSyntax( IkeSaRecord ikeSaRecord, boolean isResp, int eType)474     private ReceivedIkePacket makeDummyReceivedIkePacketWithInvalidSyntax(
475             IkeSaRecord ikeSaRecord, boolean isResp, int eType) {
476         return makeDummyReceivedIkePacketWithDecodingError(
477                 ikeSaRecord, isResp, eType, new InvalidSyntaxException("IkeStateMachineTest"));
478     }
479 
makeDummyReceivedIkePacketWithDecodingError( IkeSaRecord ikeSaRecord, boolean isResp, int eType, IkeProtocolException exception)480     private ReceivedIkePacket makeDummyReceivedIkePacketWithDecodingError(
481             IkeSaRecord ikeSaRecord, boolean isResp, int eType, IkeProtocolException exception) {
482         IkeHeader header =
483                 makeDummyIkeHeader(ikeSaRecord, isResp, eType, IkePayload.PAYLOAD_TYPE_SK);
484         byte[] dummyPacket = new byte[0];
485         doReturn(new DecodeResultProtectedError(exception, dummyPacket))
486                 .when(mMockIkeMessageHelper)
487                 .decode(anyInt(), any(), any(), eq(ikeSaRecord), eq(header), any(), any());
488 
489         return new ReceivedIkePacket(header, dummyPacket);
490     }
491 
makeDummyReceivedIkePacketWithUnprotectedError( IkeSaRecord ikeSaRecord, boolean isResp, int eType, IkeException exception)492     private ReceivedIkePacket makeDummyReceivedIkePacketWithUnprotectedError(
493             IkeSaRecord ikeSaRecord, boolean isResp, int eType, IkeException exception) {
494         IkeHeader header =
495                 makeDummyIkeHeader(ikeSaRecord, isResp, eType, IkePayload.PAYLOAD_TYPE_SK);
496         byte[] dummyPacket = new byte[0];
497         doReturn(new DecodeResultUnprotectedError(exception))
498                 .when(mMockIkeMessageHelper)
499                 .decode(anyInt(), any(), any(), eq(ikeSaRecord), eq(header), any(), any());
500 
501         return new ReceivedIkePacket(header, dummyPacket);
502     }
503 
makeDummyReceivedIkeFragmentPacket( IkeSaRecord ikeSaRecord, boolean isResp, int eType, IkeSkfPayload skfPayload, int nextPayloadType, DecodeResultPartial collectedFrags)504     private ReceivedIkePacket makeDummyReceivedIkeFragmentPacket(
505             IkeSaRecord ikeSaRecord,
506             boolean isResp,
507             int eType,
508             IkeSkfPayload skfPayload,
509             int nextPayloadType,
510             DecodeResultPartial collectedFrags) {
511         IkeHeader header =
512                 makeDummyIkeHeader(ikeSaRecord, isResp, eType, IkePayload.PAYLOAD_TYPE_SKF);
513 
514         byte[] dummyPacket = new byte[0];
515         DecodeResultPartial resultFrags =
516                 new DecodeResultPartial(
517                         header, dummyPacket, skfPayload, nextPayloadType, collectedFrags);
518         setDecodeEncryptedPacketResult(ikeSaRecord, header, collectedFrags, resultFrags);
519 
520         return new ReceivedIkePacket(header, dummyPacket);
521     }
522 
makeDummyReceivedLastIkeFragmentPacketOk( IkeSaRecord ikeSaRecord, boolean isResp, int eType, DecodeResultPartial collectedFrags, List<IkePayload> payloadList, byte[] firstFragBytes)523     private ReceivedIkePacket makeDummyReceivedLastIkeFragmentPacketOk(
524             IkeSaRecord ikeSaRecord,
525             boolean isResp,
526             int eType,
527             DecodeResultPartial collectedFrags,
528             List<IkePayload> payloadList,
529             byte[] firstFragBytes) {
530         IkeHeader header =
531                 makeDummyIkeHeader(ikeSaRecord, isResp, eType, IkePayload.PAYLOAD_TYPE_SKF);
532 
533         IkeMessage completeMessage = new IkeMessage(header, payloadList);
534 
535         setDecodeEncryptedPacketResult(
536                 ikeSaRecord,
537                 header,
538                 collectedFrags,
539                 new DecodeResultOk(completeMessage, firstFragBytes));
540 
541         return new ReceivedIkePacket(header, new byte[0] /*dummyIkePacketBytes*/);
542     }
543 
makeDummyReceivedLastIkeFragmentPacketError( IkeSaRecord ikeSaRecord, boolean isResp, int eType, DecodeResultPartial collectedFrags, IkeException exception)544     private ReceivedIkePacket makeDummyReceivedLastIkeFragmentPacketError(
545             IkeSaRecord ikeSaRecord,
546             boolean isResp,
547             int eType,
548             DecodeResultPartial collectedFrags,
549             IkeException exception) {
550         IkeHeader header =
551                 makeDummyIkeHeader(ikeSaRecord, isResp, eType, IkePayload.PAYLOAD_TYPE_SKF);
552 
553         byte[] dummyIkePacketBytes = new byte[0];
554         setDecodeEncryptedPacketResult(
555                 ikeSaRecord,
556                 header,
557                 collectedFrags,
558                 new DecodeResultProtectedError(exception, dummyIkePacketBytes));
559 
560         return new ReceivedIkePacket(header, dummyIkePacketBytes);
561     }
562 
makeDummyIkeHeader( IkeSaRecord ikeSaRecord, boolean isResp, int eType, int firstPayloadType)563     private IkeHeader makeDummyIkeHeader(
564             IkeSaRecord ikeSaRecord, boolean isResp, int eType, int firstPayloadType) {
565         return new IkeHeader(
566                 ikeSaRecord.getInitiatorSpi(),
567                 ikeSaRecord.getResponderSpi(),
568                 firstPayloadType,
569                 eType,
570                 isResp,
571                 !ikeSaRecord.isLocalInit,
572                 isResp
573                         ? ikeSaRecord.getLocalRequestMessageId()
574                         : ikeSaRecord.getRemoteRequestMessageId());
575     }
576 
setDecodeEncryptedPacketResult( IkeSaRecord ikeSaRecord, IkeHeader header, DecodeResultPartial collectedFrags, DecodeResult result)577     private void setDecodeEncryptedPacketResult(
578             IkeSaRecord ikeSaRecord,
579             IkeHeader header,
580             DecodeResultPartial collectedFrags,
581             DecodeResult result) {
582         doReturn(result)
583                 .when(mMockIkeMessageHelper)
584                 .decode(
585                         anyInt(),
586                         any(),
587                         any(),
588                         eq(ikeSaRecord),
589                         eq(header),
590                         any(),
591                         eq(collectedFrags));
592     }
593 
makeDummyIkeMessageForTest( long initSpi, long respSpi, @IkeHeader.ExchangeType int eType, boolean isResp, boolean fromikeInit, int messageId, boolean isEncrypted, List<IkePayload> payloadList)594     private IkeMessage makeDummyIkeMessageForTest(
595             long initSpi,
596             long respSpi,
597             @IkeHeader.ExchangeType int eType,
598             boolean isResp,
599             boolean fromikeInit,
600             int messageId,
601             boolean isEncrypted,
602             List<IkePayload> payloadList)
603             throws Exception {
604         int firstPayloadType =
605                 isEncrypted ? IkePayload.PAYLOAD_TYPE_SK : IkePayload.PAYLOAD_TYPE_NO_NEXT;
606 
607         IkeHeader header =
608                 new IkeHeader(
609                         initSpi, respSpi, firstPayloadType, eType, isResp, fromikeInit, messageId);
610 
611         return new IkeMessage(header, payloadList);
612     }
613 
hexStrListToIkePayloadList( List<Integer> payloadTypeList, List<String> payloadHexStringList, boolean isResp)614     private static List<IkePayload> hexStrListToIkePayloadList(
615             List<Integer> payloadTypeList, List<String> payloadHexStringList, boolean isResp)
616             throws Exception {
617         List<IkePayload> payloadList = new LinkedList<>();
618         for (int i = 0; i < payloadTypeList.size(); i++) {
619             payloadList.add(
620                     IkeTestUtils.hexStringToIkePayload(
621                             payloadTypeList.get(i), isResp, payloadHexStringList.get(i)));
622         }
623         return payloadList;
624     }
625 
verifyDecodeEncryptedMessage(IkeSaRecord record, ReceivedIkePacket rcvPacket)626     private void verifyDecodeEncryptedMessage(IkeSaRecord record, ReceivedIkePacket rcvPacket)
627             throws Exception {
628         verify(mMockIkeMessageHelper)
629                 .decode(
630                         anyInt(),
631                         any(),
632                         any(),
633                         eq(record),
634                         eq(rcvPacket.ikeHeader),
635                         eq(rcvPacket.ikePacketBytes),
636                         eq(null));
637     }
638 
makeDummyIkeSaRecord(long initSpi, long respSpi, boolean isLocalInit)639     private static IkeSaRecord makeDummyIkeSaRecord(long initSpi, long respSpi, boolean isLocalInit)
640             throws IOException {
641         Inet4Address initAddress = isLocalInit ? LOCAL_ADDRESS : REMOTE_ADDRESS;
642         Inet4Address respAddress = isLocalInit ? REMOTE_ADDRESS : LOCAL_ADDRESS;
643 
644         return new IkeSaRecord(
645                 IKE_SPI_GENERATOR.allocateSpi(initAddress, initSpi),
646                 IKE_SPI_GENERATOR.allocateSpi(respAddress, respSpi),
647                 isLocalInit,
648                 TestUtils.hexStringToByteArray(NONCE_INIT_HEX_STRING),
649                 TestUtils.hexStringToByteArray(NONCE_RESP_HEX_STRING),
650                 new byte[KEY_LEN_IKE_SKD],
651                 new byte[KEY_LEN_IKE_INTE],
652                 new byte[KEY_LEN_IKE_INTE],
653                 new byte[KEY_LEN_IKE_ENCR],
654                 new byte[KEY_LEN_IKE_ENCR],
655                 TestUtils.hexStringToByteArray(PRF_KEY_INIT_HEX_STRING),
656                 TestUtils.hexStringToByteArray(PRF_KEY_RESP_HEX_STRING),
657                 mock(SaLifetimeAlarmScheduler.class));
658     }
659 
mockScheduleRekey(SaLifetimeAlarmScheduler mockSaLifetimeAlarmScheduler)660     private void mockScheduleRekey(SaLifetimeAlarmScheduler mockSaLifetimeAlarmScheduler) {
661         IkeLocalRequest rekeyReq =
662                 new IkeLocalRequest(IkeSessionStateMachine.CMD_LOCAL_REQUEST_REKEY_IKE);
663         doAnswer(
664                 (invocation) -> {
665                         mIkeSessionStateMachine.sendMessageDelayed(
666                                 IkeSessionStateMachine.CMD_LOCAL_REQUEST_REKEY_IKE,
667                                 rekeyReq,
668                                 mIkeSessionStateMachine.mIkeSessionParams
669                                         .getSoftLifetimeMsInternal());
670                         return null;
671                 })
672                 .when(mockSaLifetimeAlarmScheduler)
673                 .scheduleLifetimeExpiryAlarm(anyString());
674     }
675 
676     @Before
setUp()677     public void setUp() throws Exception {
678         super.setUp();
679 
680         mSpyIkeLog = TestUtils.makeSpyLogThrowExceptionForWtf(TAG);
681         IkeManager.setIkeLog(mSpyIkeLog);
682 
683         mEapSessionConfig =
684                 new EapSessionConfig.Builder()
685                         .setEapSimConfig(EAP_SIM_SUB_ID, TelephonyManager.APPTYPE_USIM)
686                         .build();
687 
688         mMockEapAuthenticatorFactory = mock(IkeEapAuthenticatorFactory.class);
689         mMockEapAuthenticator = mock(EapAuthenticator.class);
690         doReturn(mMockEapAuthenticator)
691                 .when(mMockEapAuthenticatorFactory)
692                 .newEapAuthenticator(
693                         any(Looper.class),
694                         any(IEapCallback.class),
695                         any(Context.class),
696                         any(EapSessionConfig.class),
697                         any(RandomnessFactory.class));
698 
699         mRootCertificate = CertUtils.createCertFromPemFile("self-signed-ca-a.pem");
700         mServerEndCertificate = CertUtils.createCertFromPemFile("end-cert-a.pem");
701         mUserEndCert = CertUtils.createCertFromPemFile("end-cert-b.pem");
702         mUserPrivateKey = CertUtils.createRsaPrivateKeyFromKeyFile("end-cert-key-b.key");
703 
704         mPsk = TestUtils.hexStringToByteArray(PSK_HEX_STRING);
705 
706         mChildSessionParams = buildChildSessionParams();
707 
708         mIkeEncryptionTransform =
709                 new EncryptionTransform(
710                         SaProposal.ENCRYPTION_ALGORITHM_AES_CBC, SaProposal.KEY_LEN_AES_128);
711         mIkeIntegrityTransform =
712                 new IntegrityTransform(SaProposal.INTEGRITY_ALGORITHM_HMAC_SHA1_96);
713         mIkePrfTransform = new PrfTransform(SaProposal.PSEUDORANDOM_FUNCTION_HMAC_SHA1);
714         mIkeDhGroupTransform = new DhGroupTransform(SaProposal.DH_GROUP_1024_BIT_MODP);
715 
716         mSpyUserCbExecutor =
717                 spy(
718                         (command) -> {
719                             command.run();
720                         });
721 
722         mMockIkeSessionCallback = mock(IkeSessionCallback.class);
723         mMockChildSessionCallback = mock(ChildSessionCallback.class);
724 
725         mLooper = new TestLooper();
726 
727         mMockChildSessionStateMachine = mock(ChildSessionStateMachine.class);
728         mMockChildSessionFactoryHelper = mock(IChildSessionFactoryHelper.class);
729         ChildSessionStateMachineFactory.setChildSessionFactoryHelper(
730                 mMockChildSessionFactoryHelper);
731         setupChildStateMachineFactory(mMockChildSessionStateMachine);
732 
733         // Setup state machine
734         mIkeSessionStateMachine = makeAndStartIkeSession(buildIkeSessionParamsPsk(mPsk));
735 
736         mMockIkeMessageHelper = mock(IkeMessage.IIkeMessageHelper.class);
737         IkeMessage.setIkeMessageHelper(mMockIkeMessageHelper);
738         resetMockIkeMessageHelper();
739 
740         mMockSaRecordHelper = mock(SaRecord.ISaRecordHelper.class);
741         SaRecord.setSaRecordHelper(mMockSaRecordHelper);
742 
743         mSpyCurrentIkeSaRecord = spy(makeDummyIkeSaRecord(11, 12, true));
744         mSpyLocalInitIkeSaRecord = spy(makeDummyIkeSaRecord(21, 22, true));
745         mSpyRemoteInitIkeSaRecord = spy(makeDummyIkeSaRecord(31, 32, false));
746 
747         mExpectedCurrentSaLocalReqMsgId = 0;
748         mExpectedCurrentSaRemoteReqMsgId = 0;
749     }
750 
751     @After
tearDown()752     public void tearDown() throws Exception {
753         mIkeSessionStateMachine.killSession();
754         mLooper.dispatchAll();
755         mIkeSessionStateMachine.setDbg(false);
756 
757         mSpyCurrentIkeSaRecord.close();
758         mSpyLocalInitIkeSaRecord.close();
759         mSpyRemoteInitIkeSaRecord.close();
760 
761         IkeManager.resetIkeLog();
762         IkeMessage.setIkeMessageHelper(new IkeMessageHelper());
763         SaRecord.setSaRecordHelper(new SaRecordHelper());
764         ChildSessionStateMachineFactory.setChildSessionFactoryHelper(
765                 new ChildSessionFactoryHelper());
766     }
767 
makeAndStartIkeSession(IkeSessionParams ikeParams)768     private IkeSessionStateMachine makeAndStartIkeSession(IkeSessionParams ikeParams)
769             throws Exception {
770         IkeSessionStateMachine ikeSession =
771                 new IkeSessionStateMachine(
772                         mLooper.getLooper(),
773                         mSpyContext,
774                         mIpSecManager,
775                         ikeParams,
776                         mChildSessionParams,
777                         mSpyUserCbExecutor,
778                         mMockIkeSessionCallback,
779                         mMockChildSessionCallback,
780                         mMockEapAuthenticatorFactory);
781         ikeSession.setDbg(true);
782 
783         mLooper.dispatchAll();
784         ikeSession.mLocalAddress = LOCAL_ADDRESS;
785         assertEquals(REMOTE_ADDRESS, ikeSession.mRemoteAddress);
786 
787         // Setup socket instances used by the IkeSessionStateMachine
788         // TODO: rename these from spy to mock.
789         mSpyIkeUdp4Socket = mock(IkeUdp4Socket.class);
790         mSpyIkeUdp6Socket = mock(IkeUdp6Socket.class);
791         mSpyIkeUdpEncapSocket = mock(IkeUdpEncapSocket.class);
792 
793         doNothing().when(mSpyIkeUdp4Socket).sendIkePacket(any(), any());
794         doNothing().when(mSpyIkeUdp6Socket).sendIkePacket(any(), any());
795         doNothing().when(mSpyIkeUdpEncapSocket).sendIkePacket(any(), any());
796 
797         // Always start with unencap'd socket.
798         mSpyCurrentIkeSocket = mSpyIkeUdp4Socket;
799         ikeSession.mIkeSocket = mSpyCurrentIkeSocket;
800         return ikeSession;
801     }
802 
buildSaProposal()803     public static IkeSaProposal buildSaProposal() throws Exception {
804         return buildSaProposalCommon().addDhGroup(SaProposal.DH_GROUP_2048_BIT_MODP).build();
805     }
806 
buildNegotiatedSaProposal()807     private static IkeSaProposal buildNegotiatedSaProposal() throws Exception {
808         return buildSaProposalCommon().build();
809     }
810 
buildSaProposalCommon()811     private static IkeSaProposal.Builder buildSaProposalCommon() throws Exception {
812         return new IkeSaProposal.Builder()
813                 .addEncryptionAlgorithm(
814                         SaProposal.ENCRYPTION_ALGORITHM_AES_CBC, SaProposal.KEY_LEN_AES_128)
815                 .addIntegrityAlgorithm(SaProposal.INTEGRITY_ALGORITHM_HMAC_SHA1_96)
816                 .addPseudorandomFunction(SaProposal.PSEUDORANDOM_FUNCTION_HMAC_SHA1)
817                 .addDhGroup(SaProposal.DH_GROUP_1024_BIT_MODP);
818     }
819 
buildIkeSessionParamsCommon()820     private IkeSessionParams.Builder buildIkeSessionParamsCommon() throws Exception {
821         return new IkeSessionParams.Builder(mMockConnectManager)
822                 .setServerHostname(REMOTE_ADDRESS.getHostAddress())
823                 .addSaProposal(buildSaProposal())
824                 .setLocalIdentification(LOCAL_ID_IPV4)
825                 .setRemoteIdentification(REMOTE_ID_FQDN)
826                 .addPcscfServerRequest(AF_INET)
827                 .addPcscfServerRequest(AF_INET6)
828                 .setRetransmissionTimeoutsMillis(
829                         new int[] {5000, 10000, 20000, 30000, 40000, 50000});
830     }
831 
buildIkeSessionParams()832     private IkeSessionParams buildIkeSessionParams() throws Exception {
833         return buildIkeSessionParamsCommon().setAuthPsk(mPsk).build();
834     }
835 
buildIkeSessionParamsPsk(byte[] psk)836     private IkeSessionParams buildIkeSessionParamsPsk(byte[] psk) throws Exception {
837         return buildIkeSessionParamsCommon().setAuthPsk(psk).build();
838     }
839 
buildIkeSessionParamsEap()840     private IkeSessionParams buildIkeSessionParamsEap() throws Exception {
841         return buildIkeSessionParamsCommon()
842                 .setAuthEap(mRootCertificate, mEapSessionConfig)
843                 .build();
844     }
845 
buildIkeSessionParamsDigitalSignature()846     private IkeSessionParams buildIkeSessionParamsDigitalSignature() throws Exception {
847         return buildIkeSessionParamsCommon()
848                 .setAuthDigitalSignature(mRootCertificate, mUserEndCert, mUserPrivateKey)
849                 .build();
850     }
851 
buildChildSessionParams()852     private ChildSessionParams buildChildSessionParams() throws Exception {
853         ChildSaProposal saProposal =
854                 new ChildSaProposal.Builder()
855                         .addEncryptionAlgorithm(
856                                 SaProposal.ENCRYPTION_ALGORITHM_AES_CBC, SaProposal.KEY_LEN_AES_128)
857                         .addIntegrityAlgorithm(SaProposal.INTEGRITY_ALGORITHM_HMAC_SHA1_96)
858                         .build();
859 
860         return new TunnelModeChildSessionParams.Builder()
861                 .addSaProposal(saProposal)
862                 .addInternalAddressRequest(AF_INET)
863                 .addInternalAddressRequest(AF_INET6)
864                 .build();
865     }
866 
makeIkeInitResponse()867     private ReceivedIkePacket makeIkeInitResponse() throws Exception {
868         // TODO: Build real IKE INIT response when IKE INIT response validation is implemented.
869         List<Integer> payloadTypeList = new LinkedList<>();
870         List<String> payloadHexStringList = new LinkedList<>();
871 
872         payloadTypeList.add(IkePayload.PAYLOAD_TYPE_SA);
873         payloadTypeList.add(IkePayload.PAYLOAD_TYPE_KE);
874         payloadTypeList.add(IkePayload.PAYLOAD_TYPE_NONCE);
875         payloadTypeList.add(IkePayload.PAYLOAD_TYPE_NOTIFY);
876         payloadTypeList.add(IkePayload.PAYLOAD_TYPE_NOTIFY);
877         payloadTypeList.add(IkePayload.PAYLOAD_TYPE_NOTIFY);
878         payloadTypeList.add(IkePayload.PAYLOAD_TYPE_NOTIFY);
879         payloadTypeList.add(IkePayload.PAYLOAD_TYPE_VENDOR);
880 
881         payloadHexStringList.add(IKE_SA_PAYLOAD_HEX_STRING);
882         payloadHexStringList.add(KE_PAYLOAD_HEX_STRING);
883         payloadHexStringList.add(NONCE_RESP_PAYLOAD_HEX_STRING);
884         payloadHexStringList.add(NAT_DETECTION_SOURCE_PAYLOAD_HEX_STRING);
885         payloadHexStringList.add(NAT_DETECTION_DESTINATION_PAYLOAD_HEX_STRING);
886         payloadHexStringList.add(FRAGMENTATION_SUPPORTED_PAYLOAD_HEX_STRING);
887         payloadHexStringList.add(SIGNATURE_HASH_SUPPORTED_PAYLOAD_HEX_STRING);
888         payloadHexStringList.add(VENDOR_ID_PAYLOAD_HEX_STRING);
889 
890         // In each test assign different IKE responder SPI in IKE INIT response to avoid remote SPI
891         // collision during response validation.
892         // STOPSHIP: b/131617794 allow #mockIkeSetup to be independent in each test after we can
893         // support IkeSession cleanup.
894         return makeDummyReceivedIkeInitRespPacket(
895                 1L /*initiator SPI*/,
896                 2L /*responder SPI*/,
897                 IkeHeader.EXCHANGE_TYPE_IKE_SA_INIT,
898                 true /*isResp*/,
899                 false /*fromIkeInit*/,
900                 payloadTypeList,
901                 payloadHexStringList);
902     }
903 
getIkeAuthPayloadListWithChildPayloads( List<IkePayload> authRelatedPayloads)904     private List<IkePayload> getIkeAuthPayloadListWithChildPayloads(
905             List<IkePayload> authRelatedPayloads) throws Exception {
906         List<Integer> payloadTypeList = new LinkedList<>();
907         List<String> payloadHexStringList = new LinkedList<>();
908 
909         payloadTypeList.add(IkePayload.PAYLOAD_TYPE_SA);
910         payloadTypeList.add(IkePayload.PAYLOAD_TYPE_TS_INITIATOR);
911         payloadTypeList.add(IkePayload.PAYLOAD_TYPE_TS_RESPONDER);
912 
913         payloadHexStringList.add(CHILD_SA_PAYLOAD_HEX_STRING);
914         payloadHexStringList.add(TS_INIT_PAYLOAD_HEX_STRING);
915         payloadHexStringList.add(TS_RESP_PAYLOAD_HEX_STRING);
916 
917         List<IkePayload> payloadList =
918                 hexStrListToIkePayloadList(payloadTypeList, payloadHexStringList, true /*isResp*/);
919         payloadList.addAll(authRelatedPayloads);
920 
921         return payloadList;
922     }
923 
makeIkeAuthRespWithChildPayloads(List<IkePayload> authRelatedPayloads)924     private ReceivedIkePacket makeIkeAuthRespWithChildPayloads(List<IkePayload> authRelatedPayloads)
925             throws Exception {
926         List<IkePayload> payloadList = getIkeAuthPayloadListWithChildPayloads(authRelatedPayloads);
927 
928         return makeDummyEncryptedReceivedIkePacketWithPayloadList(
929                 mSpyCurrentIkeSaRecord,
930                 IkeHeader.EXCHANGE_TYPE_IKE_AUTH,
931                 true /*isResp*/,
932                 payloadList);
933     }
934 
makeIkeAuthRespWithoutChildPayloads( List<IkePayload> authRelatedPayloads)935     private ReceivedIkePacket makeIkeAuthRespWithoutChildPayloads(
936             List<IkePayload> authRelatedPayloads) throws Exception {
937         return makeDummyEncryptedReceivedIkePacketWithPayloadList(
938                 mSpyCurrentIkeSaRecord,
939                 IkeHeader.EXCHANGE_TYPE_IKE_AUTH,
940                 true /*isResp*/,
941                 authRelatedPayloads);
942     }
943 
makeCreateChildCreateMessage(boolean isResp)944     private ReceivedIkePacket makeCreateChildCreateMessage(boolean isResp) throws Exception {
945         return makeDummyEncryptedReceivedIkePacketWithPayloadList(
946                 mSpyCurrentIkeSaRecord,
947                 IkeHeader.EXCHANGE_TYPE_CREATE_CHILD_SA,
948                 isResp,
949                 makeCreateChildPayloadList(isResp));
950     }
951 
makeRekeyChildCreateMessage(boolean isResp, int spi)952     private ReceivedIkePacket makeRekeyChildCreateMessage(boolean isResp, int spi)
953             throws Exception {
954         IkeNotifyPayload rekeyPayload =
955                 new IkeNotifyPayload(
956                         IkePayload.PROTOCOL_ID_ESP,
957                         spi,
958                         IkeNotifyPayload.NOTIFY_TYPE_REKEY_SA,
959                         new byte[0]);
960 
961         List<IkePayload> payloadList = makeCreateChildPayloadList(isResp);
962         payloadList.add(rekeyPayload);
963 
964         return makeDummyEncryptedReceivedIkePacketWithPayloadList(
965                 mSpyCurrentIkeSaRecord,
966                 IkeHeader.EXCHANGE_TYPE_CREATE_CHILD_SA,
967                 isResp,
968                 payloadList);
969     }
970 
makeCreateChildPayloadList(boolean isResp)971     private List<IkePayload> makeCreateChildPayloadList(boolean isResp) throws Exception {
972         List<Integer> payloadTypeList = new LinkedList<>();
973         List<String> payloadHexStringList = new LinkedList<>();
974 
975         payloadTypeList.add(IkePayload.PAYLOAD_TYPE_SA);
976         payloadTypeList.add(IkePayload.PAYLOAD_TYPE_NONCE);
977         payloadTypeList.add(IkePayload.PAYLOAD_TYPE_TS_INITIATOR);
978         payloadTypeList.add(IkePayload.PAYLOAD_TYPE_TS_RESPONDER);
979 
980         payloadHexStringList.add(CHILD_SA_PAYLOAD_HEX_STRING);
981         payloadHexStringList.add(NONCE_RESP_PAYLOAD_HEX_STRING);
982         payloadHexStringList.add(TS_INIT_PAYLOAD_HEX_STRING);
983         payloadHexStringList.add(TS_RESP_PAYLOAD_HEX_STRING);
984 
985         return hexStrListToIkePayloadList(payloadTypeList, payloadHexStringList, isResp);
986     }
987 
makeDeleteChildPacket(IkeDeletePayload[] payloads, boolean isResp)988     private ReceivedIkePacket makeDeleteChildPacket(IkeDeletePayload[] payloads, boolean isResp)
989             throws Exception {
990         return makeDummyEncryptedReceivedIkePacketWithPayloadList(
991                 mSpyCurrentIkeSaRecord,
992                 IkeHeader.EXCHANGE_TYPE_INFORMATIONAL,
993                 isResp,
994                 Arrays.asList(payloads));
995     }
996 
makeRekeyIkeResponse()997     private ReceivedIkePacket makeRekeyIkeResponse() throws Exception {
998         List<Integer> payloadTypeList = new LinkedList<>();
999         List<String> payloadHexStringList = new LinkedList<>();
1000 
1001         payloadTypeList.add(IkePayload.PAYLOAD_TYPE_SA);
1002         payloadTypeList.add(IkePayload.PAYLOAD_TYPE_KE);
1003         payloadTypeList.add(IkePayload.PAYLOAD_TYPE_NONCE);
1004 
1005         payloadHexStringList.add(IKE_REKEY_SA_PAYLOAD_HEX_STRING);
1006         payloadHexStringList.add(KE_PAYLOAD_HEX_STRING);
1007         payloadHexStringList.add(NONCE_RESP_PAYLOAD_HEX_STRING);
1008 
1009         return makeDummyEncryptedReceivedIkePacket(
1010                 mSpyCurrentIkeSaRecord,
1011                 IkeHeader.EXCHANGE_TYPE_CREATE_CHILD_SA,
1012                 true /*isResp*/,
1013                 payloadTypeList,
1014                 payloadHexStringList);
1015     }
1016 
makeDeleteIkeResponse(IkeSaRecord ikeSaRecord)1017     private ReceivedIkePacket makeDeleteIkeResponse(IkeSaRecord ikeSaRecord) throws Exception {
1018         return makeDummyEncryptedReceivedIkePacket(
1019                 ikeSaRecord,
1020                 IkeHeader.EXCHANGE_TYPE_INFORMATIONAL,
1021                 true /*isResp*/,
1022                 new LinkedList<>(),
1023                 new LinkedList<>());
1024     }
1025 
makeDpdIkeRequest(IkeSaRecord saRecord)1026     private ReceivedIkePacket makeDpdIkeRequest(IkeSaRecord saRecord) throws Exception {
1027         return makeDummyEncryptedReceivedIkePacket(
1028                 saRecord,
1029                 IkeHeader.EXCHANGE_TYPE_INFORMATIONAL,
1030                 false /*isResp*/,
1031                 new LinkedList<>(),
1032                 new LinkedList<>());
1033     }
1034 
makeDpdIkeRequest(int msgId, byte[] dummyIkePacketBytes)1035     private ReceivedIkePacket makeDpdIkeRequest(int msgId, byte[] dummyIkePacketBytes)
1036             throws Exception {
1037         return makeDummyEncryptedReceivedIkePacketWithPayloadList(
1038                 mSpyCurrentIkeSaRecord,
1039                 EXCHANGE_TYPE_INFORMATIONAL,
1040                 false /*isResp*/,
1041                 msgId,
1042                 new LinkedList<>(),
1043                 dummyIkePacketBytes);
1044     }
1045 
makeRekeyIkeRequest()1046     private ReceivedIkePacket makeRekeyIkeRequest() throws Exception {
1047         IkeSaPayload saPayload =
1048                 (IkeSaPayload)
1049                         IkeTestUtils.hexStringToIkePayload(
1050                                 IkePayload.PAYLOAD_TYPE_SA,
1051                                 false /*isResp*/,
1052                                 IKE_REKEY_SA_PAYLOAD_HEX_STRING);
1053         return makeRekeyIkeRequest(saPayload);
1054     }
1055 
makeRekeyIkeRequestWithUnacceptableProposal()1056     private ReceivedIkePacket makeRekeyIkeRequestWithUnacceptableProposal() throws Exception {
1057         IkeSaPayload saPayload =
1058                 (IkeSaPayload)
1059                         IkeTestUtils.hexStringToIkePayload(
1060                                 IkePayload.PAYLOAD_TYPE_SA,
1061                                 false /*isResp*/,
1062                                 IKE_REKEY_UNACCEPTABLE_SA_PAYLOAD_HEX_STRING);
1063         return makeRekeyIkeRequest(saPayload);
1064     }
1065 
makeRekeyIkeRequest(IkeSaPayload saPayload)1066     private ReceivedIkePacket makeRekeyIkeRequest(IkeSaPayload saPayload) throws Exception {
1067         List<Integer> payloadTypeList = new LinkedList<>();
1068         List<String> payloadHexStringList = new LinkedList<>();
1069 
1070         payloadTypeList.add(IkePayload.PAYLOAD_TYPE_KE);
1071         payloadTypeList.add(IkePayload.PAYLOAD_TYPE_NONCE);
1072 
1073         payloadHexStringList.add(KE_PAYLOAD_HEX_STRING);
1074         payloadHexStringList.add(NONCE_INIT_PAYLOAD_HEX_STRING);
1075 
1076         List<IkePayload> payloadList =
1077                 hexStrListToIkePayloadList(payloadTypeList, payloadHexStringList, false /*isResp*/);
1078         payloadList.add(saPayload);
1079 
1080         return makeDummyEncryptedReceivedIkePacketWithPayloadList(
1081                 mSpyCurrentIkeSaRecord,
1082                 IkeHeader.EXCHANGE_TYPE_CREATE_CHILD_SA,
1083                 false /*isResp*/,
1084                 payloadList);
1085     }
1086 
makeDeleteIkeRequest(IkeSaRecord saRecord)1087     private ReceivedIkePacket makeDeleteIkeRequest(IkeSaRecord saRecord) throws Exception {
1088         List<Integer> payloadTypeList = new LinkedList<>();
1089         List<String> payloadHexStringList = new LinkedList<>();
1090 
1091         payloadTypeList.add(IkePayload.PAYLOAD_TYPE_DELETE);
1092 
1093         payloadHexStringList.add(DELETE_IKE_PAYLOAD_HEX_STRING);
1094 
1095         return makeDummyEncryptedReceivedIkePacket(
1096                 saRecord,
1097                 IkeHeader.EXCHANGE_TYPE_INFORMATIONAL,
1098                 false /*isResp*/,
1099                 payloadTypeList,
1100                 payloadHexStringList);
1101     }
1102 
makeResponseWithErrorNotify(IkeNotifyPayload notify)1103     private ReceivedIkePacket makeResponseWithErrorNotify(IkeNotifyPayload notify)
1104             throws Exception {
1105         List<IkePayload> payloads = new LinkedList<>();
1106         payloads.add(notify);
1107         return makeDummyEncryptedReceivedIkePacketWithPayloadList(
1108                 mSpyCurrentIkeSaRecord, EXCHANGE_TYPE_INFORMATIONAL, true /*isResp*/, payloads);
1109     }
1110 
isIkePayloadExist( List<IkePayload> payloadList, @IkePayload.PayloadType int payloadType)1111     private static boolean isIkePayloadExist(
1112             List<IkePayload> payloadList, @IkePayload.PayloadType int payloadType) {
1113         for (IkePayload payload : payloadList) {
1114             if (payload.payloadType == payloadType) return true;
1115         }
1116         return false;
1117     }
1118 
isNotifyExist( List<IkePayload> payloadList, @IkeNotifyPayload.NotifyType int notifyType)1119     private static boolean isNotifyExist(
1120             List<IkePayload> payloadList, @IkeNotifyPayload.NotifyType int notifyType) {
1121         for (IkeNotifyPayload notify :
1122                 IkePayload.getPayloadListForTypeInProvidedList(
1123                         PAYLOAD_TYPE_NOTIFY, IkeNotifyPayload.class, payloadList)) {
1124             if (notify.notifyType == notifyType) return true;
1125         }
1126         return false;
1127     }
1128 
assertByteArrayListEquals( List<byte[]> expectedList, List<byte[]> resultList)1129     private static void assertByteArrayListEquals(
1130             List<byte[]> expectedList, List<byte[]> resultList) {
1131         assertEquals(expectedList.size(), resultList.size());
1132         for (int i = 0; i < expectedList.size(); i++) {
1133             assertArrayEquals(expectedList.get(i), resultList.get(i));
1134         }
1135     }
1136 
verifyIncrementLocaReqMsgId()1137     private void verifyIncrementLocaReqMsgId() {
1138         assertEquals(
1139                 ++mExpectedCurrentSaLocalReqMsgId,
1140                 mSpyCurrentIkeSaRecord.getLocalRequestMessageId());
1141     }
1142 
verifyIncrementRemoteReqMsgId()1143     private void verifyIncrementRemoteReqMsgId() {
1144         assertEquals(
1145                 ++mExpectedCurrentSaRemoteReqMsgId,
1146                 mSpyCurrentIkeSaRecord.getRemoteRequestMessageId());
1147     }
1148 
verifyRetransmissionStarted()1149     private void verifyRetransmissionStarted() {
1150         assertTrue(
1151                 mIkeSessionStateMachine
1152                         .getHandler()
1153                         .hasMessages(IkeSessionStateMachine.CMD_RETRANSMIT));
1154     }
1155 
verifyRetransmissionStopped()1156     private void verifyRetransmissionStopped() {
1157         assertFalse(
1158                 mIkeSessionStateMachine
1159                         .getHandler()
1160                         .hasMessages(IkeSessionStateMachine.CMD_RETRANSMIT));
1161     }
1162 
verifyEncryptAndEncodeAndGetMessage(IkeSaRecord ikeSaRecord)1163     private IkeMessage verifyEncryptAndEncodeAndGetMessage(IkeSaRecord ikeSaRecord) {
1164         verify(mMockIkeMessageHelper)
1165                 .encryptAndEncode(
1166                         anyObject(),
1167                         anyObject(),
1168                         eq(ikeSaRecord),
1169                         mIkeMessageCaptor.capture(),
1170                         anyBoolean(),
1171                         anyInt());
1172         return mIkeMessageCaptor.getValue();
1173     }
1174 
verifyEncryptAndEncodeNeverCalled(IkeSaRecord ikeSaRecord)1175     private void verifyEncryptAndEncodeNeverCalled(IkeSaRecord ikeSaRecord) {
1176         verify(mMockIkeMessageHelper, never())
1177                 .encryptAndEncode(
1178                         anyObject(),
1179                         anyObject(),
1180                         eq(ikeSaRecord),
1181                         any(IkeMessage.class),
1182                         anyBoolean(),
1183                         anyInt());
1184     }
1185 
verifyEncryptAndEncodeNeverCalled()1186     private void verifyEncryptAndEncodeNeverCalled() {
1187         verify(mMockIkeMessageHelper, never())
1188                 .encryptAndEncode(
1189                         anyObject(),
1190                         anyObject(),
1191                         any(IkeSaRecord.class),
1192                         any(IkeMessage.class),
1193                         anyBoolean(),
1194                         anyInt());
1195     }
1196 
resetMockIkeMessageHelper()1197     private void resetMockIkeMessageHelper() {
1198         reset(mMockIkeMessageHelper);
1199         doReturn(new byte[0]).when(mMockIkeMessageHelper).encode(any());
1200         doReturn(new byte[1][0])
1201                 .when(mMockIkeMessageHelper)
1202                 .encryptAndEncode(any(), any(), any(), any(), anyBoolean(), anyInt());
1203     }
1204 
1205     @Test
testQuit()1206     public void testQuit() {
1207         mIkeSessionStateMachine.quit();
1208         mLooper.dispatchAll();
1209 
1210         verify(mSpyCurrentIkeSocket).releaseReference(eq(mIkeSessionStateMachine));
1211         verify(mMockBusyWakelock).release();
1212     }
1213 
1214     @Test
testAllocateIkeSpi()1215     public void testAllocateIkeSpi() throws Exception {
1216         // Test randomness.
1217         IkeSecurityParameterIndex ikeSpiOne = IKE_SPI_GENERATOR.allocateSpi(LOCAL_ADDRESS);
1218         IkeSecurityParameterIndex ikeSpiTwo = IKE_SPI_GENERATOR.allocateSpi(LOCAL_ADDRESS);
1219 
1220         assertNotEquals(ikeSpiOne.getSpi(), ikeSpiTwo.getSpi());
1221         ikeSpiTwo.close();
1222 
1223         // Test duplicate SPIs.
1224         long spiValue = ikeSpiOne.getSpi();
1225         try {
1226             IKE_SPI_GENERATOR.allocateSpi(LOCAL_ADDRESS, spiValue);
1227             fail("Expected to fail because duplicate SPI was assigned to the same address.");
1228         } catch (IOException expected) {
1229 
1230         }
1231 
1232         ikeSpiOne.close();
1233         IkeSecurityParameterIndex ikeSpiThree =
1234                 IKE_SPI_GENERATOR.allocateSpi(LOCAL_ADDRESS, spiValue);
1235         ikeSpiThree.close();
1236     }
1237 
setupFirstIkeSa()1238     private void setupFirstIkeSa() throws Exception {
1239         // Inject IkeSaRecord and release IKE SPI resource since we will lose their references
1240         // later.
1241         when(mMockSaRecordHelper.makeFirstIkeSaRecord(any(), any(), any()))
1242                 .thenAnswer(
1243                         (invocation) -> {
1244                             captureAndReleaseIkeSpiResource(invocation, 2);
1245                             mockScheduleRekey(mSpyCurrentIkeSaRecord.mSaLifetimeAlarmScheduler);
1246                             mSpyCurrentIkeSaRecord.mSaLifetimeAlarmScheduler
1247                                     .scheduleLifetimeExpiryAlarm(anyString());
1248                             return mSpyCurrentIkeSaRecord;
1249                         });
1250     }
1251 
setupRekeyedIkeSa(IkeSaRecord rekeySaRecord)1252     private void setupRekeyedIkeSa(IkeSaRecord rekeySaRecord) throws Exception {
1253         // Inject IkeSaRecord and release IKE SPI resource since we will lose their references
1254         // later.
1255         when(mMockSaRecordHelper.makeRekeyedIkeSaRecord(
1256                         eq(mSpyCurrentIkeSaRecord), any(), any(), any(), any()))
1257                 .thenAnswer(
1258                         (invocation) -> {
1259                             captureAndReleaseIkeSpiResource(invocation, 4);
1260                             mockScheduleRekey(rekeySaRecord.mSaLifetimeAlarmScheduler);
1261                             rekeySaRecord.mSaLifetimeAlarmScheduler.scheduleLifetimeExpiryAlarm(
1262                                     anyString());
1263                             return rekeySaRecord;
1264                         });
1265     }
1266 
throwExceptionWhenMakeRekeyIkeSa(Exception exception)1267     private void throwExceptionWhenMakeRekeyIkeSa(Exception exception) throws Exception {
1268         // Inject IkeSaRecord and release IKE SPI resource since we will lose their references
1269         // later.
1270         when(mMockSaRecordHelper.makeRekeyedIkeSaRecord(
1271                         eq(mSpyCurrentIkeSaRecord), any(), any(), any(), any()))
1272                 .thenAnswer(
1273                         (invocation) -> {
1274                             captureAndReleaseIkeSpiResource(invocation, 4);
1275                             throw exception;
1276                         });
1277     }
1278 
captureAndReleaseIkeSpiResource(InvocationOnMock invocation, int ikeConfigIndex)1279     private void captureAndReleaseIkeSpiResource(InvocationOnMock invocation, int ikeConfigIndex) {
1280         IkeSaRecordConfig config = (IkeSaRecordConfig) invocation.getArguments()[ikeConfigIndex];
1281         config.initSpi.close();
1282         config.respSpi.close();
1283     }
1284 
1285     @Test
testResolveRemoteHostName()1286     public void testResolveRemoteHostName() throws Exception {
1287         mIkeSessionStateMachine.quitNow();
1288 
1289         IkeSessionParams ikeParams =
1290                 buildIkeSessionParamsCommon()
1291                         .setAuthPsk(mPsk)
1292                         .setServerHostname(REMOTE_HOSTNAME)
1293                         .build();
1294         mIkeSessionStateMachine = makeAndStartIkeSession(ikeParams);
1295 
1296         verify(mMockDefaultNetwork).getByName(REMOTE_HOSTNAME);
1297     }
1298 
1299     @Test
testEnableTestMode()1300     public void testEnableTestMode() throws Exception {
1301         doReturn(true)
1302                 .when(mMockNetworkCapabilities)
1303                 .hasTransport(RandomnessFactory.TRANSPORT_TEST);
1304 
1305         IkeSessionStateMachine ikeSession = makeAndStartIkeSession(buildIkeSessionParams());
1306 
1307         SecureRandom random = ikeSession.mRandomFactory.getRandom();
1308         assertNotNull(random);
1309         assertTrue(random instanceof DeterministicSecureRandom);
1310     }
1311 
1312     @Test
testDisableTestMode()1313     public void testDisableTestMode() throws Exception {
1314         doReturn(false)
1315                 .when(mMockNetworkCapabilities)
1316                 .hasTransport(RandomnessFactory.TRANSPORT_TEST);
1317 
1318         IkeSessionStateMachine ikeSession = makeAndStartIkeSession(buildIkeSessionParams());
1319 
1320         SecureRandom random = ikeSession.mRandomFactory.getRandom();
1321         assertNull(random);
1322     }
1323 
1324     @Test
testCreateIkeLocalIkeInitNegotiatesDhGroup()1325     public void testCreateIkeLocalIkeInitNegotiatesDhGroup() throws Exception {
1326         setupFirstIkeSa();
1327         mIkeSessionStateMachine.sendMessage(IkeSessionStateMachine.CMD_LOCAL_REQUEST_CREATE_IKE);
1328         mLooper.dispatchAll();
1329 
1330         // Verify we started with the top proposed DH group
1331         assertEquals(
1332                 SaProposal.DH_GROUP_1024_BIT_MODP, mIkeSessionStateMachine.mPeerSelectedDhGroup);
1333 
1334         // Send back a INVALID_KE_PAYLOAD, and verify that the selected DH group changes
1335         ReceivedIkePacket resp =
1336                 makeDummyReceivedIkeInitRespPacket(
1337                         1L /*initiator SPI*/,
1338                         2L /*responder SPI*/,
1339                         IkeHeader.EXCHANGE_TYPE_IKE_SA_INIT,
1340                         true /*isResp*/,
1341                         false /*fromIkeInit*/,
1342                         Arrays.asList(IkePayload.PAYLOAD_TYPE_NOTIFY),
1343                         Arrays.asList(INVALID_KE_PAYLOAD_HEX_STRING));
1344         mIkeSessionStateMachine.sendMessage(IkeSessionStateMachine.CMD_RECEIVE_IKE_PACKET, resp);
1345         mLooper.dispatchAll();
1346 
1347         assertEquals(
1348                 SaProposal.DH_GROUP_2048_BIT_MODP, mIkeSessionStateMachine.mPeerSelectedDhGroup);
1349     }
1350 
1351     @Test
testCreateIkeLocalIkeInitSwitchesToEncapPorts()1352     public void testCreateIkeLocalIkeInitSwitchesToEncapPorts() throws Exception {
1353         setupFirstIkeSa();
1354         mIkeSessionStateMachine.sendMessage(IkeSessionStateMachine.CMD_LOCAL_REQUEST_CREATE_IKE);
1355         mLooper.dispatchAll();
1356 
1357         // Receive IKE INIT response
1358         ReceivedIkePacket dummyReceivedIkePacket = makeIkeInitResponse();
1359         mIkeSessionStateMachine.sendMessage(
1360                 IkeSessionStateMachine.CMD_RECEIVE_IKE_PACKET, dummyReceivedIkePacket);
1361         mLooper.dispatchAll();
1362 
1363         // Validate socket switched
1364         assertTrue(mIkeSessionStateMachine.mIkeSocket instanceof IkeUdpEncapSocket);
1365         verify(mSpyIkeUdp4Socket).unregisterIke(anyLong());
1366     }
1367 
1368     @Ignore
disableTestCreateIkeLocalIkeInit()1369     public void disableTestCreateIkeLocalIkeInit() throws Exception {
1370         setupFirstIkeSa();
1371 
1372         // Send IKE INIT request
1373         mIkeSessionStateMachine.sendMessage(IkeSessionStateMachine.CMD_LOCAL_REQUEST_CREATE_IKE);
1374         mLooper.dispatchAll();
1375         verifyRetransmissionStarted();
1376 
1377         // Receive IKE INIT response
1378         ReceivedIkePacket dummyReceivedIkePacket = makeIkeInitResponse();
1379         mIkeSessionStateMachine.sendMessage(
1380                 IkeSessionStateMachine.CMD_RECEIVE_IKE_PACKET, dummyReceivedIkePacket);
1381         mLooper.dispatchAll();
1382         verifyIncrementLocaReqMsgId();
1383 
1384         // Validate outbound IKE INIT request
1385         verify(mMockIkeMessageHelper, times(2)).encode(mIkeMessageCaptor.capture());
1386         IkeMessage ikeInitReqMessage = mIkeMessageCaptor.getValue();
1387 
1388         IkeHeader ikeHeader = ikeInitReqMessage.ikeHeader;
1389         assertEquals(IkeHeader.EXCHANGE_TYPE_IKE_SA_INIT, ikeHeader.exchangeType);
1390         assertFalse(ikeHeader.isResponseMsg);
1391         assertTrue(ikeHeader.fromIkeInitiator);
1392 
1393         List<IkePayload> payloadList = ikeInitReqMessage.ikePayloadList;
1394         assertTrue(isIkePayloadExist(payloadList, IkePayload.PAYLOAD_TYPE_SA));
1395         assertTrue(isIkePayloadExist(payloadList, IkePayload.PAYLOAD_TYPE_KE));
1396         assertTrue(isIkePayloadExist(payloadList, IkePayload.PAYLOAD_TYPE_NONCE));
1397         assertTrue(isNotifyExist(payloadList, NOTIFY_TYPE_NAT_DETECTION_SOURCE_IP));
1398         assertTrue(isNotifyExist(payloadList, NOTIFY_TYPE_NAT_DETECTION_DESTINATION_IP));
1399         assertTrue(isNotifyExist(payloadList, NOTIFY_TYPE_IKEV2_FRAGMENTATION_SUPPORTED));
1400         assertTrue(isNotifyExist(payloadList, NOTIFY_TYPE_SIGNATURE_HASH_ALGORITHMS));
1401 
1402         verify(mSpyCurrentIkeSocket)
1403                 .registerIke(eq(mSpyCurrentIkeSaRecord.getLocalSpi()), eq(mIkeSessionStateMachine));
1404 
1405         verify(mMockIkeMessageHelper)
1406                 .decode(0, dummyReceivedIkePacket.ikeHeader, dummyReceivedIkePacket.ikePacketBytes);
1407         assertTrue(
1408                 mIkeSessionStateMachine.getCurrentState()
1409                         instanceof IkeSessionStateMachine.CreateIkeLocalIkeAuth);
1410         verifyRetransmissionStarted();
1411 
1412         // Validate negotiated SA proposal.
1413         IkeSaProposal negotiatedProposal = mIkeSessionStateMachine.mSaProposal;
1414         assertNotNull(negotiatedProposal);
1415 
1416         assertEquals(
1417                 new EncryptionTransform[] {mIkeEncryptionTransform},
1418                 negotiatedProposal.getEncryptionTransforms());
1419         assertEquals(
1420                 new IntegrityTransform[] {mIkeIntegrityTransform},
1421                 negotiatedProposal.getIntegrityTransforms());
1422         assertEquals(new PrfTransform[] {mIkePrfTransform}, negotiatedProposal.getPrfTransforms());
1423 
1424         // Validate current IkeSaRecord.
1425         verify(mMockSaRecordHelper)
1426                 .makeFirstIkeSaRecord(
1427                         any(IkeMessage.class),
1428                         any(IkeMessage.class),
1429                         mIkeSaRecordConfigCaptor.capture());
1430 
1431         IkeSaRecordConfig ikeSaRecordConfig = mIkeSaRecordConfigCaptor.getValue();
1432         assertEquals(KEY_LEN_IKE_PRF, ikeSaRecordConfig.prf.getKeyLength());
1433         assertEquals(KEY_LEN_IKE_INTE, ikeSaRecordConfig.integrityKeyLength);
1434         assertEquals(KEY_LEN_IKE_ENCR, ikeSaRecordConfig.encryptionKeyLength);
1435         assertNotNull(ikeSaRecordConfig.saLifetimeAlarmScheduler);
1436 
1437         // Validate NAT detection
1438         assertTrue(mIkeSessionStateMachine.mIsLocalBehindNat);
1439         assertFalse(mIkeSessionStateMachine.mIsRemoteBehindNat);
1440 
1441         // Validate vendor IDs
1442         assertByteArrayListEquals(
1443                 Arrays.asList(REMOTE_VENDOR_ID_ONE), mIkeSessionStateMachine.mRemoteVendorIds);
1444 
1445         // Validate fragmentation support negotiation
1446         assertTrue(mIkeSessionStateMachine.mSupportFragment);
1447         assertEquals(
1448                 Arrays.asList(EXTENSION_TYPE_FRAGMENTATION),
1449                 mIkeSessionStateMachine.mEnabledExtensions);
1450     }
1451 
setIkeInitResults()1452     private void setIkeInitResults() throws Exception {
1453         mIkeSessionStateMachine.mIkeCipher = mock(IkeCipher.class);
1454         mIkeSessionStateMachine.mIkeIntegrity = mock(IkeMacIntegrity.class);
1455         mIkeSessionStateMachine.mIkePrf = mock(IkeMacPrf.class);
1456         mIkeSessionStateMachine.mSaProposal = buildNegotiatedSaProposal();
1457         mIkeSessionStateMachine.mCurrentIkeSaRecord = mSpyCurrentIkeSaRecord;
1458         mIkeSessionStateMachine.mLocalAddress = LOCAL_ADDRESS;
1459         mIkeSessionStateMachine.mIsLocalBehindNat = true;
1460         mIkeSessionStateMachine.mIsRemoteBehindNat = false;
1461         mIkeSessionStateMachine.mSupportFragment = true;
1462         mIkeSessionStateMachine.mRemoteVendorIds =
1463                 Arrays.asList(REMOTE_VENDOR_ID_ONE, REMOTE_VENDOR_ID_TWO);
1464         mIkeSessionStateMachine.mEnabledExtensions = Arrays.asList(EXTENSION_TYPE_FRAGMENTATION);
1465         mIkeSessionStateMachine.addIkeSaRecord(mSpyCurrentIkeSaRecord);
1466 
1467         mSpyCurrentIkeSocket = mSpyIkeUdpEncapSocket;
1468         mIkeSessionStateMachine.mIkeSocket = mSpyCurrentIkeSocket;
1469     }
1470 
1471     /** Initializes the mIkeSessionStateMachine in the IDLE state. */
setupIdleStateMachine()1472     private void setupIdleStateMachine() throws Exception {
1473         verify(mMockBusyWakelock).acquire();
1474 
1475         setIkeInitResults();
1476 
1477         mIkeSessionStateMachine.sendMessage(
1478                 IkeSessionStateMachine.CMD_FORCE_TRANSITION, mIkeSessionStateMachine.mIdle);
1479         mLooper.dispatchAll();
1480 
1481         mDummyChildSmCallback =
1482                 createChildAndGetChildSessionSmCallback(
1483                         mMockChildSessionStateMachine, CHILD_SPI_REMOTE, mMockChildSessionCallback);
1484 
1485         assertTrue(
1486                 mIkeSessionStateMachine.getCurrentState() instanceof IkeSessionStateMachine.Idle);
1487 
1488         verify(mMockBusyWakelock).release();
1489 
1490         // For convenience to verify wakelocks in all other places.
1491         reset(mMockBusyWakelock);
1492     }
1493 
mockIkeInitAndTransitionToIkeAuth(State authState)1494     private void mockIkeInitAndTransitionToIkeAuth(State authState) throws Exception {
1495         setIkeInitResults();
1496 
1497         // Need to create a real IkeMacPrf instance for authentication because we cannot inject a
1498         // method stub for IkeMacPrf#signBytes. IkeMacPrf#signBytes is inheritted from a package
1499         // protected class IkePrf. We don't have the visibility to mock it.
1500         mIkeSessionStateMachine.mIkePrf =
1501                 IkeMacPrf.create(new PrfTransform(SaProposal.PSEUDORANDOM_FUNCTION_HMAC_SHA1));
1502 
1503         mIkeSessionStateMachine.mIkeInitRequestBytes = new byte[0];
1504         mIkeSessionStateMachine.mIkeInitResponseBytes = new byte[0];
1505         mIkeSessionStateMachine.mIkeInitNoncePayload =
1506                 new IkeNoncePayload(createMockRandomFactory());
1507         mIkeSessionStateMachine.mIkeRespNoncePayload =
1508                 new IkeNoncePayload(createMockRandomFactory());
1509 
1510         mIkeSessionStateMachine.sendMessage(IkeSessionStateMachine.CMD_FORCE_TRANSITION, authState);
1511         mLooper.dispatchAll();
1512     }
1513 
setupChildStateMachineFactory(ChildSessionStateMachine child)1514     private void setupChildStateMachineFactory(ChildSessionStateMachine child) {
1515         // After state machine start, add to the callback->statemachine map
1516         when(mMockChildSessionFactoryHelper.makeChildSessionStateMachine(
1517                         eq(mLooper.getLooper()),
1518                         eq(mSpyContext),
1519                         anyInt(),
1520                         any(AlarmManager.class),
1521                         any(RandomnessFactory.class),
1522                         any(IpSecSpiGenerator.class),
1523                         eq(mChildSessionParams),
1524                         eq(mSpyUserCbExecutor),
1525                         any(ChildSessionCallback.class),
1526                         any(IChildSessionSmCallback.class)))
1527                 .thenReturn(child);
1528     }
1529 
1530     /**
1531      * Utility to register a new callback -> state machine mapping.
1532      *
1533      * <p>Must be used if IkeSessionStateMachine.openChildSession() is not called, but commands
1534      * injected instead.
1535      *
1536      * @param callback The callback to be used for the mapping
1537      * @param sm The ChildSessionStateMachine instance to be used.
1538      */
registerChildStateMachine( ChildSessionCallback callback, ChildSessionStateMachine sm)1539     private void registerChildStateMachine(
1540             ChildSessionCallback callback, ChildSessionStateMachine sm) {
1541         setupChildStateMachineFactory(sm);
1542         mIkeSessionStateMachine.registerChildSessionCallback(
1543                 mChildSessionParams, callback, false /*isFirstChild*/);
1544     }
1545 
1546     @Test
testCreateAdditionalChild()1547     public void testCreateAdditionalChild() throws Exception {
1548         setupIdleStateMachine();
1549 
1550         ChildSessionCallback childCallback = mock(ChildSessionCallback.class);
1551         ChildSessionStateMachine childStateMachine = mock(ChildSessionStateMachine.class);
1552         registerChildStateMachine(childCallback, childStateMachine);
1553 
1554         mIkeSessionStateMachine.sendMessage(
1555                 IkeSessionStateMachine.CMD_EXECUTE_LOCAL_REQ,
1556                 new ChildLocalRequest(
1557                         IkeSessionStateMachine.CMD_LOCAL_REQUEST_CREATE_CHILD,
1558                         childCallback,
1559                         mChildSessionParams));
1560         mLooper.dispatchAll();
1561 
1562         assertTrue(
1563                 mIkeSessionStateMachine.getCurrentState()
1564                         instanceof IkeSessionStateMachine.ChildProcedureOngoing);
1565         verify(childStateMachine)
1566                 .createChildSession(
1567                         eq(LOCAL_ADDRESS),
1568                         eq(REMOTE_ADDRESS),
1569                         any(), // udpEncapSocket
1570                         eq(mIkeSessionStateMachine.mIkePrf),
1571                         any()); // sk_d
1572 
1573         // Once for initial child, a second time for the additional child.
1574         verify(mMockChildSessionFactoryHelper)
1575                 .makeChildSessionStateMachine(
1576                         eq(mLooper.getLooper()),
1577                         eq(mSpyContext),
1578                         anyInt(),
1579                         any(AlarmManager.class),
1580                         any(RandomnessFactory.class),
1581                         any(IpSecSpiGenerator.class),
1582                         eq(mChildSessionParams),
1583                         eq(mSpyUserCbExecutor),
1584                         eq(childCallback),
1585                         mChildSessionSmCbCaptor.capture());
1586         IChildSessionSmCallback cb = mChildSessionSmCbCaptor.getValue();
1587 
1588         // Mocking sending request
1589         cb.onOutboundPayloadsReady(
1590                 IkeHeader.EXCHANGE_TYPE_CREATE_CHILD_SA,
1591                 false /*isResp*/,
1592                 new LinkedList<>(),
1593                 childStateMachine);
1594         mLooper.dispatchAll();
1595         verifyRetransmissionStarted();
1596 
1597         IkeMessage createChildRequest = verifyEncryptAndEncodeAndGetMessage(mSpyCurrentIkeSaRecord);
1598 
1599         IkeHeader ikeHeader = createChildRequest.ikeHeader;
1600         assertEquals(IkeHeader.EXCHANGE_TYPE_CREATE_CHILD_SA, ikeHeader.exchangeType);
1601         assertFalse(ikeHeader.isResponseMsg);
1602         assertTrue(ikeHeader.fromIkeInitiator);
1603         assertEquals(mSpyCurrentIkeSaRecord.getLocalRequestMessageId(), ikeHeader.messageId);
1604         assertTrue(createChildRequest.ikePayloadList.isEmpty());
1605 
1606         assertTrue(
1607                 mIkeSessionStateMachine.getCurrentState()
1608                         instanceof IkeSessionStateMachine.ChildProcedureOngoing);
1609 
1610         // Mocking receiving response
1611         ReceivedIkePacket dummyCreateChildResp = makeCreateChildCreateMessage(true /*isResp*/);
1612         mIkeSessionStateMachine.sendMessage(
1613                 IkeSessionStateMachine.CMD_RECEIVE_IKE_PACKET, dummyCreateChildResp);
1614         mLooper.dispatchAll();
1615 
1616         verifyIncrementLocaReqMsgId();
1617         verifyDecodeEncryptedMessage(mSpyCurrentIkeSaRecord, dummyCreateChildResp);
1618 
1619         verify(childStateMachine)
1620                 .receiveResponse(
1621                         eq(IkeHeader.EXCHANGE_TYPE_CREATE_CHILD_SA), mPayloadListCaptor.capture());
1622 
1623         List<IkePayload> childRespList = mPayloadListCaptor.getValue();
1624         assertTrue(isIkePayloadExist(childRespList, IkePayload.PAYLOAD_TYPE_SA));
1625         assertTrue(isIkePayloadExist(childRespList, IkePayload.PAYLOAD_TYPE_TS_INITIATOR));
1626         assertTrue(isIkePayloadExist(childRespList, IkePayload.PAYLOAD_TYPE_TS_RESPONDER));
1627         assertTrue(isIkePayloadExist(childRespList, IkePayload.PAYLOAD_TYPE_NONCE));
1628 
1629         // Mock finishing procedure
1630         cb.onProcedureFinished(childStateMachine);
1631         mLooper.dispatchAll();
1632         assertTrue(
1633                 mIkeSessionStateMachine.getCurrentState() instanceof IkeSessionStateMachine.Idle);
1634         verifyRetransmissionStopped();
1635     }
1636 
1637     @Test
testTriggerDeleteChildLocal()1638     public void testTriggerDeleteChildLocal() throws Exception {
1639         setupIdleStateMachine();
1640 
1641         mIkeSessionStateMachine.sendMessage(
1642                 IkeSessionStateMachine.CMD_EXECUTE_LOCAL_REQ,
1643                 new ChildLocalRequest(
1644                         IkeSessionStateMachine.CMD_LOCAL_REQUEST_DELETE_CHILD,
1645                         mMockChildSessionCallback,
1646                         null /*childParams*/));
1647         mLooper.dispatchAll();
1648 
1649         assertTrue(
1650                 mIkeSessionStateMachine.getCurrentState()
1651                         instanceof IkeSessionStateMachine.ChildProcedureOngoing);
1652         verify(mMockChildSessionStateMachine).deleteChildSession();
1653         verify(mMockBusyWakelock).acquire();
1654     }
1655 
1656     @Test
testHandleDeleteChildBeforeCreation()1657     public void testHandleDeleteChildBeforeCreation() throws Exception {
1658         setupIdleStateMachine();
1659 
1660         mIkeSessionStateMachine.sendMessage(
1661                 IkeSessionStateMachine.CMD_EXECUTE_LOCAL_REQ,
1662                 new ChildLocalRequest(
1663                         IkeSessionStateMachine.CMD_LOCAL_REQUEST_DELETE_CHILD,
1664                         mock(ChildSessionCallback.class),
1665                         null /*childParams*/));
1666         mLooper.dispatchAll();
1667 
1668         assertTrue(
1669                 mIkeSessionStateMachine.getCurrentState() instanceof IkeSessionStateMachine.Idle);
1670     }
1671 
1672     @Test
testTriggerRekeyChildLocal()1673     public void testTriggerRekeyChildLocal() throws Exception {
1674         setupIdleStateMachine();
1675 
1676         mIkeSessionStateMachine.sendMessage(
1677                 IkeSessionStateMachine.CMD_EXECUTE_LOCAL_REQ,
1678                 new ChildLocalRequest(
1679                         IkeSessionStateMachine.CMD_LOCAL_REQUEST_REKEY_CHILD,
1680                         mMockChildSessionCallback,
1681                         null /*childParams*/));
1682         mLooper.dispatchAll();
1683 
1684         assertTrue(
1685                 mIkeSessionStateMachine.getCurrentState()
1686                         instanceof IkeSessionStateMachine.ChildProcedureOngoing);
1687         verify(mMockChildSessionStateMachine).rekeyChildSession();
1688         verify(mMockBusyWakelock).acquire();
1689     }
1690 
createChildAndGetChildSessionSmCallback( ChildSessionStateMachine child, int remoteSpi)1691     private IChildSessionSmCallback createChildAndGetChildSessionSmCallback(
1692             ChildSessionStateMachine child, int remoteSpi) throws Exception {
1693         return createChildAndGetChildSessionSmCallback(
1694                 child, remoteSpi, mock(ChildSessionCallback.class));
1695     }
1696 
createChildAndGetChildSessionSmCallback( ChildSessionStateMachine child, int remoteSpi, ChildSessionCallback childCallback)1697     private IChildSessionSmCallback createChildAndGetChildSessionSmCallback(
1698             ChildSessionStateMachine child, int remoteSpi, ChildSessionCallback childCallback)
1699             throws Exception {
1700         registerChildStateMachine(childCallback, child);
1701 
1702         IChildSessionSmCallback cb = mIkeSessionStateMachine.new ChildSessionSmCallback();
1703         cb.onChildSaCreated(remoteSpi, child);
1704         mLooper.dispatchAll();
1705 
1706         return cb;
1707     }
1708 
transitionToChildProcedureOngoing()1709     private void transitionToChildProcedureOngoing() {
1710         mIkeSessionStateMachine.sendMessage(
1711                 IkeSessionStateMachine.CMD_FORCE_TRANSITION,
1712                 mIkeSessionStateMachine.mChildProcedureOngoing);
1713         mLooper.dispatchAll();
1714         assertTrue(
1715                 mIkeSessionStateMachine.getCurrentState()
1716                         instanceof IkeSessionStateMachine.ChildProcedureOngoing);
1717     }
1718 
verifyChildReceiveDeleteRequest( ChildSessionStateMachine child, IkeDeletePayload[] expectedDelPayloads)1719     private void verifyChildReceiveDeleteRequest(
1720             ChildSessionStateMachine child, IkeDeletePayload[] expectedDelPayloads) {
1721         verify(child)
1722                 .receiveRequest(
1723                         eq(IKE_EXCHANGE_SUBTYPE_DELETE_CHILD),
1724                         eq(EXCHANGE_TYPE_INFORMATIONAL),
1725                         mPayloadListCaptor.capture());
1726         List<IkePayload> reqPayloads = mPayloadListCaptor.getValue();
1727 
1728         int numExpectedDelPayloads = expectedDelPayloads.length;
1729         assertEquals(numExpectedDelPayloads, reqPayloads.size());
1730 
1731         for (int i = 0; i < numExpectedDelPayloads; i++) {
1732             assertEquals(expectedDelPayloads[i], (IkeDeletePayload) reqPayloads.get(i));
1733         }
1734     }
1735 
outboundDeleteChildPayloadsReady( IChildSessionSmCallback childSmCb, IkeDeletePayload delPayload, boolean isResp, ChildSessionStateMachine child)1736     private void outboundDeleteChildPayloadsReady(
1737             IChildSessionSmCallback childSmCb,
1738             IkeDeletePayload delPayload,
1739             boolean isResp,
1740             ChildSessionStateMachine child) {
1741         List<IkePayload> outPayloadList = new LinkedList<>();
1742         outPayloadList.add(delPayload);
1743         childSmCb.onOutboundPayloadsReady(
1744                 IkeHeader.EXCHANGE_TYPE_INFORMATIONAL, isResp, outPayloadList, child);
1745         mLooper.dispatchAll();
1746     }
1747 
verifyOutInfoMsgHeaderAndGetPayloads(boolean isResp)1748     private List<IkePayload> verifyOutInfoMsgHeaderAndGetPayloads(boolean isResp) {
1749         IkeMessage deleteChildMessage = verifyEncryptAndEncodeAndGetMessage(mSpyCurrentIkeSaRecord);
1750 
1751         IkeHeader ikeHeader = deleteChildMessage.ikeHeader;
1752         assertEquals(mSpyCurrentIkeSaRecord.getInitiatorSpi(), ikeHeader.ikeInitiatorSpi);
1753         assertEquals(mSpyCurrentIkeSaRecord.getResponderSpi(), ikeHeader.ikeResponderSpi);
1754         assertEquals(IkePayload.PAYLOAD_TYPE_SK, ikeHeader.nextPayloadType);
1755         assertEquals(IkeHeader.EXCHANGE_TYPE_INFORMATIONAL, ikeHeader.exchangeType);
1756         assertEquals(mSpyCurrentIkeSaRecord.isLocalInit, ikeHeader.fromIkeInitiator);
1757         assertEquals(isResp, ikeHeader.isResponseMsg);
1758 
1759         return deleteChildMessage.ikePayloadList;
1760     }
1761 
1762     @Test
testDeferChildRequestToChildProcedureOngoing()1763     public void testDeferChildRequestToChildProcedureOngoing() throws Exception {
1764         setupIdleStateMachine();
1765 
1766         IkeDeletePayload[] inboundDelPayloads =
1767                 new IkeDeletePayload[] {new IkeDeletePayload(new int[] {CHILD_SPI_REMOTE})};
1768         mIkeSessionStateMachine.sendMessage(
1769                 IkeSessionStateMachine.CMD_RECEIVE_IKE_PACKET,
1770                 makeDeleteChildPacket(inboundDelPayloads, false /*isResp*/));
1771         mLooper.dispatchAll();
1772 
1773         assertTrue(
1774                 mIkeSessionStateMachine.getCurrentState()
1775                         instanceof IkeSessionStateMachine.ChildProcedureOngoing);
1776         verifyChildReceiveDeleteRequest(mMockChildSessionStateMachine, inboundDelPayloads);
1777     }
1778 
1779     @Test
testRemoteDeleteOneChild()1780     public void testRemoteDeleteOneChild() throws Exception {
1781         setupIdleStateMachine();
1782         transitionToChildProcedureOngoing();
1783 
1784         // Receive Delete Child Request
1785         IkeDeletePayload[] inboundDelPayloads =
1786                 new IkeDeletePayload[] {new IkeDeletePayload(new int[] {CHILD_SPI_REMOTE})};
1787         mIkeSessionStateMachine.sendMessage(
1788                 IkeSessionStateMachine.CMD_RECEIVE_IKE_PACKET,
1789                 makeDeleteChildPacket(inboundDelPayloads, false /*isResp*/));
1790         mLooper.dispatchAll();
1791 
1792         // Verify received payloads
1793         verifyChildReceiveDeleteRequest(mMockChildSessionStateMachine, inboundDelPayloads);
1794 
1795         // Outbound payload list ready
1796         IkeDeletePayload outDelPayload = new IkeDeletePayload(new int[] {CHILD_SPI_LOCAL});
1797         outboundDeleteChildPayloadsReady(
1798                 mDummyChildSmCallback,
1799                 outDelPayload,
1800                 true /*isResp*/,
1801                 mMockChildSessionStateMachine);
1802 
1803         // Verify outbound response
1804         List<IkePayload> payloadList = verifyOutInfoMsgHeaderAndGetPayloads(true /*isResp*/);
1805         assertEquals(1, payloadList.size());
1806         assertEquals(outDelPayload, ((IkeDeletePayload) payloadList.get(0)));
1807         verify(mMockBusyWakelock).acquire();
1808     }
1809 
1810     @Test
testRemoteDeleteMultipleChildSession()1811     public void testRemoteDeleteMultipleChildSession() throws Exception {
1812         ChildSessionStateMachine childOne = mock(ChildSessionStateMachine.class);
1813         int childOneRemoteSpi = 11;
1814         int childOneLocalSpi = 12;
1815 
1816         ChildSessionStateMachine childTwo = mock(ChildSessionStateMachine.class);
1817         int childTwoRemoteSpi = 21;
1818         int childTwoLocalSpi = 22;
1819 
1820         setupIdleStateMachine();
1821         IChildSessionSmCallback childSmCbOne =
1822                 createChildAndGetChildSessionSmCallback(childOne, childOneRemoteSpi);
1823         IChildSessionSmCallback childSmCbTwo =
1824                 createChildAndGetChildSessionSmCallback(childTwo, childTwoRemoteSpi);
1825 
1826         transitionToChildProcedureOngoing();
1827 
1828         // Receive Delete Child Request
1829         IkeDeletePayload[] inboundDelPayloads =
1830                 new IkeDeletePayload[] {
1831                     new IkeDeletePayload(new int[] {childOneRemoteSpi, childTwoRemoteSpi})
1832                 };
1833         mIkeSessionStateMachine.sendMessage(
1834                 IkeSessionStateMachine.CMD_RECEIVE_IKE_PACKET,
1835                 makeDeleteChildPacket(inboundDelPayloads, false /*isResp*/));
1836         mLooper.dispatchAll();
1837 
1838         // Verify received payloads
1839         verifyChildReceiveDeleteRequest(childOne, inboundDelPayloads);
1840         verifyChildReceiveDeleteRequest(childTwo, inboundDelPayloads);
1841 
1842         // childOne outbound payload list ready
1843         IkeDeletePayload outDelPayloadOne = new IkeDeletePayload(new int[] {childOneLocalSpi});
1844         outboundDeleteChildPayloadsReady(childSmCbOne, outDelPayloadOne, true /*isResp*/, childOne);
1845         mLooper.dispatchAll();
1846 
1847         // Verify that no response is sent
1848         verifyEncryptAndEncodeNeverCalled(mSpyCurrentIkeSaRecord);
1849 
1850         // childTwo outbound payload list ready
1851         IkeDeletePayload outDelPayloadTwo = new IkeDeletePayload(new int[] {childTwoLocalSpi});
1852         outboundDeleteChildPayloadsReady(childSmCbTwo, outDelPayloadTwo, true /*isResp*/, childTwo);
1853         mLooper.dispatchAll();
1854 
1855         // Verify outbound response
1856         List<IkePayload> payloadList = verifyOutInfoMsgHeaderAndGetPayloads(true /*isResp*/);
1857         assertEquals(2, payloadList.size());
1858         assertEquals(outDelPayloadOne, ((IkeDeletePayload) payloadList.get(0)));
1859         assertEquals(outDelPayloadTwo, ((IkeDeletePayload) payloadList.get(1)));
1860     }
1861 
1862     @Test
testRemoteDeleteMultipleChildSaInSameSession()1863     public void testRemoteDeleteMultipleChildSaInSameSession() throws Exception {
1864         int newChildRemoteSpi = 21;
1865         int newChildLocalSpi = 22;
1866 
1867         setupIdleStateMachine();
1868         mDummyChildSmCallback.onChildSaCreated(newChildRemoteSpi, mMockChildSessionStateMachine);
1869 
1870         transitionToChildProcedureOngoing();
1871 
1872         // Receive Delete Child Request
1873         IkeDeletePayload[] inboundDelPayloads =
1874                 new IkeDeletePayload[] {
1875                     new IkeDeletePayload(new int[] {CHILD_SPI_REMOTE}),
1876                     new IkeDeletePayload(new int[] {newChildRemoteSpi})
1877                 };
1878         mIkeSessionStateMachine.sendMessage(
1879                 IkeSessionStateMachine.CMD_RECEIVE_IKE_PACKET,
1880                 makeDeleteChildPacket(inboundDelPayloads, false /*isResp*/));
1881         mLooper.dispatchAll();
1882 
1883         // Verify received payloads
1884         verifyChildReceiveDeleteRequest(mMockChildSessionStateMachine, inboundDelPayloads);
1885 
1886         // child outbound payload list ready
1887         IkeDeletePayload outDelPayload =
1888                 new IkeDeletePayload(new int[] {CHILD_SPI_LOCAL, newChildLocalSpi});
1889         outboundDeleteChildPayloadsReady(
1890                 mDummyChildSmCallback,
1891                 outDelPayload,
1892                 true /*isResp*/,
1893                 mMockChildSessionStateMachine);
1894         mLooper.dispatchAll();
1895 
1896         // Verify outbound response
1897         List<IkePayload> payloadList = verifyOutInfoMsgHeaderAndGetPayloads(true /*isResp*/);
1898         assertEquals(1, payloadList.size());
1899         assertEquals(outDelPayload, ((IkeDeletePayload) payloadList.get(0)));
1900     }
1901 
1902     @Test
testIgnoreUnrecognizedChildSpi()1903     public void testIgnoreUnrecognizedChildSpi() throws Exception {
1904         int unrecognizedSpi = 2;
1905 
1906         setupIdleStateMachine();
1907         transitionToChildProcedureOngoing();
1908 
1909         // Receive Delete Child Request
1910         IkeDeletePayload[] inboundDelPayloads =
1911                 new IkeDeletePayload[] {
1912                     new IkeDeletePayload(new int[] {unrecognizedSpi, CHILD_SPI_REMOTE})
1913                 };
1914         mIkeSessionStateMachine.sendMessage(
1915                 IkeSessionStateMachine.CMD_RECEIVE_IKE_PACKET,
1916                 makeDeleteChildPacket(inboundDelPayloads, false /*isResp*/));
1917         mLooper.dispatchAll();
1918 
1919         // Verify received payloads
1920         verifyChildReceiveDeleteRequest(mMockChildSessionStateMachine, inboundDelPayloads);
1921 
1922         // child outbound payload list ready
1923         IkeDeletePayload outPayload = new IkeDeletePayload(new int[] {CHILD_SPI_LOCAL});
1924         outboundDeleteChildPayloadsReady(
1925                 mDummyChildSmCallback, outPayload, true /*isResp*/, mMockChildSessionStateMachine);
1926         mLooper.dispatchAll();
1927 
1928         // Verify outbound response
1929         List<IkePayload> payloadList = verifyOutInfoMsgHeaderAndGetPayloads(true /*isResp*/);
1930         assertEquals(1, payloadList.size());
1931         assertEquals(outPayload, ((IkeDeletePayload) payloadList.get(0)));
1932     }
1933 
1934     @Test
testRemoteDeleteChildHandlesReqWithNoRecognizedSpi()1935     public void testRemoteDeleteChildHandlesReqWithNoRecognizedSpi() throws Exception {
1936         int unrecognizedSpi = 2;
1937 
1938         setupIdleStateMachine();
1939 
1940         // Receive Delete Child Request without any recognized SPI
1941         IkeDeletePayload[] inboundDelPayloads =
1942                 new IkeDeletePayload[] {new IkeDeletePayload(new int[] {unrecognizedSpi})};
1943         mIkeSessionStateMachine.sendMessage(
1944                 IkeSessionStateMachine.CMD_RECEIVE_IKE_PACKET,
1945                 makeDeleteChildPacket(inboundDelPayloads, false /*isResp*/));
1946         mLooper.dispatchAll();
1947 
1948         // Verify outbound empty response was sent
1949         List<IkePayload> payloadList = verifyOutInfoMsgHeaderAndGetPayloads(true /*isResp*/);
1950         assertTrue(payloadList.isEmpty());
1951 
1952         // Verify IKE Session was back to Idle
1953         assertTrue(
1954                 mIkeSessionStateMachine.getCurrentState() instanceof IkeSessionStateMachine.Idle);
1955     }
1956 
1957     @Test
testRemoteCreateChild()1958     public void testRemoteCreateChild() throws Exception {
1959         setupIdleStateMachine();
1960 
1961         mIkeSessionStateMachine.sendMessage(
1962                 CMD_RECEIVE_IKE_PACKET, makeCreateChildCreateMessage(false /*isResp*/));
1963 
1964         mLooper.dispatchAll();
1965 
1966         assertTrue(
1967                 mIkeSessionStateMachine.getCurrentState() instanceof IkeSessionStateMachine.Idle);
1968 
1969         List<IkePayload> ikePayloadList = verifyOutInfoMsgHeaderAndGetPayloads(true /*isResp*/);
1970         assertEquals(1, ikePayloadList.size());
1971         assertEquals(
1972                 ERROR_TYPE_NO_ADDITIONAL_SAS,
1973                 ((IkeNotifyPayload) ikePayloadList.get(0)).notifyType);
1974     }
1975 
1976     @Test
testTriggerRemoteRekeyChild()1977     public void testTriggerRemoteRekeyChild() throws Exception {
1978         setupIdleStateMachine();
1979 
1980         mIkeSessionStateMachine.sendMessage(
1981                 CMD_RECEIVE_IKE_PACKET,
1982                 makeRekeyChildCreateMessage(false /*isResp*/, CHILD_SPI_REMOTE));
1983         mLooper.dispatchAll();
1984 
1985         verify(mMockChildSessionStateMachine)
1986                 .receiveRequest(
1987                         eq(IKE_EXCHANGE_SUBTYPE_REKEY_CHILD),
1988                         eq(EXCHANGE_TYPE_CREATE_CHILD_SA),
1989                         any(List.class));
1990         assertTrue(
1991                 mIkeSessionStateMachine.getCurrentState()
1992                         instanceof IkeSessionStateMachine.ChildProcedureOngoing);
1993     }
1994 
1995     @Test
testHandleRekeyChildReqWithUnrecognizedSpi()1996     public void testHandleRekeyChildReqWithUnrecognizedSpi() throws Exception {
1997         int unrecognizedSpi = 2;
1998 
1999         setupIdleStateMachine();
2000 
2001         mIkeSessionStateMachine.sendMessage(
2002                 CMD_RECEIVE_IKE_PACKET,
2003                 makeRekeyChildCreateMessage(false /*isResp*/, unrecognizedSpi));
2004         mLooper.dispatchAll();
2005 
2006         verify(mMockChildSessionStateMachine, never()).receiveRequest(anyInt(), anyInt(), any());
2007         assertTrue(
2008                 mIkeSessionStateMachine.getCurrentState() instanceof IkeSessionStateMachine.Idle);
2009 
2010         List<IkePayload> ikePayloadList = verifyOutInfoMsgHeaderAndGetPayloads(true /*isResp*/);
2011         assertEquals(1, ikePayloadList.size());
2012         IkeNotifyPayload notifyPayload = (IkeNotifyPayload) ikePayloadList.get(0);
2013         assertEquals(ERROR_TYPE_CHILD_SA_NOT_FOUND, notifyPayload.notifyType);
2014         assertEquals(unrecognizedSpi, notifyPayload.spi);
2015     }
2016 
verifyNotifyUserCloseSession()2017     private void verifyNotifyUserCloseSession() {
2018         verify(mSpyUserCbExecutor).execute(any(Runnable.class));
2019         verify(mMockIkeSessionCallback).onClosed();
2020     }
2021 
2022     @Test
testRcvRemoteDeleteIkeWhenChildProcedureOngoing()2023     public void testRcvRemoteDeleteIkeWhenChildProcedureOngoing() throws Exception {
2024         setupIdleStateMachine();
2025         transitionToChildProcedureOngoing();
2026 
2027         mIkeSessionStateMachine.sendMessage(
2028                 CMD_RECEIVE_IKE_PACKET, makeDeleteIkeRequest(mSpyCurrentIkeSaRecord));
2029 
2030         mLooper.dispatchAll();
2031 
2032         verifyNotifyUserCloseSession();
2033 
2034         // Verify state machine quit properly
2035         assertNull(mIkeSessionStateMachine.getCurrentState());
2036 
2037         List<IkePayload> ikePayloadList = verifyOutInfoMsgHeaderAndGetPayloads(true /*isResp*/);
2038         assertTrue(ikePayloadList.isEmpty());
2039     }
2040 
2041     @Test
testRcvRemoteRekeyIkeWhenChildProcedureOngoing()2042     public void testRcvRemoteRekeyIkeWhenChildProcedureOngoing() throws Exception {
2043         setupIdleStateMachine();
2044         transitionToChildProcedureOngoing();
2045 
2046         mIkeSessionStateMachine.sendMessage(CMD_RECEIVE_IKE_PACKET, makeRekeyIkeRequest());
2047 
2048         mLooper.dispatchAll();
2049 
2050         // Since we have forced state machine to transition to ChildProcedureOngoing state without
2051         // really starting any Child procedure, it should transition to Idle at this time.
2052         assertTrue(
2053                 mIkeSessionStateMachine.getCurrentState() instanceof IkeSessionStateMachine.Idle);
2054 
2055         List<IkePayload> ikePayloadList = verifyOutInfoMsgHeaderAndGetPayloads(true /*isResp*/);
2056         assertEquals(1, ikePayloadList.size());
2057         assertEquals(
2058                 ERROR_TYPE_TEMPORARY_FAILURE,
2059                 ((IkeNotifyPayload) ikePayloadList.get(0)).notifyType);
2060     }
2061 
2062     @Test
testKillChildSessions()2063     public void testKillChildSessions() throws Exception {
2064         setupIdleStateMachine();
2065 
2066         ChildSessionStateMachine childOne = mock(ChildSessionStateMachine.class);
2067         ChildSessionStateMachine childTwo = mock(ChildSessionStateMachine.class);
2068         registerChildStateMachine(mock(ChildSessionCallback.class), childOne);
2069         registerChildStateMachine(mock(ChildSessionCallback.class), childTwo);
2070 
2071         mIkeSessionStateMachine.mCurrentIkeSaRecord = null;
2072 
2073         mIkeSessionStateMachine.quitNow();
2074 
2075         mLooper.dispatchAll();
2076 
2077         verify(childOne).killSession();
2078         verify(childTwo).killSession();
2079     }
2080 
verifyAuthReqAndGetMsg()2081     private IkeMessage verifyAuthReqAndGetMsg() {
2082         IkeMessage ikeAuthReqMessage = verifyEncryptAndEncodeAndGetMessage(mSpyCurrentIkeSaRecord);
2083 
2084         IkeHeader ikeHeader = ikeAuthReqMessage.ikeHeader;
2085         assertEquals(IkeHeader.EXCHANGE_TYPE_IKE_AUTH, ikeHeader.exchangeType);
2086         assertFalse(ikeHeader.isResponseMsg);
2087         assertTrue(ikeHeader.fromIkeInitiator);
2088 
2089         return ikeAuthReqMessage;
2090     }
2091 
verifyAuthReqWithChildPayloadsAndGetMsg()2092     private IkeMessage verifyAuthReqWithChildPayloadsAndGetMsg() {
2093         IkeMessage ikeAuthReqMessage = verifyAuthReqAndGetMsg();
2094 
2095         assertNotNull(
2096                 ikeAuthReqMessage.getPayloadForType(
2097                         IkePayload.PAYLOAD_TYPE_ID_INITIATOR, IkeIdPayload.class));
2098         assertNotNull(
2099                 ikeAuthReqMessage.getPayloadForType(
2100                         IkePayload.PAYLOAD_TYPE_ID_RESPONDER, IkeIdPayload.class));
2101         assertNotNull(
2102                 ikeAuthReqMessage.getPayloadForType(
2103                         IkePayload.PAYLOAD_TYPE_SA, IkeSaPayload.class));
2104         assertNotNull(
2105                 ikeAuthReqMessage.getPayloadForType(
2106                         IkePayload.PAYLOAD_TYPE_TS_INITIATOR, IkeTsPayload.class));
2107         assertNotNull(
2108                 ikeAuthReqMessage.getPayloadForType(
2109                         IkePayload.PAYLOAD_TYPE_TS_RESPONDER, IkeTsPayload.class));
2110 
2111         IkeConfigPayload configPayload =
2112                 ikeAuthReqMessage.getPayloadForType(
2113                         IkePayload.PAYLOAD_TYPE_CP, IkeConfigPayload.class);
2114         assertNotNull(configPayload);
2115 
2116         Map<Integer, Integer> expectedAttributes =
2117                 Map.of(
2118                         CONFIG_ATTR_IP4_PCSCF,
2119                         1,
2120                         CONFIG_ATTR_IP6_PCSCF,
2121                         1,
2122                         CONFIG_ATTR_INTERNAL_IP4_ADDRESS,
2123                         1,
2124                         CONFIG_ATTR_INTERNAL_IP6_ADDRESS,
2125                         1,
2126                         CONFIG_ATTR_APPLICATION_VERSION,
2127                         1,
2128                         CONFIG_ATTR_INTERNAL_IP4_NETMASK,
2129                         1);
2130         Map<Integer, Integer> actualAttributes =
2131                 buildAttributeMap(configPayload.recognizedAttributeList);
2132         assertEquals(expectedAttributes, actualAttributes);
2133 
2134         IkeNoncePayload noncePayload =
2135                 ikeAuthReqMessage.getPayloadForType(
2136                         IkePayload.PAYLOAD_TYPE_NONCE, IkeNoncePayload.class);
2137         assertNull(noncePayload);
2138 
2139         return ikeAuthReqMessage;
2140     }
2141 
buildAttributeMap( List<IkeConfigPayload.ConfigAttribute> recognizedAttributeList)2142     private Map<Integer, Integer> buildAttributeMap(
2143             List<IkeConfigPayload.ConfigAttribute> recognizedAttributeList) {
2144         Map<Integer, Integer> attrCountMap = new HashMap<>();
2145         for (IkeConfigPayload.ConfigAttribute attr : recognizedAttributeList) {
2146             attrCountMap.compute(attr.attributeType, (key, val) -> (val == null) ? 1 : val + 1);
2147         }
2148 
2149         return attrCountMap;
2150     }
2151 
verifyDigitalSignatureAuthentication( IkeAuthDigitalSignPayload spyAuthPayload, X509Certificate certificate, IkeIdPayload respIdPayload, List<IkePayload> authRelatedPayloads, boolean hasChildPayloads, boolean hasConfigPayloadInResp)2152     private void verifyDigitalSignatureAuthentication(
2153             IkeAuthDigitalSignPayload spyAuthPayload,
2154             X509Certificate certificate,
2155             IkeIdPayload respIdPayload,
2156             List<IkePayload> authRelatedPayloads,
2157             boolean hasChildPayloads,
2158             boolean hasConfigPayloadInResp)
2159             throws Exception {
2160         IkeMessage ikeAuthReqMessage =
2161                 verifyAuthenticationCommonAndGetIkeMessage(
2162                         respIdPayload,
2163                         authRelatedPayloads,
2164                         hasChildPayloads,
2165                         hasConfigPayloadInResp);
2166 
2167         verify(spyAuthPayload)
2168                 .verifyInboundSignature(
2169                         certificate,
2170                         mIkeSessionStateMachine.mIkeInitRequestBytes,
2171                         mSpyCurrentIkeSaRecord.nonceInitiator,
2172                         respIdPayload.getEncodedPayloadBody(),
2173                         mIkeSessionStateMachine.mIkePrf,
2174                         mSpyCurrentIkeSaRecord.getSkPr());
2175 
2176         assertNotNull(
2177                 ikeAuthReqMessage.getPayloadForType(
2178                         IkePayload.PAYLOAD_TYPE_AUTH, IkeAuthDigitalSignPayload.class));
2179     }
2180 
verifySharedKeyAuthentication( IkeAuthPskPayload spyAuthPayload, IkeIdPayload respIdPayload, List<IkePayload> authRelatedPayloads, boolean hasChildPayloads, boolean hasConfigPayloadInResp)2181     private void verifySharedKeyAuthentication(
2182             IkeAuthPskPayload spyAuthPayload,
2183             IkeIdPayload respIdPayload,
2184             List<IkePayload> authRelatedPayloads,
2185             boolean hasChildPayloads,
2186             boolean hasConfigPayloadInResp)
2187             throws Exception {
2188         IkeMessage ikeAuthReqMessage =
2189                 verifyAuthenticationCommonAndGetIkeMessage(
2190                         respIdPayload,
2191                         authRelatedPayloads,
2192                         hasChildPayloads,
2193                         hasConfigPayloadInResp);
2194 
2195         // Validate authentication is done. Cannot use matchers because IkeAuthPskPayload is final.
2196         verify(spyAuthPayload)
2197                 .verifyInboundSignature(
2198                         mPsk,
2199                         mIkeSessionStateMachine.mIkeInitRequestBytes,
2200                         mSpyCurrentIkeSaRecord.nonceInitiator,
2201                         respIdPayload.getEncodedPayloadBody(),
2202                         mIkeSessionStateMachine.mIkePrf,
2203                         mSpyCurrentIkeSaRecord.getSkPr());
2204 
2205         assertNotNull(
2206                 ikeAuthReqMessage.getPayloadForType(
2207                         IkePayload.PAYLOAD_TYPE_AUTH, IkeAuthPskPayload.class));
2208     }
2209 
verifyAuthenticationCommonAndGetIkeMessage( IkeIdPayload respIdPayload, List<IkePayload> authRelatedPayloads, boolean hasChildPayloads, boolean hasConfigPayloadInResp)2210     private IkeMessage verifyAuthenticationCommonAndGetIkeMessage(
2211             IkeIdPayload respIdPayload,
2212             List<IkePayload> authRelatedPayloads,
2213             boolean hasChildPayloads,
2214             boolean hasConfigPayloadInResp)
2215             throws Exception {
2216         // Send IKE AUTH response to IKE state machine
2217         ReceivedIkePacket authResp = makeIkeAuthRespWithChildPayloads(authRelatedPayloads);
2218         mIkeSessionStateMachine.sendMessage(
2219                 IkeSessionStateMachine.CMD_RECEIVE_IKE_PACKET, authResp);
2220         mLooper.dispatchAll();
2221 
2222         // Validate outbound IKE AUTH request
2223         IkeMessage ikeAuthReqMessage;
2224         if (hasChildPayloads) {
2225             ikeAuthReqMessage = verifyAuthReqWithChildPayloadsAndGetMsg();
2226         } else {
2227             ikeAuthReqMessage = verifyAuthReqAndGetMsg();
2228         }
2229 
2230         // Validate that there is no EAP only notify payload
2231         List<IkeNotifyPayload> notifyPayloads =
2232                 ikeAuthReqMessage.getPayloadListForType(
2233                         IkePayload.PAYLOAD_TYPE_NOTIFY, IkeNotifyPayload.class);
2234         assertFalse(hasEapOnlyNotifyPayload(notifyPayloads));
2235 
2236         // Validate inbound IKE AUTH response
2237         verifyIncrementLocaReqMsgId();
2238         verifyDecodeEncryptedMessage(mSpyCurrentIkeSaRecord, authResp);
2239 
2240         // Validate that user has been notified
2241         verify(mSpyUserCbExecutor).execute(any(Runnable.class));
2242 
2243         // Verify IkeSessionConfiguration
2244         ArgumentCaptor<IkeSessionConfiguration> ikeSessionConfigurationArgumentCaptor =
2245                 ArgumentCaptor.forClass(IkeSessionConfiguration.class);
2246         verify(mMockIkeSessionCallback).onOpened(ikeSessionConfigurationArgumentCaptor.capture());
2247 
2248         IkeSessionConfiguration sessionConfig = ikeSessionConfigurationArgumentCaptor.getValue();
2249         assertNotNull(sessionConfig);
2250         if (hasConfigPayloadInResp) {
2251             List<InetAddress> pcscfAddressList = sessionConfig.getPcscfServers();
2252             assertEquals(3, pcscfAddressList.size());
2253             assertTrue(pcscfAddressList.contains(InetAddress.getByName(PCSCF_IPV6_ADDRESS1)));
2254             assertTrue(pcscfAddressList.contains(InetAddress.getByName(PCSCF_IPV6_ADDRESS2)));
2255             assertTrue(pcscfAddressList.contains(InetAddress.getByName(PCSCF_IPV6_ADDRESS3)));
2256         } else {
2257             assertTrue(sessionConfig.getPcscfServers().size() == 0);
2258         }
2259 
2260         assertEquals(
2261                 "" /*expected application version*/, sessionConfig.getRemoteApplicationVersion());
2262         assertByteArrayListEquals(
2263                 Arrays.asList(REMOTE_VENDOR_ID_ONE, REMOTE_VENDOR_ID_TWO),
2264                 sessionConfig.getRemoteVendorIds());
2265         assertTrue(
2266                 sessionConfig.isIkeExtensionEnabled(
2267                         IkeSessionConfiguration.EXTENSION_TYPE_FRAGMENTATION));
2268 
2269         IkeSessionConnectionInfo ikeConnInfo = sessionConfig.getIkeSessionConnectionInfo();
2270         assertEquals(LOCAL_ADDRESS, ikeConnInfo.getLocalAddress());
2271         assertEquals(REMOTE_ADDRESS, ikeConnInfo.getRemoteAddress());
2272         assertEquals(mMockDefaultNetwork, ikeConnInfo.getNetwork());
2273 
2274         // Verify payload list pair for first Child negotiation
2275         ArgumentCaptor<List<IkePayload>> mReqPayloadListCaptor =
2276                 ArgumentCaptor.forClass(List.class);
2277         ArgumentCaptor<List<IkePayload>> mRespPayloadListCaptor =
2278                 ArgumentCaptor.forClass(List.class);
2279         verify(mMockChildSessionStateMachine)
2280                 .handleFirstChildExchange(
2281                         mReqPayloadListCaptor.capture(),
2282                         mRespPayloadListCaptor.capture(),
2283                         eq(LOCAL_ADDRESS),
2284                         eq(REMOTE_ADDRESS),
2285                         any(), // udpEncapSocket
2286                         eq(mIkeSessionStateMachine.mIkePrf),
2287                         any()); // sk_d
2288         List<IkePayload> childReqList = mReqPayloadListCaptor.getValue();
2289         List<IkePayload> childRespList = mRespPayloadListCaptor.getValue();
2290 
2291         assertTrue(isIkePayloadExist(childReqList, IkePayload.PAYLOAD_TYPE_SA));
2292         assertTrue(isIkePayloadExist(childReqList, IkePayload.PAYLOAD_TYPE_TS_INITIATOR));
2293         assertTrue(isIkePayloadExist(childReqList, IkePayload.PAYLOAD_TYPE_TS_RESPONDER));
2294         assertTrue(isIkePayloadExist(childReqList, IkePayload.PAYLOAD_TYPE_NONCE));
2295         IkeSaPayload reqSaPayload =
2296                 IkePayload.getPayloadForTypeInProvidedList(
2297                         IkePayload.PAYLOAD_TYPE_SA, IkeSaPayload.class, childReqList);
2298         assertFalse(reqSaPayload.isSaResponse);
2299 
2300         assertTrue(isIkePayloadExist(childRespList, IkePayload.PAYLOAD_TYPE_SA));
2301         assertTrue(isIkePayloadExist(childRespList, IkePayload.PAYLOAD_TYPE_TS_INITIATOR));
2302         assertTrue(isIkePayloadExist(childRespList, IkePayload.PAYLOAD_TYPE_TS_RESPONDER));
2303         assertTrue(isIkePayloadExist(childRespList, IkePayload.PAYLOAD_TYPE_NONCE));
2304         if (hasConfigPayloadInResp) {
2305             assertTrue(isIkePayloadExist(childRespList, IkePayload.PAYLOAD_TYPE_CP));
2306         } else {
2307             assertFalse(isIkePayloadExist(childRespList, IkePayload.PAYLOAD_TYPE_CP));
2308         }
2309         IkeSaPayload respSaPayload =
2310                 IkePayload.getPayloadForTypeInProvidedList(
2311                         IkePayload.PAYLOAD_TYPE_SA, IkeSaPayload.class, childRespList);
2312         assertTrue(respSaPayload.isSaResponse);
2313 
2314         // Mock finishing first Child SA negotiation.
2315         assertTrue(
2316                 mIkeSessionStateMachine.getCurrentState()
2317                         instanceof IkeSessionStateMachine.ChildProcedureOngoing);
2318 
2319         verify(mMockChildSessionFactoryHelper)
2320                 .makeChildSessionStateMachine(
2321                         eq(mLooper.getLooper()),
2322                         eq(mSpyContext),
2323                         anyInt(),
2324                         any(AlarmManager.class),
2325                         any(RandomnessFactory.class),
2326                         any(IpSecSpiGenerator.class),
2327                         eq(mChildSessionParams),
2328                         eq(mSpyUserCbExecutor),
2329                         eq(mMockChildSessionCallback),
2330                         mChildSessionSmCbCaptor.capture());
2331         IChildSessionSmCallback cb = mChildSessionSmCbCaptor.getValue();
2332 
2333         cb.onProcedureFinished(mMockChildSessionStateMachine);
2334         mLooper.dispatchAll();
2335         assertTrue(
2336                 mIkeSessionStateMachine.getCurrentState() instanceof IkeSessionStateMachine.Idle);
2337 
2338         return ikeAuthReqMessage;
2339     }
2340 
makeSpyRespPskPayload()2341     private IkeAuthPskPayload makeSpyRespPskPayload() throws Exception {
2342         IkeAuthPskPayload spyAuthPayload =
2343                 spy(
2344                         (IkeAuthPskPayload)
2345                                 IkeTestUtils.hexStringToIkePayload(
2346                                         IkePayload.PAYLOAD_TYPE_AUTH,
2347                                         true /*isResp*/,
2348                                         PSK_AUTH_RESP_PAYLOAD_HEX_STRING));
2349 
2350         doNothing()
2351                 .when(spyAuthPayload)
2352                 .verifyInboundSignature(any(), any(), any(), any(), any(), any());
2353         return spyAuthPayload;
2354     }
2355 
makeSpyDigitalSignAuthPayload()2356     private IkeAuthDigitalSignPayload makeSpyDigitalSignAuthPayload() throws Exception {
2357         IkeAuthDigitalSignPayload spyAuthPayload =
2358                 spy(
2359                         (IkeAuthDigitalSignPayload)
2360                                 IkeTestUtils.hexStringToIkePayload(
2361                                         IkePayload.PAYLOAD_TYPE_AUTH,
2362                                         true /*isResp*/,
2363                                         GENERIC_DIGITAL_SIGN_AUTH_RESP_HEX_STRING));
2364         doNothing()
2365                 .when(spyAuthPayload)
2366                 .verifyInboundSignature(any(), any(), any(), any(), any(), any());
2367         return spyAuthPayload;
2368     }
2369 
makeRespIdPayload()2370     private IkeIdPayload makeRespIdPayload() {
2371         return makeRespIdPayload(REMOTE_ID_FQDN);
2372     }
2373 
makeRespIdPayload(IkeIdentification ikeId)2374     private IkeIdPayload makeRespIdPayload(IkeIdentification ikeId) {
2375         return new IkeIdPayload(false /* isInitiator */, ikeId);
2376     }
2377 
verifyEmptyInformationalSent(int count, boolean expectedResp)2378     private void verifyEmptyInformationalSent(int count, boolean expectedResp) {
2379         verify(mMockIkeMessageHelper, times(count))
2380                 .encryptAndEncode(
2381                         anyObject(),
2382                         anyObject(),
2383                         eq(mSpyCurrentIkeSaRecord),
2384                         argThat(
2385                                 msg -> {
2386                                     return msg.ikePayloadList.isEmpty()
2387                                             && msg.ikeHeader.isResponseMsg == expectedResp
2388                                             && msg.ikeHeader.fromIkeInitiator
2389                                             && msg.ikeHeader.exchangeType
2390                                                     == IkeHeader.EXCHANGE_TYPE_INFORMATIONAL;
2391                                 }),
2392                         anyBoolean(),
2393                         anyInt());
2394     }
2395 
2396     @Test
testCreateIkeLocalIkeAuthDefersOtherMessages()2397     public void testCreateIkeLocalIkeAuthDefersOtherMessages() throws Exception {
2398         mockIkeInitAndTransitionToIkeAuth(mIkeSessionStateMachine.mCreateIkeLocalIkeAuth);
2399         verifyRetransmissionStarted();
2400 
2401         // Build IKE AUTH response with Auth-PSK, ID-Responder and config payloads.
2402         List<IkePayload> authRelatedPayloads = new LinkedList<>();
2403         IkeAuthPskPayload spyAuthPayload = makeSpyRespPskPayload();
2404         authRelatedPayloads.add(spyAuthPayload);
2405 
2406         ReceivedIkePacket req =
2407                 makeDummyEncryptedReceivedIkePacket(
2408                         mSpyCurrentIkeSaRecord,
2409                         IkeHeader.EXCHANGE_TYPE_INFORMATIONAL,
2410                         false,
2411                         Collections.emptyList(),
2412                         Collections.emptyList());
2413         mIkeSessionStateMachine.sendMessage(IkeSessionStateMachine.CMD_RECEIVE_IKE_PACKET, req);
2414 
2415         verifyEmptyInformationalSent(0, true /* expcetedResp*/);
2416 
2417         // Send IKE AUTH response to IKE state machine to trigger moving to next state
2418         IkeIdPayload respIdPayload = makeRespIdPayload();
2419         authRelatedPayloads.add(respIdPayload);
2420         authRelatedPayloads.add(makeConfigPayload());
2421 
2422         ReceivedIkePacket authResp = makeIkeAuthRespWithChildPayloads(authRelatedPayloads);
2423         mIkeSessionStateMachine.sendMessage(
2424                 IkeSessionStateMachine.CMD_RECEIVE_IKE_PACKET, authResp);
2425         mLooper.dispatchAll();
2426 
2427         verifyEmptyInformationalSent(1, true /* expcetedResp*/);
2428         assertTrue(
2429                 mIkeSessionStateMachine.getCurrentState()
2430                         instanceof IkeSessionStateMachine.ChildProcedureOngoing);
2431     }
2432 
2433     @Test
testCreateIkeLocalIkeAuthDigitalSignature()2434     public void testCreateIkeLocalIkeAuthDigitalSignature() throws Exception {
2435         // Quit and restart IKE Session with Digital Signature Auth params
2436         mIkeSessionStateMachine.quitNow();
2437         reset(mMockChildSessionFactoryHelper);
2438         setupChildStateMachineFactory(mMockChildSessionStateMachine);
2439         mIkeSessionStateMachine = makeAndStartIkeSession(buildIkeSessionParamsDigitalSignature());
2440         mockIkeInitAndTransitionToIkeAuth(mIkeSessionStateMachine.mCreateIkeLocalIkeAuth);
2441 
2442         // Build IKE AUTH response with Digital Signature Auth, ID-Responder and config payloads.
2443         List<IkePayload> authRelatedPayloads = new LinkedList<>();
2444         IkeAuthDigitalSignPayload spyAuthPayload = makeSpyDigitalSignAuthPayload();
2445         authRelatedPayloads.add(spyAuthPayload);
2446         authRelatedPayloads.add(new IkeCertX509CertPayload(mServerEndCertificate));
2447 
2448         IkeIdPayload respIdPayload = makeRespIdPayload();
2449         authRelatedPayloads.add(respIdPayload);
2450         authRelatedPayloads.add(makeConfigPayload());
2451 
2452         verifyDigitalSignatureAuthentication(
2453                 spyAuthPayload,
2454                 mServerEndCertificate,
2455                 respIdPayload,
2456                 authRelatedPayloads,
2457                 true /*hasChildPayloads*/,
2458                 true /*hasConfigPayloadInResp*/);
2459         verifyRetransmissionStopped();
2460     }
2461 
2462     @Test
testCreateIkeLocalIkeAuthPsk()2463     public void testCreateIkeLocalIkeAuthPsk() throws Exception {
2464         mockIkeInitAndTransitionToIkeAuth(mIkeSessionStateMachine.mCreateIkeLocalIkeAuth);
2465         verifyRetransmissionStarted();
2466 
2467         // Build IKE AUTH response with Auth-PSK, ID-Responder and config payloads.
2468         List<IkePayload> authRelatedPayloads = new LinkedList<>();
2469         IkeAuthPskPayload spyAuthPayload = makeSpyRespPskPayload();
2470         authRelatedPayloads.add(spyAuthPayload);
2471 
2472         IkeIdPayload respIdPayload = makeRespIdPayload();
2473         authRelatedPayloads.add(respIdPayload);
2474         authRelatedPayloads.add(makeConfigPayload());
2475 
2476         verifySharedKeyAuthentication(
2477                 spyAuthPayload,
2478                 respIdPayload,
2479                 authRelatedPayloads,
2480                 true /*hasChildPayloads*/,
2481                 true /*hasConfigPayloadInResp*/);
2482         verifyRetransmissionStopped();
2483     }
2484 
2485     @Test
testCreateIkeLocalIkeAuthDigitalSignatureIdMismatch()2486     public void testCreateIkeLocalIkeAuthDigitalSignatureIdMismatch() throws Exception {
2487         // Quit and restart IKE Session with Digital Signature Auth params
2488         mIkeSessionStateMachine.quitNow();
2489         mIkeSessionStateMachine = makeAndStartIkeSession(buildIkeSessionParamsDigitalSignature());
2490         mockIkeInitAndTransitionToIkeAuth(mIkeSessionStateMachine.mCreateIkeLocalIkeAuth);
2491         resetMockIkeMessageHelper();
2492 
2493         // Build IKE AUTH response with Digital Signature Auth, ID-Responder and config payloads.
2494         List<IkePayload> authRelatedPayloads = new LinkedList<>();
2495         IkeAuthDigitalSignPayload spyAuthPayload = makeSpyDigitalSignAuthPayload();
2496         authRelatedPayloads.add(spyAuthPayload);
2497         authRelatedPayloads.add(new IkeCertX509CertPayload(mServerEndCertificate));
2498 
2499         authRelatedPayloads.add(makeRespIdPayload(REMOTE_ID_IPV4));
2500 
2501         sendAuthFailRespAndVerifyCloseIke(makeIkeAuthRespWithChildPayloads(authRelatedPayloads));
2502     }
2503 
2504     @Test
testCreateIkeLocalIkeAuthPskVerifyFail()2505     public void testCreateIkeLocalIkeAuthPskVerifyFail() throws Exception {
2506         mockIkeInitAndTransitionToIkeAuth(mIkeSessionStateMachine.mCreateIkeLocalIkeAuth);
2507         verifyRetransmissionStarted();
2508         resetMockIkeMessageHelper();
2509 
2510         // Build IKE AUTH response with invalid Auth-PSK Payload and ID-Responder Payload.
2511         List<IkePayload> authRelatedPayloads = new LinkedList<>();
2512         IkeAuthPskPayload spyAuthPayload = makeSpyRespPskPayload();
2513         doThrow(new AuthenticationFailedException("DummyAuthFailException"))
2514                 .when(spyAuthPayload)
2515                 .verifyInboundSignature(any(), any(), any(), any(), any(), any());
2516         authRelatedPayloads.add(spyAuthPayload);
2517 
2518         IkeIdPayload respIdPayload = makeRespIdPayload();
2519         authRelatedPayloads.add(respIdPayload);
2520 
2521         sendAuthFailRespAndVerifyCloseIke(makeIkeAuthRespWithChildPayloads(authRelatedPayloads));
2522     }
2523 
sendAuthFailRespAndVerifyCloseIke(ReceivedIkePacket authFailResp)2524     private void sendAuthFailRespAndVerifyCloseIke(ReceivedIkePacket authFailResp)
2525             throws Exception {
2526         // Send response to IKE state machine
2527         mIkeSessionStateMachine.sendMessage(
2528                 IkeSessionStateMachine.CMD_RECEIVE_IKE_PACKET, authFailResp);
2529         mLooper.dispatchAll();
2530 
2531         // Verify Delete request was sent
2532         List<IkePayload> payloads = verifyOutInfoMsgHeaderAndGetPayloads(false /*isResp*/);
2533         assertEquals(1, payloads.size());
2534         assertEquals(IkePayload.PAYLOAD_TYPE_DELETE, payloads.get(0).payloadType);
2535 
2536         // Verify IKE Session was closed properly
2537         assertNull(mIkeSessionStateMachine.getCurrentState());
2538         verify(mMockIkeSessionCallback)
2539                 .onClosedExceptionally(any(AuthenticationFailedException.class));
2540     }
2541 
2542     @Test
testAuthHandlesIkeErrorNotify()2543     public void testAuthHandlesIkeErrorNotify() throws Exception {
2544         mockIkeInitAndTransitionToIkeAuth(mIkeSessionStateMachine.mCreateIkeLocalIkeAuth);
2545         verifyRetransmissionStarted();
2546         resetMockIkeMessageHelper();
2547 
2548         // Mock rejecting IKE AUTH with Authenticatio Failure notification
2549         ReceivedIkePacket mockAuthFailPacket =
2550                 makeIkeAuthRespWithoutChildPayloads(
2551                         Arrays.asList(new IkeNotifyPayload(ERROR_TYPE_AUTHENTICATION_FAILED)));
2552         mIkeSessionStateMachine.sendMessage(CMD_RECEIVE_IKE_PACKET, mockAuthFailPacket);
2553         mLooper.dispatchAll();
2554 
2555         // Verify IKE Session is closed properly
2556         assertNull(mIkeSessionStateMachine.getCurrentState());
2557         verify(mMockIkeSessionCallback)
2558                 .onClosedExceptionally(any(AuthenticationFailedException.class));
2559     }
2560 
2561     @Test
testAuthHandlesCreateChildErrorNotify()2562     public void testAuthHandlesCreateChildErrorNotify() throws Exception {
2563         mockIkeInitAndTransitionToIkeAuth(mIkeSessionStateMachine.mCreateIkeLocalIkeAuth);
2564         verifyRetransmissionStarted();
2565         resetMockIkeMessageHelper();
2566 
2567         // Mock rejecting IKE AUTH with a Create Child error notification
2568         ReceivedIkePacket mockAuthFailPacket =
2569                 makeIkeAuthRespWithoutChildPayloads(
2570                         Arrays.asList(new IkeNotifyPayload(ERROR_TYPE_INTERNAL_ADDRESS_FAILURE)));
2571         mIkeSessionStateMachine.sendMessage(CMD_RECEIVE_IKE_PACKET, mockAuthFailPacket);
2572         mLooper.dispatchAll();
2573 
2574         // Verify IKE Session is closed properly
2575         assertNull(mIkeSessionStateMachine.getCurrentState());
2576 
2577         ArgumentCaptor<IkeProtocolException> captor =
2578                 ArgumentCaptor.forClass(IkeProtocolException.class);
2579         verify(mMockIkeSessionCallback).onClosedExceptionally(captor.capture());
2580         IkeProtocolException exception = captor.getValue();
2581         assertEquals(ERROR_TYPE_INTERNAL_ADDRESS_FAILURE, exception.getErrorType());
2582     }
2583 
2584     @Test
testAuthPskHandleRespWithParsingError()2585     public void testAuthPskHandleRespWithParsingError() throws Exception {
2586         mockIkeInitAndTransitionToIkeAuth(mIkeSessionStateMachine.mCreateIkeLocalIkeAuth);
2587         verifyRetransmissionStarted();
2588         resetMockIkeMessageHelper();
2589 
2590         // Mock receiving packet with syntax error
2591         ReceivedIkePacket mockInvalidPacket =
2592                 makeDummyReceivedIkePacketWithInvalidSyntax(
2593                         mSpyCurrentIkeSaRecord, true /*isResp*/, IkeHeader.EXCHANGE_TYPE_IKE_AUTH);
2594         mIkeSessionStateMachine.sendMessage(CMD_RECEIVE_IKE_PACKET, mockInvalidPacket);
2595         mLooper.dispatchAll();
2596 
2597         // Verify Delete request was sent
2598         List<IkePayload> payloads = verifyOutInfoMsgHeaderAndGetPayloads(false /*isResp*/);
2599         assertEquals(1, payloads.size());
2600         assertEquals(IkePayload.PAYLOAD_TYPE_DELETE, payloads.get(0).payloadType);
2601 
2602         // Verify IKE Session is closed properly
2603         assertNull(mIkeSessionStateMachine.getCurrentState());
2604         verify(mMockIkeSessionCallback).onClosedExceptionally(any(InvalidSyntaxException.class));
2605     }
2606 
2607     @Test
testAuthWithOptionAcceptAnyRemoteId()2608     public void testAuthWithOptionAcceptAnyRemoteId() throws Exception {
2609         mIkeSessionStateMachine.quitNow();
2610         reset(mMockChildSessionFactoryHelper);
2611         setupChildStateMachineFactory(mMockChildSessionStateMachine);
2612 
2613         IkeSessionParams ikeSessionParams =
2614                 buildIkeSessionParamsCommon()
2615                         .setAuthPsk(mPsk)
2616                         .addIkeOption(IkeSessionParams.IKE_OPTION_ACCEPT_ANY_REMOTE_ID)
2617                         .build();
2618         mIkeSessionStateMachine = makeAndStartIkeSession(ikeSessionParams);
2619 
2620         // Mock IKE INIT
2621         mockIkeInitAndTransitionToIkeAuth(mIkeSessionStateMachine.mCreateIkeLocalIkeAuth);
2622         verifyRetransmissionStarted();
2623 
2624         // Build IKE AUTH response with Auth-PSK Payload and ID-Responder Payload that is different
2625         // from configured ID-Responder.
2626         List<IkePayload> authRelatedPayloads = new LinkedList<>();
2627         IkeAuthPskPayload spyAuthPayload = makeSpyRespPskPayload();
2628         authRelatedPayloads.add(spyAuthPayload);
2629 
2630         IkeIdPayload respIdPayload = makeRespIdPayload(REMOTE_ID_IPV4);
2631         authRelatedPayloads.add(respIdPayload);
2632 
2633         // Send response to IKE state machine and verify authentication is done.
2634         verifySharedKeyAuthentication(
2635                 spyAuthPayload,
2636                 respIdPayload,
2637                 authRelatedPayloads,
2638                 true /*hasChildPayloads*/,
2639                 false /*hasConfigPayloadInResp*/);
2640         verifyRetransmissionStopped();
2641     }
2642 
2643     @Test
testAuthRejectOtherResponderId()2644     public void testAuthRejectOtherResponderId() throws Exception {
2645         mockIkeInitAndTransitionToIkeAuth(mIkeSessionStateMachine.mCreateIkeLocalIkeAuth);
2646         verifyRetransmissionStarted();
2647 
2648         // Build IKE AUTH response with Auth-PSK Payload and ID-Responder Payload that is different
2649         // from configured ID-Responder.
2650         List<IkePayload> authRelatedPayloads = new LinkedList<>();
2651         IkeAuthPskPayload spyAuthPayload = makeSpyRespPskPayload();
2652         authRelatedPayloads.add(spyAuthPayload);
2653 
2654         IkeIdPayload respIdPayload = makeRespIdPayload(REMOTE_ID_IPV4);
2655         authRelatedPayloads.add(respIdPayload);
2656 
2657         // Send response to IKE state machine
2658         mIkeSessionStateMachine.sendMessage(
2659                 IkeSessionStateMachine.CMD_RECEIVE_IKE_PACKET,
2660                 makeIkeAuthRespWithChildPayloads(authRelatedPayloads));
2661         mLooper.dispatchAll();
2662 
2663         // Verify IKE Session is closed properly
2664         assertNull(mIkeSessionStateMachine.getCurrentState());
2665         verify(mMockIkeSessionCallback)
2666                 .onClosedExceptionally(any(AuthenticationFailedException.class));
2667     }
2668 
2669     @Test
testCreateIkeLocalIkeAuthPreEap()2670     public void testCreateIkeLocalIkeAuthPreEap() throws Exception {
2671         mIkeSessionStateMachine.quitNow();
2672         mIkeSessionStateMachine = makeAndStartIkeSession(buildIkeSessionParamsEap());
2673 
2674         // Mock IKE INIT
2675         mockIkeInitAndTransitionToIkeAuth(mIkeSessionStateMachine.mCreateIkeLocalIkeAuth);
2676         verifyRetransmissionStarted();
2677 
2678         // Build IKE AUTH response with EAP. Auth, ID-Resp and Cert payloads.
2679         List<IkePayload> authRelatedPayloads = new LinkedList<>();
2680 
2681         authRelatedPayloads.add(new IkeEapPayload(EAP_DUMMY_MSG));
2682         authRelatedPayloads.add(makeSpyDigitalSignAuthPayload());
2683         authRelatedPayloads.add(makeRespIdPayload());
2684 
2685         IkeCertX509CertPayload certPayload = new IkeCertX509CertPayload(mServerEndCertificate);
2686         authRelatedPayloads.add(certPayload);
2687 
2688         // Send IKE AUTH response to IKE state machine
2689         mIkeSessionStateMachine.sendMessage(
2690                 IkeSessionStateMachine.CMD_RECEIVE_IKE_PACKET,
2691                 makeIkeAuthRespWithoutChildPayloads(authRelatedPayloads));
2692         mLooper.dispatchAll();
2693 
2694         // Validate outbound IKE AUTH request
2695         IkeMessage ikeAuthReqMessage = verifyAuthReqWithChildPayloadsAndGetMsg();
2696         assertNull(
2697                 ikeAuthReqMessage.getPayloadForType(
2698                         IkePayload.PAYLOAD_TYPE_AUTH, IkeAuthPayload.class));
2699 
2700         assertTrue(
2701                 mIkeSessionStateMachine.getCurrentState()
2702                         instanceof IkeSessionStateMachine.CreateIkeLocalIkeAuthInEap);
2703         verifyRetransmissionStopped();
2704         assertNotNull(mIkeSessionStateMachine.mInitIdPayload);
2705         assertNotNull(mIkeSessionStateMachine.mRespIdPayload);
2706     }
2707 
verifyEapAuthenticatorCreatedAndGetCallback()2708     private IEapCallback verifyEapAuthenticatorCreatedAndGetCallback() {
2709         ArgumentCaptor<IEapCallback> captor = ArgumentCaptor.forClass(IEapCallback.class);
2710 
2711         verify(mMockEapAuthenticatorFactory)
2712                 .newEapAuthenticator(
2713                         eq(mIkeSessionStateMachine.getHandler().getLooper()),
2714                         captor.capture(),
2715                         eq(mSpyContext),
2716                         eq(mEapSessionConfig),
2717                         any(RandomnessFactory.class));
2718 
2719         return captor.getValue();
2720     }
2721 
2722     @Test
testCreateIkeLocalIkeAuthInEapStartsAuthenticatorAndProxiesMessage()2723     public void testCreateIkeLocalIkeAuthInEapStartsAuthenticatorAndProxiesMessage()
2724             throws Exception {
2725         mIkeSessionStateMachine.quitNow();
2726         mIkeSessionStateMachine = makeAndStartIkeSession(buildIkeSessionParamsEap());
2727 
2728         // Setup state and go to IN_EAP state
2729         mockIkeInitAndTransitionToIkeAuth(mIkeSessionStateMachine.mCreateIkeLocalIkeAuthInEap);
2730         mLooper.dispatchAll();
2731 
2732         mIkeSessionStateMachine.sendMessage(
2733                 IkeSessionStateMachine.CMD_EAP_START_EAP_AUTH, new IkeEapPayload(EAP_DUMMY_MSG));
2734         mLooper.dispatchAll();
2735 
2736         verifyEapAuthenticatorCreatedAndGetCallback();
2737 
2738         verify(mMockEapAuthenticator).processEapMessage(eq(EAP_DUMMY_MSG));
2739     }
2740 
2741     @Test
testCreateIkeLocalIkeAuthInEapHandlesOutboundResponse()2742     public void testCreateIkeLocalIkeAuthInEapHandlesOutboundResponse() throws Exception {
2743         mIkeSessionStateMachine.quitNow();
2744         mIkeSessionStateMachine = makeAndStartIkeSession(buildIkeSessionParamsEap());
2745 
2746         // Setup state and go to IN_EAP state
2747         mockIkeInitAndTransitionToIkeAuth(mIkeSessionStateMachine.mCreateIkeLocalIkeAuthInEap);
2748         mLooper.dispatchAll();
2749 
2750         IEapCallback callback = verifyEapAuthenticatorCreatedAndGetCallback();
2751         callback.onResponse(EAP_DUMMY_MSG);
2752         mLooper.dispatchAll();
2753         verifyRetransmissionStarted();
2754 
2755         // Verify EAP response
2756         IkeMessage resp = verifyEncryptAndEncodeAndGetMessage(mSpyCurrentIkeSaRecord);
2757         IkeHeader ikeHeader = resp.ikeHeader;
2758         assertEquals(IkePayload.PAYLOAD_TYPE_SK, ikeHeader.nextPayloadType);
2759         assertEquals(IkeHeader.EXCHANGE_TYPE_IKE_AUTH, ikeHeader.exchangeType);
2760         assertFalse(ikeHeader.isResponseMsg);
2761         assertEquals(mSpyCurrentIkeSaRecord.isLocalInit, ikeHeader.fromIkeInitiator);
2762 
2763         assertEquals(1, resp.ikePayloadList.size());
2764         assertArrayEquals(EAP_DUMMY_MSG, ((IkeEapPayload) resp.ikePayloadList.get(0)).eapMessage);
2765     }
2766 
2767     @Test
testCreateIkeLocalIkeAuthInEapHandlesMissingEapPacket()2768     public void testCreateIkeLocalIkeAuthInEapHandlesMissingEapPacket() throws Exception {
2769         mIkeSessionStateMachine.quitNow();
2770         mIkeSessionStateMachine = makeAndStartIkeSession(buildIkeSessionParamsEap());
2771 
2772         // Setup state and go to IN_EAP state
2773         mockIkeInitAndTransitionToIkeAuth(mIkeSessionStateMachine.mCreateIkeLocalIkeAuthInEap);
2774         mLooper.dispatchAll();
2775 
2776         // Mock sending IKE_AUTH{EAP} request
2777         IEapCallback callback = verifyEapAuthenticatorCreatedAndGetCallback();
2778         callback.onResponse(EAP_DUMMY_MSG);
2779         mLooper.dispatchAll();
2780         verifyRetransmissionStarted();
2781 
2782         // Send IKE AUTH response with no EAP Payload to IKE state machine
2783         mIkeSessionStateMachine.sendMessage(
2784                 IkeSessionStateMachine.CMD_RECEIVE_IKE_PACKET,
2785                 makeIkeAuthRespWithoutChildPayloads(new LinkedList<>()));
2786         mLooper.dispatchAll();
2787 
2788         // Verify state machine quit properly
2789         verify(mMockIkeSessionCallback)
2790                 .onClosedExceptionally(any(AuthenticationFailedException.class));
2791         assertNull(mIkeSessionStateMachine.getCurrentState());
2792     }
2793 
2794     @Test
testCreateIkeLocalIkeAuthInEapHandlesSuccess()2795     public void testCreateIkeLocalIkeAuthInEapHandlesSuccess() throws Exception {
2796         mIkeSessionStateMachine.quitNow();
2797         mIkeSessionStateMachine = makeAndStartIkeSession(buildIkeSessionParamsEap());
2798 
2799         // Setup state and go to IN_EAP state
2800         mockIkeInitAndTransitionToIkeAuth(mIkeSessionStateMachine.mCreateIkeLocalIkeAuthInEap);
2801         mLooper.dispatchAll();
2802 
2803         IEapCallback callback = verifyEapAuthenticatorCreatedAndGetCallback();
2804 
2805         // Setup dummy initIdPayload for next state.
2806         mIkeSessionStateMachine.mInitIdPayload = mock(IkeIdPayload.class);
2807         doReturn(new byte[0]).when(mIkeSessionStateMachine.mInitIdPayload).getEncodedPayloadBody();
2808 
2809         callback.onSuccess(mPsk, new byte[0]); // use mPsk as MSK, eMSK does not matter
2810         mLooper.dispatchAll();
2811 
2812         assertTrue(
2813                 mIkeSessionStateMachine.getCurrentState()
2814                         instanceof IkeSessionStateMachine.CreateIkeLocalIkeAuthPostEap);
2815     }
2816 
2817     @Test
testCreateIkeLocalIkeAuthInEapHandlesError()2818     public void testCreateIkeLocalIkeAuthInEapHandlesError() throws Exception {
2819         mIkeSessionStateMachine.quitNow();
2820         mIkeSessionStateMachine = makeAndStartIkeSession(buildIkeSessionParamsEap());
2821 
2822         // Setup state and go to IN_EAP state
2823         mockIkeInitAndTransitionToIkeAuth(mIkeSessionStateMachine.mCreateIkeLocalIkeAuthInEap);
2824         mLooper.dispatchAll();
2825 
2826         IEapCallback callback = verifyEapAuthenticatorCreatedAndGetCallback();
2827 
2828         Throwable error = new IllegalArgumentException();
2829         callback.onError(error);
2830         mLooper.dispatchAll();
2831 
2832         // Fires user error callbacks
2833         verify(mMockIkeSessionCallback)
2834                 .onClosedExceptionally(argThat(err -> err.getCause() == error));
2835 
2836         // Verify state machine quit properly
2837         verify(mSpyCurrentIkeSaRecord).close();
2838         assertNull(mIkeSessionStateMachine.getCurrentState());
2839     }
2840 
2841     @Test
testCreateIkeLocalIkeAuthInEapHandlesFailure()2842     public void testCreateIkeLocalIkeAuthInEapHandlesFailure() throws Exception {
2843         mIkeSessionStateMachine.quitNow();
2844         mIkeSessionStateMachine = makeAndStartIkeSession(buildIkeSessionParamsEap());
2845 
2846         // Setup state and go to IN_EAP state
2847         mockIkeInitAndTransitionToIkeAuth(mIkeSessionStateMachine.mCreateIkeLocalIkeAuthInEap);
2848         mLooper.dispatchAll();
2849 
2850         IEapCallback callback = verifyEapAuthenticatorCreatedAndGetCallback();
2851         callback.onFail();
2852         mLooper.dispatchAll();
2853 
2854         // Fires user error callbacks
2855         verify(mMockIkeSessionCallback)
2856                 .onClosedExceptionally(any(AuthenticationFailedException.class));
2857 
2858         // Verify state machine quit properly
2859         verify(mSpyCurrentIkeSaRecord).close();
2860         assertNull(mIkeSessionStateMachine.getCurrentState());
2861     }
2862 
2863     @Test
testCreateIkeLocalIkeAuthPostEap()2864     public void testCreateIkeLocalIkeAuthPostEap() throws Exception {
2865         mIkeSessionStateMachine.quitNow();
2866         reset(mMockChildSessionFactoryHelper);
2867         setupChildStateMachineFactory(mMockChildSessionStateMachine);
2868         mIkeSessionStateMachine = makeAndStartIkeSession(buildIkeSessionParamsEap());
2869 
2870         // Setup dummy state from IkeAuthPreEap for next state.
2871         mIkeSessionStateMachine.mInitIdPayload = mock(IkeIdPayload.class);
2872         doReturn(new byte[0]).when(mIkeSessionStateMachine.mInitIdPayload).getEncodedPayloadBody();
2873         mIkeSessionStateMachine.mRespIdPayload = makeRespIdPayload();
2874 
2875         List<Integer> payloadTypeList = new LinkedList<>();
2876         List<String> payloadHexStringList = new LinkedList<>();
2877 
2878         payloadTypeList.add(IkePayload.PAYLOAD_TYPE_SA);
2879         payloadTypeList.add(IkePayload.PAYLOAD_TYPE_TS_INITIATOR);
2880         payloadTypeList.add(IkePayload.PAYLOAD_TYPE_TS_RESPONDER);
2881 
2882         payloadHexStringList.add(CHILD_SA_PAYLOAD_HEX_STRING);
2883         payloadHexStringList.add(TS_INIT_PAYLOAD_HEX_STRING);
2884         payloadHexStringList.add(TS_RESP_PAYLOAD_HEX_STRING);
2885 
2886         mIkeSessionStateMachine.mFirstChildReqList =
2887                 hexStrListToIkePayloadList(payloadTypeList, payloadHexStringList, false /*isResp*/);
2888 
2889         // Setup state and go to IN_EAP state
2890         mockIkeInitAndTransitionToIkeAuth(mIkeSessionStateMachine.mCreateIkeLocalIkeAuthPostEap);
2891         mIkeSessionStateMachine.sendMessage(IkeSessionStateMachine.CMD_EAP_FINISH_EAP_AUTH, mPsk);
2892         mLooper.dispatchAll();
2893         verifyRetransmissionStarted();
2894 
2895         // Build IKE AUTH response with Auth-PSK Payload and ID-Responder Payload.
2896         List<IkePayload> authRelatedPayloads = new LinkedList<>();
2897         IkeAuthPskPayload spyAuthPayload = makeSpyRespPskPayload();
2898         authRelatedPayloads.add(spyAuthPayload);
2899 
2900         IkeIdPayload respIdPayload = makeRespIdPayload();
2901 
2902         verifySharedKeyAuthentication(
2903                 spyAuthPayload,
2904                 respIdPayload,
2905                 authRelatedPayloads,
2906                 false /*hasChildPayloads*/,
2907                 false /*hasConfigPayloadInResp*/);
2908         verifyRetransmissionStopped();
2909     }
2910 
2911     @Test
testCreateIkeLocalIkeAuthHandlesFirstFrag()2912     public void testCreateIkeLocalIkeAuthHandlesFirstFrag() throws Exception {
2913         mockIkeInitAndTransitionToIkeAuth(mIkeSessionStateMachine.mCreateIkeLocalIkeAuth);
2914         verifyRetransmissionStarted();
2915 
2916         // Received IKE fragment
2917         byte[] unencryptedData = "testCreateIkeLocalIkeAuthHandlesFrag".getBytes();
2918         int fragNum = 1;
2919         int totalFragments = 2;
2920         IkeSkfPayload skfPayload =
2921                 IkeTestUtils.makeDummySkfPayload(unencryptedData, fragNum, totalFragments);
2922 
2923         ReceivedIkePacket packet =
2924                 makeDummyReceivedIkeFragmentPacket(
2925                         mSpyCurrentIkeSaRecord,
2926                         true /*isResp*/,
2927                         IkeHeader.EXCHANGE_TYPE_IKE_AUTH,
2928                         skfPayload,
2929                         PAYLOAD_TYPE_AUTH,
2930                         null /* collectedFrags*/);
2931         mIkeSessionStateMachine.sendMessage(IkeSessionStateMachine.CMD_RECEIVE_IKE_PACKET, packet);
2932         mLooper.dispatchAll();
2933 
2934         // Verify state doesn't change
2935         assertTrue(
2936                 mIkeSessionStateMachine.getCurrentState()
2937                         instanceof IkeSessionStateMachine.CreateIkeLocalIkeAuth);
2938 
2939         // Verify the IkeSaRecord has stored the fragment.
2940         DecodeResultPartial resultPartial =
2941                 mSpyCurrentIkeSaRecord.getCollectedFragments(true /*isResp*/);
2942         assertEquals(PAYLOAD_TYPE_AUTH, resultPartial.firstPayloadType);
2943         assertEquals(totalFragments, resultPartial.collectedFragsList.length);
2944         assertArrayEquals(unencryptedData, resultPartial.collectedFragsList[fragNum - 1]);
2945         assertFalse(resultPartial.isAllFragmentsReceived());
2946 
2947         assertNull(mSpyCurrentIkeSaRecord.getCollectedFragments(false /*isResp*/));
2948     }
2949 
2950     @Test
testCreateIkeLocalIkeAuthHandlesLastFragOk()2951     public void testCreateIkeLocalIkeAuthHandlesLastFragOk() throws Exception {
2952         mockIkeInitAndTransitionToIkeAuth(mIkeSessionStateMachine.mCreateIkeLocalIkeAuth);
2953         verifyRetransmissionStarted();
2954 
2955         // Set previously collected IKE fragments
2956         DecodeResultPartial mockCollectedFrags = mock(DecodeResultPartial.class);
2957         mSpyCurrentIkeSaRecord.updateCollectedFragments(mockCollectedFrags, true /*isResp*/);
2958 
2959         // Build reassembled IKE AUTH response with Auth-PSK Payload and ID-Responder Payload.
2960         List<IkePayload> authRelatedPayloads = new LinkedList<>();
2961         IkeAuthPskPayload spyAuthPayload = makeSpyRespPskPayload();
2962         authRelatedPayloads.add(spyAuthPayload);
2963 
2964         IkeIdPayload respIdPayload = makeRespIdPayload();
2965         authRelatedPayloads.add(respIdPayload);
2966 
2967         List<IkePayload> authPayloadList =
2968                 getIkeAuthPayloadListWithChildPayloads(authRelatedPayloads);
2969 
2970         // Receive last auth response and do IKE_AUTH
2971         ReceivedIkePacket packet =
2972                 makeDummyReceivedLastIkeFragmentPacketOk(
2973                         mSpyCurrentIkeSaRecord,
2974                         true /*isResp*/,
2975                         IkeHeader.EXCHANGE_TYPE_IKE_AUTH,
2976                         mockCollectedFrags,
2977                         authPayloadList,
2978                         "FirstFrag".getBytes());
2979         mIkeSessionStateMachine.sendMessage(IkeSessionStateMachine.CMD_RECEIVE_IKE_PACKET, packet);
2980         mLooper.dispatchAll();
2981 
2982         // Verify IKE AUTH is done
2983         assertTrue(
2984                 mIkeSessionStateMachine.getCurrentState()
2985                         instanceof IkeSessionStateMachine.ChildProcedureOngoing);
2986 
2987         // Verify collected response fragments are cleared.
2988         assertNull(mSpyCurrentIkeSaRecord.getCollectedFragments(true /*isResp*/));
2989         verify(mSpyCurrentIkeSaRecord).resetCollectedFragments(true /*isResp*/);
2990     }
2991 
2992     @Test
testCreateIkeLocalIkeAuthHandlesLastFragError()2993     public void testCreateIkeLocalIkeAuthHandlesLastFragError() throws Exception {
2994         mockIkeInitAndTransitionToIkeAuth(mIkeSessionStateMachine.mCreateIkeLocalIkeAuth);
2995         verifyRetransmissionStarted();
2996         resetMockIkeMessageHelper();
2997 
2998         // Set previously collected IKE fragments
2999         DecodeResultPartial mockCollectedFrags = mock(DecodeResultPartial.class);
3000         mSpyCurrentIkeSaRecord.updateCollectedFragments(mockCollectedFrags, true /*isResp*/);
3001 
3002         // Receive last auth response with syntax error
3003         ReceivedIkePacket packet =
3004                 makeDummyReceivedLastIkeFragmentPacketError(
3005                         mSpyCurrentIkeSaRecord,
3006                         true /*isResp*/,
3007                         IkeHeader.EXCHANGE_TYPE_IKE_AUTH,
3008                         mockCollectedFrags,
3009                         new InvalidSyntaxException("IkeStateMachineTest"));
3010         mIkeSessionStateMachine.sendMessage(IkeSessionStateMachine.CMD_RECEIVE_IKE_PACKET, packet);
3011         mLooper.dispatchAll();
3012 
3013         // Verify Delete request is sent
3014         List<IkePayload> payloads = verifyOutInfoMsgHeaderAndGetPayloads(false /*isResp*/);
3015         assertEquals(1, payloads.size());
3016         assertEquals(IkePayload.PAYLOAD_TYPE_DELETE, payloads.get(0).payloadType);
3017 
3018         // Verify IKE Session is closed properly
3019         assertNull(mIkeSessionStateMachine.getCurrentState());
3020         verify(mMockIkeSessionCallback).onClosedExceptionally(any(InvalidSyntaxException.class));
3021 
3022         // Collected response fragments are cleared
3023         assertNull(mSpyCurrentIkeSaRecord.getCollectedFragments(true /*isResp*/));
3024         verify(mSpyCurrentIkeSaRecord).resetCollectedFragments(true /*isResp*/);
3025     }
3026 
3027     @Test
testRekeyIkeLocalCreateSendsRequest()3028     public void testRekeyIkeLocalCreateSendsRequest() throws Exception {
3029         setupIdleStateMachine();
3030 
3031         // Send Rekey-Create request
3032         mIkeSessionStateMachine.sendMessage(
3033                 IkeSessionStateMachine.CMD_EXECUTE_LOCAL_REQ,
3034                 new IkeLocalRequest(IkeSessionStateMachine.CMD_LOCAL_REQUEST_REKEY_IKE));
3035         mLooper.dispatchAll();
3036         assertTrue(
3037                 mIkeSessionStateMachine.getCurrentState()
3038                         instanceof IkeSessionStateMachine.RekeyIkeLocalCreate);
3039         verifyRetransmissionStarted();
3040 
3041         // Verify outbound message
3042         IkeMessage rekeyMsg = verifyEncryptAndEncodeAndGetMessage(mSpyCurrentIkeSaRecord);
3043 
3044         IkeHeader ikeHeader = rekeyMsg.ikeHeader;
3045         assertEquals(IkePayload.PAYLOAD_TYPE_SK, ikeHeader.nextPayloadType);
3046         assertEquals(IkeHeader.EXCHANGE_TYPE_CREATE_CHILD_SA, ikeHeader.exchangeType);
3047         assertEquals(mSpyCurrentIkeSaRecord.getLocalRequestMessageId(), ikeHeader.messageId);
3048         assertFalse(ikeHeader.isResponseMsg);
3049         assertTrue(ikeHeader.fromIkeInitiator);
3050 
3051         // Verify SA payload & proposals
3052         IkeSaPayload saPayload =
3053                 rekeyMsg.getPayloadForType(IkePayload.PAYLOAD_TYPE_SA, IkeSaPayload.class);
3054         assertFalse(saPayload.isSaResponse);
3055         assertEquals(1, saPayload.proposalList.size());
3056 
3057         IkeSaPayload.IkeProposal proposal =
3058                 (IkeSaPayload.IkeProposal) saPayload.proposalList.get(0);
3059         assertEquals(1, proposal.number); // Must be 1-indexed
3060         assertEquals(IkePayload.PROTOCOL_ID_IKE, proposal.protocolId);
3061         assertEquals(IkePayload.SPI_LEN_IKE, proposal.spiSize);
3062         assertEquals(mIkeSessionStateMachine.mSaProposal, proposal.saProposal);
3063 
3064         // Verify Nonce and KE payloads exist.
3065         assertNotNull(
3066                 rekeyMsg.getPayloadForType(IkePayload.PAYLOAD_TYPE_NONCE, IkeNoncePayload.class));
3067 
3068         IkeKePayload kePayload =
3069                 rekeyMsg.getPayloadForType(IkePayload.PAYLOAD_TYPE_KE, IkeKePayload.class);
3070         assertNotNull(kePayload);
3071         assertTrue(kePayload.isOutbound);
3072     }
3073 
3074     @Test
testRekeyIkeLocalCreateHandlesResponse()3075     public void testRekeyIkeLocalCreateHandlesResponse() throws Exception {
3076         setupIdleStateMachine();
3077 
3078         // Send Rekey-Create request
3079         mIkeSessionStateMachine.sendMessage(
3080                 IkeSessionStateMachine.CMD_EXECUTE_LOCAL_REQ,
3081                 new IkeLocalRequest(IkeSessionStateMachine.CMD_LOCAL_REQUEST_REKEY_IKE));
3082         mLooper.dispatchAll();
3083         verifyRetransmissionStarted();
3084 
3085         // Prepare "rekeyed" SA
3086         setupRekeyedIkeSa(mSpyLocalInitIkeSaRecord);
3087 
3088         // Receive Rekey response
3089         ReceivedIkePacket dummyRekeyIkeRespReceivedPacket = makeRekeyIkeResponse();
3090         mIkeSessionStateMachine.sendMessage(
3091                 IkeSessionStateMachine.CMD_RECEIVE_IKE_PACKET, dummyRekeyIkeRespReceivedPacket);
3092         mLooper.dispatchAll();
3093         verifyIncrementLocaReqMsgId();
3094         verifyDecodeEncryptedMessage(mSpyCurrentIkeSaRecord, dummyRekeyIkeRespReceivedPacket);
3095 
3096         // Verify in delete state, and new SA record was saved:
3097         assertTrue(
3098                 mIkeSessionStateMachine.getCurrentState()
3099                         instanceof IkeSessionStateMachine.RekeyIkeLocalDelete);
3100         verifyRetransmissionStarted();
3101         assertEquals(mSpyLocalInitIkeSaRecord, mIkeSessionStateMachine.mLocalInitNewIkeSaRecord);
3102         verify(mSpyCurrentIkeSocket)
3103                 .registerIke(
3104                         eq(mSpyLocalInitIkeSaRecord.getLocalSpi()), eq(mIkeSessionStateMachine));
3105     }
3106 
3107     @Test
testRekeyIkeLocalCreateHandleRespWithParsingError()3108     public void testRekeyIkeLocalCreateHandleRespWithParsingError() throws Exception {
3109         setupIdleStateMachine();
3110 
3111         // Send Rekey-Create request
3112         mIkeSessionStateMachine.sendMessage(
3113                 IkeSessionStateMachine.CMD_EXECUTE_LOCAL_REQ,
3114                 new IkeLocalRequest(IkeSessionStateMachine.CMD_LOCAL_REQUEST_REKEY_IKE));
3115         mLooper.dispatchAll();
3116         verifyRetransmissionStarted();
3117         resetMockIkeMessageHelper();
3118 
3119         // Mock receiving packet with syntax error
3120         ReceivedIkePacket mockInvalidPacket =
3121                 makeDummyReceivedIkePacketWithInvalidSyntax(
3122                         mSpyCurrentIkeSaRecord,
3123                         true /*isResp*/,
3124                         IkeHeader.EXCHANGE_TYPE_CREATE_CHILD_SA);
3125         mIkeSessionStateMachine.sendMessage(CMD_RECEIVE_IKE_PACKET, mockInvalidPacket);
3126         mLooper.dispatchAll();
3127 
3128         // Verify Delete request was sent
3129         List<IkePayload> payloads = verifyOutInfoMsgHeaderAndGetPayloads(false /*isResp*/);
3130         assertEquals(1, payloads.size());
3131         assertEquals(IkePayload.PAYLOAD_TYPE_DELETE, payloads.get(0).payloadType);
3132 
3133         // Verify IKE Session is closed properly
3134         assertNull(mIkeSessionStateMachine.getCurrentState());
3135         verify(mMockIkeSessionCallback).onClosedExceptionally(any(InvalidSyntaxException.class));
3136     }
3137 
3138     @Test
testRekeyIkeLocalCreateHandleRespWithNonFatalErrorNotify()3139     public void testRekeyIkeLocalCreateHandleRespWithNonFatalErrorNotify() throws Exception {
3140         setupIdleStateMachine();
3141 
3142         // Send Rekey-Create request
3143         mIkeSessionStateMachine.sendMessage(
3144                 IkeSessionStateMachine.CMD_EXECUTE_LOCAL_REQ,
3145                 new IkeLocalRequest(IkeSessionStateMachine.CMD_LOCAL_REQUEST_REKEY_IKE));
3146         mLooper.dispatchAll();
3147 
3148         // Mock receiving packet with NO_PROPOSAL_CHOSEN
3149         ReceivedIkePacket resp =
3150                 makeResponseWithErrorNotify(new IkeNotifyPayload(ERROR_TYPE_NO_PROPOSAL_CHOSEN));
3151         mIkeSessionStateMachine.sendMessage(CMD_RECEIVE_IKE_PACKET, resp);
3152         mLooper.dispatchAll();
3153 
3154         // Verify IKE Session goes back to Idle and retry is scheduled
3155         verify(mSpyCurrentIkeSaRecord).rescheduleRekey(eq(RETRY_INTERVAL_MS));
3156         assertTrue(
3157                 mIkeSessionStateMachine.getCurrentState() instanceof IkeSessionStateMachine.Idle);
3158     }
3159 
3160     @Test
testRekeyIkeLocalCreateHandleRespWithFatalErrorNotify()3161     public void testRekeyIkeLocalCreateHandleRespWithFatalErrorNotify() throws Exception {
3162         setupIdleStateMachine();
3163 
3164         // Send Rekey-Create request
3165         mIkeSessionStateMachine.sendMessage(
3166                 IkeSessionStateMachine.CMD_EXECUTE_LOCAL_REQ,
3167                 new IkeLocalRequest(IkeSessionStateMachine.CMD_LOCAL_REQUEST_REKEY_IKE));
3168         mLooper.dispatchAll();
3169         resetMockIkeMessageHelper();
3170 
3171         // Mock receiving packet with NO_PROPOSAL_CHOSEN
3172         ReceivedIkePacket resp =
3173                 makeResponseWithErrorNotify(new IkeNotifyPayload(ERROR_TYPE_INVALID_SYNTAX));
3174         mIkeSessionStateMachine.sendMessage(CMD_RECEIVE_IKE_PACKET, resp);
3175         mLooper.dispatchAll();
3176 
3177         // Verify no message was sent because a fatal error notification was received
3178         verifyEncryptAndEncodeNeverCalled(mSpyCurrentIkeSaRecord);
3179 
3180         // Verify IKE Session is closed properly
3181         assertNull(mIkeSessionStateMachine.getCurrentState());
3182         verify(mMockIkeSessionCallback).onClosedExceptionally(any(InvalidSyntaxException.class));
3183     }
3184 
3185     @Test
testRekeyIkeLocalCreateSaCreationFail()3186     public void testRekeyIkeLocalCreateSaCreationFail() throws Exception {
3187         // Throw error when building new IKE SA
3188         throwExceptionWhenMakeRekeyIkeSa(
3189                 new GeneralSecurityException("testRekeyIkeLocalCreateSaCreationFail"));
3190 
3191         setupIdleStateMachine();
3192 
3193         // Send Rekey-Create request
3194         mIkeSessionStateMachine.sendMessage(
3195                 IkeSessionStateMachine.CMD_EXECUTE_LOCAL_REQ,
3196                 new IkeLocalRequest(IkeSessionStateMachine.CMD_LOCAL_REQUEST_REKEY_IKE));
3197         mLooper.dispatchAll();
3198         resetMockIkeMessageHelper();
3199 
3200         // Receive Rekey response
3201         ReceivedIkePacket dummyRekeyIkeRespReceivedPacket = makeRekeyIkeResponse();
3202         mIkeSessionStateMachine.sendMessage(
3203                 IkeSessionStateMachine.CMD_RECEIVE_IKE_PACKET, dummyRekeyIkeRespReceivedPacket);
3204         mLooper.dispatchAll();
3205 
3206         // Verify Delete request was sent
3207         List<IkePayload> payloads = verifyOutInfoMsgHeaderAndGetPayloads(false /*isResp*/);
3208         assertEquals(1, payloads.size());
3209         assertEquals(IkePayload.PAYLOAD_TYPE_DELETE, payloads.get(0).payloadType);
3210 
3211         // Verify IKE Session is closed properly
3212         assertNull(mIkeSessionStateMachine.getCurrentState());
3213         verify(mMockIkeSessionCallback).onClosedExceptionally(any(IkeInternalException.class));
3214     }
3215 
3216     @Test
testRekeyIkeLocalCreateHandleReqWithNonFatalError()3217     public void testRekeyIkeLocalCreateHandleReqWithNonFatalError() throws Exception {
3218         setupIdleStateMachine();
3219 
3220         // Send Rekey-Create request
3221         mIkeSessionStateMachine.sendMessage(
3222                 IkeSessionStateMachine.CMD_EXECUTE_LOCAL_REQ,
3223                 new IkeLocalRequest(IkeSessionStateMachine.CMD_LOCAL_REQUEST_REKEY_IKE));
3224         mLooper.dispatchAll();
3225         verifyRetransmissionStarted();
3226         resetMockIkeMessageHelper();
3227 
3228         // Build protocol exception
3229         List<Integer> unsupportedPayloads = new LinkedList<>();
3230         unsupportedPayloads.add(PAYLOAD_TYPE_UNSUPPORTED);
3231         UnsupportedCriticalPayloadException exception =
3232                 new UnsupportedCriticalPayloadException(unsupportedPayloads);
3233 
3234         // Mock receiving packet with unsupported critical payload
3235         ReceivedIkePacket mockInvalidPacket =
3236                 makeDummyReceivedIkePacketWithDecodingError(
3237                         mSpyCurrentIkeSaRecord,
3238                         false /*isResp*/,
3239                         IkeHeader.EXCHANGE_TYPE_CREATE_CHILD_SA,
3240                         exception);
3241         mIkeSessionStateMachine.sendMessage(CMD_RECEIVE_IKE_PACKET, mockInvalidPacket);
3242         mLooper.dispatchAll();
3243 
3244         // Verify error notification was sent
3245         List<IkePayload> payloads = verifyOutInfoMsgHeaderAndGetPayloads(true /*isResp*/);
3246         assertEquals(1, payloads.size());
3247 
3248         IkePayload payload = payloads.get(0);
3249         assertEquals(IkePayload.PAYLOAD_TYPE_NOTIFY, payload.payloadType);
3250         assertEquals(
3251                 ERROR_TYPE_UNSUPPORTED_CRITICAL_PAYLOAD, ((IkeNotifyPayload) payload).notifyType);
3252 
3253         // Verify IKE Session stays in the same state
3254         assertTrue(
3255                 mIkeSessionStateMachine.getCurrentState()
3256                         instanceof IkeSessionStateMachine.RekeyIkeLocalCreate);
3257     }
3258 
mockRescheduleRekey(IkeSaRecord spySaRecord)3259     private void mockRescheduleRekey(IkeSaRecord spySaRecord) {
3260         IkeLocalRequest rekeyReq =
3261                 new IkeLocalRequest(IkeSessionStateMachine.CMD_LOCAL_REQUEST_REKEY_IKE);
3262         doAnswer(
3263                 (invocation) -> {
3264                         mIkeSessionStateMachine.sendMessageDelayed(
3265                                 IkeSessionStateMachine.CMD_LOCAL_REQUEST_REKEY_IKE,
3266                                 rekeyReq,
3267                                 RETRY_INTERVAL_MS);
3268                         return null;
3269                 })
3270                 .when(spySaRecord)
3271                 .rescheduleRekey(eq(RETRY_INTERVAL_MS));
3272     }
3273 
3274     @Test
testRekeyIkeLocalCreateHandleRespWithTempFailure()3275     public void testRekeyIkeLocalCreateHandleRespWithTempFailure() throws Exception {
3276         setupIdleStateMachine();
3277 
3278         // Send Rekey-Create request
3279         mIkeSessionStateMachine.sendMessage(
3280                 IkeSessionStateMachine.CMD_EXECUTE_LOCAL_REQ,
3281                 new IkeLocalRequest(IkeSessionStateMachine.CMD_LOCAL_REQUEST_REKEY_IKE));
3282         mLooper.dispatchAll();
3283 
3284         // Mock sending TEMPORARY_FAILURE response
3285         mockRcvTempFail();
3286         mLooper.dispatchAll();
3287 
3288         verify(mSpyCurrentIkeSaRecord).rescheduleRekey(eq(RETRY_INTERVAL_MS));
3289         assertTrue(
3290                 mIkeSessionStateMachine.getCurrentState() instanceof IkeSessionStateMachine.Idle);
3291     }
3292 
mockCreateAndTransitionToRekeyDeleteLocal()3293     private void mockCreateAndTransitionToRekeyDeleteLocal() {
3294         // Seed fake rekey data and force transition to RekeyIkeLocalDelete
3295         mIkeSessionStateMachine.mLocalInitNewIkeSaRecord = mSpyLocalInitIkeSaRecord;
3296         mIkeSessionStateMachine.addIkeSaRecord(mSpyLocalInitIkeSaRecord);
3297         mIkeSessionStateMachine.sendMessage(
3298                 IkeSessionStateMachine.CMD_FORCE_TRANSITION,
3299                 mIkeSessionStateMachine.mRekeyIkeLocalDelete);
3300         mLooper.dispatchAll();
3301         verifyRetransmissionStarted();
3302     }
3303 
3304     @Test
testRekeyIkeLocalDeleteSendsRequest()3305     public void testRekeyIkeLocalDeleteSendsRequest() throws Exception {
3306         setupIdleStateMachine();
3307         mockCreateAndTransitionToRekeyDeleteLocal();
3308 
3309         // Verify Rekey-Delete request
3310         assertTrue(
3311                 mIkeSessionStateMachine.getCurrentState()
3312                         instanceof IkeSessionStateMachine.RekeyIkeLocalDelete);
3313         verifyRetransmissionStarted();
3314 
3315         // Verify outbound message
3316         IkeMessage delMsg = verifyEncryptAndEncodeAndGetMessage(mSpyCurrentIkeSaRecord);
3317 
3318         IkeHeader ikeHeader = delMsg.ikeHeader;
3319         assertEquals(mSpyCurrentIkeSaRecord.getInitiatorSpi(), ikeHeader.ikeInitiatorSpi);
3320         assertEquals(mSpyCurrentIkeSaRecord.getResponderSpi(), ikeHeader.ikeResponderSpi);
3321         assertEquals(IkePayload.PAYLOAD_TYPE_SK, ikeHeader.nextPayloadType);
3322         assertEquals(IkeHeader.EXCHANGE_TYPE_INFORMATIONAL, ikeHeader.exchangeType);
3323         assertEquals(mSpyCurrentIkeSaRecord.isLocalInit, ikeHeader.fromIkeInitiator);
3324         assertFalse(ikeHeader.isResponseMsg);
3325 
3326         List<IkeDeletePayload> deletePayloadList =
3327                 delMsg.getPayloadListForType(
3328                         IkePayload.PAYLOAD_TYPE_DELETE, IkeDeletePayload.class);
3329         assertEquals(1, deletePayloadList.size());
3330 
3331         IkeDeletePayload deletePayload = deletePayloadList.get(0);
3332         assertEquals(IkePayload.PROTOCOL_ID_IKE, deletePayload.protocolId);
3333         assertEquals(0, deletePayload.numSpi);
3334         assertEquals(0, deletePayload.spiSize);
3335         assertArrayEquals(new int[0], deletePayload.spisToDelete);
3336     }
3337 
verifyRekeyReplaceSa(IkeSaRecord newSaRecord)3338     private void verifyRekeyReplaceSa(IkeSaRecord newSaRecord) {
3339         verify(mSpyCurrentIkeSaRecord).close();
3340         verify(mSpyCurrentIkeSocket).unregisterIke(eq(mSpyCurrentIkeSaRecord.getLocalSpi()));
3341         verify(mSpyCurrentIkeSocket, never()).unregisterIke(eq(newSaRecord.getLocalSpi()));
3342 
3343         assertEquals(mIkeSessionStateMachine.mCurrentIkeSaRecord, newSaRecord);
3344 
3345         verify(mMockChildSessionStateMachine).setSkD(newSaRecord.getSkD());
3346     }
3347 
3348     @Test
testRekeyIkeLocalDeleteHandlesResponse()3349     public void testRekeyIkeLocalDeleteHandlesResponse() throws Exception {
3350         setupIdleStateMachine();
3351         mockCreateAndTransitionToRekeyDeleteLocal();
3352 
3353         // Receive Delete response
3354         ReceivedIkePacket dummyDeleteIkeRespReceivedPacket =
3355                 makeDeleteIkeResponse(mSpyCurrentIkeSaRecord);
3356         mIkeSessionStateMachine.sendMessage(
3357                 IkeSessionStateMachine.CMD_RECEIVE_IKE_PACKET, dummyDeleteIkeRespReceivedPacket);
3358         mLooper.dispatchAll();
3359         verifyIncrementLocaReqMsgId();
3360         verifyDecodeEncryptedMessage(mSpyCurrentIkeSaRecord, dummyDeleteIkeRespReceivedPacket);
3361 
3362         // Verify final state - Idle, with new SA, and old SA closed.
3363         verifyRekeyReplaceSa(mSpyLocalInitIkeSaRecord);
3364         verify(mMockIkeSessionCallback, never()).onClosed();
3365         assertTrue(
3366                 mIkeSessionStateMachine.getCurrentState() instanceof IkeSessionStateMachine.Idle);
3367         verifyRetransmissionStopped();
3368     }
3369 
3370     @Ignore
disableTestRekeyIkeLocalDeleteHandlesRespWithParsingError()3371     public void disableTestRekeyIkeLocalDeleteHandlesRespWithParsingError() throws Exception {
3372         setupIdleStateMachine();
3373         mockCreateAndTransitionToRekeyDeleteLocal();
3374         resetMockIkeMessageHelper();
3375 
3376         // Mock receiving packet with syntax error
3377         ReceivedIkePacket mockInvalidPacket =
3378                 makeDummyReceivedIkePacketWithInvalidSyntax(
3379                         mSpyCurrentIkeSaRecord,
3380                         true /*isResp*/,
3381                         IkeHeader.EXCHANGE_TYPE_INFORMATIONAL);
3382         mIkeSessionStateMachine.sendMessage(CMD_RECEIVE_IKE_PACKET, mockInvalidPacket);
3383         mLooper.dispatchAll();
3384 
3385         // Verify no more request out
3386         verifyEncryptAndEncodeNeverCalled(mSpyCurrentIkeSaRecord);
3387 
3388         // Verify final state - Idle, with new SA, and old SA closed.
3389         verifyRekeyReplaceSa(mSpyLocalInitIkeSaRecord);
3390         assertTrue(
3391                 mIkeSessionStateMachine.getCurrentState() instanceof IkeSessionStateMachine.Idle);
3392         verifyRetransmissionStopped();
3393     }
3394 
3395     @Test
testRekeyIkeLocalDeleteWithRequestOnNewSa()3396     public void testRekeyIkeLocalDeleteWithRequestOnNewSa() throws Exception {
3397         setupIdleStateMachine();
3398         mockCreateAndTransitionToRekeyDeleteLocal();
3399 
3400         // Receive an empty (DPD) request on the new IKE SA
3401         mIkeSessionStateMachine.sendMessage(
3402                 IkeSessionStateMachine.CMD_RECEIVE_IKE_PACKET,
3403                 makeDpdIkeRequest(mSpyLocalInitIkeSaRecord));
3404         mLooper.dispatchAll();
3405 
3406         // Verify final state - Idle, with new SA, and old SA closed.
3407         verifyRekeyReplaceSa(mSpyLocalInitIkeSaRecord);
3408         assertTrue(
3409                 mIkeSessionStateMachine.getCurrentState() instanceof IkeSessionStateMachine.Idle);
3410         verifyRetransmissionStopped();
3411     }
3412 
3413     @Test
testRekeyIkeLocalDeleteWithRequestFragOnNewSa()3414     public void testRekeyIkeLocalDeleteWithRequestFragOnNewSa() throws Exception {
3415         setupIdleStateMachine();
3416         mockCreateAndTransitionToRekeyDeleteLocal();
3417 
3418         // Received IKE fragment
3419         byte[] unencryptedData = "testRekeyIkeLocalDeleteWithRequestFragOnNewSa".getBytes();
3420         int fragNum = 1;
3421         int totalFragments = 2;
3422         IkeSkfPayload skfPayload =
3423                 IkeTestUtils.makeDummySkfPayload(unencryptedData, fragNum, totalFragments);
3424 
3425         ReceivedIkePacket packet =
3426                 makeDummyReceivedIkeFragmentPacket(
3427                         mSpyLocalInitIkeSaRecord,
3428                         false /*isResp*/,
3429                         IkeHeader.EXCHANGE_TYPE_CREATE_CHILD_SA,
3430                         skfPayload,
3431                         PAYLOAD_TYPE_SA,
3432                         null /* collectedFrags*/);
3433         mIkeSessionStateMachine.sendMessage(IkeSessionStateMachine.CMD_RECEIVE_IKE_PACKET, packet);
3434         mLooper.dispatchAll();
3435 
3436         // Verify rekey is done.
3437         verifyRekeyReplaceSa(mSpyLocalInitIkeSaRecord);
3438         verifyRetransmissionStopped();
3439 
3440         // Verify the IkeSaRecord has stored the new fragment.
3441         DecodeResultPartial resultPartial =
3442                 mSpyLocalInitIkeSaRecord.getCollectedFragments(false /*isResp*/);
3443         assertEquals(PAYLOAD_TYPE_SA, resultPartial.firstPayloadType);
3444         assertEquals(totalFragments, resultPartial.collectedFragsList.length);
3445         assertArrayEquals(unencryptedData, resultPartial.collectedFragsList[fragNum - 1]);
3446         assertFalse(resultPartial.isAllFragmentsReceived());
3447     }
3448 
3449     @Test
testRekeyIkeRemoteDeleteWithRequestOnNewSa()3450     public void testRekeyIkeRemoteDeleteWithRequestOnNewSa() throws Exception {
3451         setupIdleStateMachine();
3452 
3453         // Seed fake rekey data and force transition to RekeyIkeRemoteDelete
3454         mIkeSessionStateMachine.mRemoteInitNewIkeSaRecord = mSpyRemoteInitIkeSaRecord;
3455         mIkeSessionStateMachine.addIkeSaRecord(mSpyRemoteInitIkeSaRecord);
3456         mIkeSessionStateMachine.sendMessage(
3457                 IkeSessionStateMachine.CMD_FORCE_TRANSITION,
3458                 mIkeSessionStateMachine.mRekeyIkeRemoteDelete);
3459         mLooper.dispatchAll();
3460 
3461         // Receive an empty (DPD) request on the new IKE SA
3462         mIkeSessionStateMachine.sendMessage(
3463                 IkeSessionStateMachine.CMD_RECEIVE_IKE_PACKET,
3464                 makeDpdIkeRequest(mSpyRemoteInitIkeSaRecord));
3465         mLooper.dispatchAll();
3466 
3467         // Verify final state - Idle, with new SA, and old SA closed.
3468         verifyRekeyReplaceSa(mSpyRemoteInitIkeSaRecord);
3469         assertTrue(
3470                 mIkeSessionStateMachine.getCurrentState() instanceof IkeSessionStateMachine.Idle);
3471     }
3472 
3473     @Test
testRekeyIkeRemoteCreate()3474     public void testRekeyIkeRemoteCreate() throws Exception {
3475         setupIdleStateMachine();
3476 
3477         setupRekeyedIkeSa(mSpyRemoteInitIkeSaRecord);
3478 
3479         // Receive Rekey request
3480         ReceivedIkePacket dummyRekeyIkeRequestReceivedPacket = makeRekeyIkeRequest();
3481         mIkeSessionStateMachine.sendMessage(
3482                 IkeSessionStateMachine.CMD_RECEIVE_IKE_PACKET, dummyRekeyIkeRequestReceivedPacket);
3483         mLooper.dispatchAll();
3484         verifyIncrementRemoteReqMsgId();
3485         verifyDecodeEncryptedMessage(mSpyCurrentIkeSaRecord, dummyRekeyIkeRequestReceivedPacket);
3486 
3487         // Verify SA created with correct parameters
3488         ArgumentCaptor<SaRecord.IkeSaRecordConfig> recordConfigCaptor =
3489                 ArgumentCaptor.forClass(SaRecord.IkeSaRecordConfig.class);
3490         verify(mMockSaRecordHelper)
3491                 .makeRekeyedIkeSaRecord(any(), any(), any(), any(), recordConfigCaptor.capture());
3492         assertEquals(IKE_REKEY_SA_INITIATOR_SPI, recordConfigCaptor.getValue().initSpi.getSpi());
3493 
3494         // Verify outbound CREATE_CHILD_SA message
3495         IkeMessage rekeyCreateResp = verifyEncryptAndEncodeAndGetMessage(mSpyCurrentIkeSaRecord);
3496         IkeHeader rekeyCreateRespHeader = rekeyCreateResp.ikeHeader;
3497         assertEquals(IkePayload.PAYLOAD_TYPE_SK, rekeyCreateRespHeader.nextPayloadType);
3498         assertEquals(IkeHeader.EXCHANGE_TYPE_CREATE_CHILD_SA, rekeyCreateRespHeader.exchangeType);
3499         assertTrue(rekeyCreateRespHeader.isResponseMsg);
3500         assertTrue(rekeyCreateRespHeader.fromIkeInitiator);
3501         assertNotNull(
3502                 rekeyCreateResp.getPayloadForType(IkePayload.PAYLOAD_TYPE_SA, IkeSaPayload.class));
3503         assertNotNull(
3504                 rekeyCreateResp.getPayloadForType(IkePayload.PAYLOAD_TYPE_KE, IkeKePayload.class));
3505         assertNotNull(
3506                 rekeyCreateResp.getPayloadForType(
3507                         IkePayload.PAYLOAD_TYPE_NONCE, IkeNoncePayload.class));
3508 
3509         // Verify SA, StateMachine state
3510         assertEquals(mSpyCurrentIkeSaRecord, mIkeSessionStateMachine.mIkeSaRecordAwaitingRemoteDel);
3511         assertEquals(mSpyRemoteInitIkeSaRecord, mIkeSessionStateMachine.mIkeSaRecordSurviving);
3512         assertTrue(
3513                 mIkeSessionStateMachine.getCurrentState()
3514                         instanceof IkeSessionStateMachine.RekeyIkeRemoteDelete);
3515         verify(mSpyCurrentIkeSocket)
3516                 .registerIke(
3517                         eq(mSpyRemoteInitIkeSaRecord.getLocalSpi()), eq(mIkeSessionStateMachine));
3518     }
3519 
3520     @Ignore
disableTestRekeyIkeRemoteCreateHandlesInvalidReq()3521     public void disableTestRekeyIkeRemoteCreateHandlesInvalidReq() throws Exception {
3522         setupIdleStateMachine();
3523 
3524         // Receive Rekey request
3525         ReceivedIkePacket request = makeRekeyIkeRequestWithUnacceptableProposal();
3526         mIkeSessionStateMachine.sendMessage(IkeSessionStateMachine.CMD_RECEIVE_IKE_PACKET, request);
3527         mLooper.dispatchAll();
3528 
3529         verifyProcessRekeyReqFailure(ERROR_TYPE_NO_PROPOSAL_CHOSEN);
3530     }
3531 
3532     @Ignore
disableTestRekeyIkeRemoteCreateSaCreationFailure()3533     public void disableTestRekeyIkeRemoteCreateSaCreationFailure() throws Exception {
3534         // Throw error when building new IKE SA
3535         throwExceptionWhenMakeRekeyIkeSa(
3536                 new GeneralSecurityException("testRekeyIkeRemoteCreateSaCreationFailure"));
3537         setupIdleStateMachine();
3538 
3539         // Receive Rekey request
3540         ReceivedIkePacket request = makeRekeyIkeRequest();
3541         mIkeSessionStateMachine.sendMessage(IkeSessionStateMachine.CMD_RECEIVE_IKE_PACKET, request);
3542         mLooper.dispatchAll();
3543 
3544         verifyProcessRekeyReqFailure(ERROR_TYPE_NO_PROPOSAL_CHOSEN);
3545     }
3546 
verifyProcessRekeyReqFailure(int expectedErrorCode)3547     private void verifyProcessRekeyReqFailure(int expectedErrorCode) {
3548         // Verify IKE Session is back to Idle
3549         assertTrue(
3550                 mIkeSessionStateMachine.getCurrentState() instanceof IkeSessionStateMachine.Idle);
3551 
3552         // Verify error notification was sent
3553         List<IkePayload> payloads = verifyOutInfoMsgHeaderAndGetPayloads(true /*isResp*/);
3554         assertEquals(1, payloads.size());
3555         IkeNotifyPayload notify = (IkeNotifyPayload) payloads.get(0);
3556         assertEquals(expectedErrorCode, notify.notifyType);
3557     }
3558 
3559     @Test
testRekeyIkeRemoteDelete()3560     public void testRekeyIkeRemoteDelete() throws Exception {
3561         setupIdleStateMachine();
3562 
3563         // Seed fake rekey data and force transition to RekeyIkeLocalDelete
3564         mIkeSessionStateMachine.mRemoteInitNewIkeSaRecord = mSpyRemoteInitIkeSaRecord;
3565         mIkeSessionStateMachine.sendMessage(
3566                 IkeSessionStateMachine.CMD_FORCE_TRANSITION,
3567                 mIkeSessionStateMachine.mRekeyIkeRemoteDelete);
3568         mLooper.dispatchAll();
3569 
3570         // Rekey Delete request
3571         ReceivedIkePacket dummyDeleteIkeRequestReceivedPacket =
3572                 makeDeleteIkeRequest(mSpyCurrentIkeSaRecord);
3573         mIkeSessionStateMachine.sendMessage(
3574                 IkeSessionStateMachine.CMD_RECEIVE_IKE_PACKET, dummyDeleteIkeRequestReceivedPacket);
3575         mLooper.dispatchAll();
3576         verifyIncrementRemoteReqMsgId();
3577         verifyDecodeEncryptedMessage(mSpyCurrentIkeSaRecord, dummyDeleteIkeRequestReceivedPacket);
3578 
3579         // Verify outbound DELETE_IKE_SA message
3580         IkeMessage rekeyDeleteResp = verifyEncryptAndEncodeAndGetMessage(mSpyCurrentIkeSaRecord);
3581         IkeHeader rekeyDeleteRespHeader = rekeyDeleteResp.ikeHeader;
3582         assertEquals(IkePayload.PAYLOAD_TYPE_SK, rekeyDeleteRespHeader.nextPayloadType);
3583         assertEquals(IkeHeader.EXCHANGE_TYPE_INFORMATIONAL, rekeyDeleteRespHeader.exchangeType);
3584         assertTrue(rekeyDeleteRespHeader.isResponseMsg);
3585         assertTrue(rekeyDeleteRespHeader.fromIkeInitiator);
3586         assertTrue(rekeyDeleteResp.ikePayloadList.isEmpty());
3587 
3588         // Verify final state - Idle, with new SA, and old SA closed.
3589         verifyRekeyReplaceSa(mSpyRemoteInitIkeSaRecord);
3590 
3591         verify(mMockIkeSessionCallback, never()).onClosed();
3592 
3593         verifyDecodeEncryptedMessage(mSpyCurrentIkeSaRecord, dummyDeleteIkeRequestReceivedPacket);
3594         assertTrue(
3595                 mIkeSessionStateMachine.getCurrentState() instanceof IkeSessionStateMachine.Idle);
3596     }
3597 
3598     @Test
testRekeyIkeRemoteDeleteExitAndRenter()3599     public void testRekeyIkeRemoteDeleteExitAndRenter() throws Exception {
3600         setupIdleStateMachine();
3601 
3602         // Seed fake rekey data and force transition to RekeyIkeLocalDelete
3603         mIkeSessionStateMachine.mRemoteInitNewIkeSaRecord = mSpyRemoteInitIkeSaRecord;
3604         mIkeSessionStateMachine.sendMessage(
3605                 IkeSessionStateMachine.CMD_FORCE_TRANSITION,
3606                 mIkeSessionStateMachine.mRekeyIkeRemoteDelete);
3607         mLooper.dispatchAll();
3608 
3609         // Trigger a timeout, and immediately re-enter remote-delete
3610         mLooper.moveTimeForward(IkeSessionStateMachine.REKEY_DELETE_TIMEOUT_MS / 2 + 1);
3611         mIkeSessionStateMachine.sendMessage(IkeSessionStateMachine.TIMEOUT_REKEY_REMOTE_DELETE);
3612         mIkeSessionStateMachine.sendMessage(
3613                 IkeSessionStateMachine.CMD_FORCE_TRANSITION,
3614                 mIkeSessionStateMachine.mRekeyIkeRemoteDelete);
3615         mLooper.dispatchAll();
3616 
3617         // Shift time forward, and assert the previous timeout was NOT fired.
3618         mLooper.moveTimeForward(IkeSessionStateMachine.REKEY_DELETE_TIMEOUT_MS / 2 + 1);
3619         mLooper.dispatchAll();
3620 
3621         // Verify no request received, or response sent.
3622         verify(mMockIkeMessageHelper, never()).decode(anyInt(), anyObject(), anyObject());
3623         verifyEncryptAndEncodeNeverCalled(mSpyCurrentIkeSaRecord);
3624 
3625         // Verify final state has not changed - signal was not sent.
3626         assertTrue(
3627                 mIkeSessionStateMachine.getCurrentState()
3628                         instanceof IkeSessionStateMachine.RekeyIkeRemoteDelete);
3629     }
3630 
3631     @Test
testRekeyIkeRemoteDeleteTimedOut()3632     public void testRekeyIkeRemoteDeleteTimedOut() throws Exception {
3633         setupIdleStateMachine();
3634 
3635         // Seed fake rekey data and force transition to RekeyIkeLocalDelete
3636         mIkeSessionStateMachine.mRemoteInitNewIkeSaRecord = mSpyRemoteInitIkeSaRecord;
3637         mIkeSessionStateMachine.sendMessage(
3638                 IkeSessionStateMachine.CMD_FORCE_TRANSITION,
3639                 mIkeSessionStateMachine.mRekeyIkeRemoteDelete);
3640         mLooper.dispatchAll();
3641 
3642         mLooper.moveTimeForward(IkeSessionStateMachine.REKEY_DELETE_TIMEOUT_MS);
3643         mLooper.dispatchAll();
3644 
3645         // Verify no request received, or response sent.
3646         verify(mMockIkeMessageHelper, never()).decode(anyInt(), anyObject(), anyObject());
3647         verifyEncryptAndEncodeNeverCalled(mSpyCurrentIkeSaRecord);
3648 
3649         // Verify final state - Idle, with new SA, and old SA closed.
3650         verifyRekeyReplaceSa(mSpyRemoteInitIkeSaRecord);
3651 
3652         assertTrue(
3653                 mIkeSessionStateMachine.getCurrentState() instanceof IkeSessionStateMachine.Idle);
3654     }
3655 
3656     @Ignore
disableTestSimulRekey()3657     public void disableTestSimulRekey() throws Exception {
3658         setupIdleStateMachine();
3659 
3660         // Prepare "rekeyed" SA
3661         setupRekeyedIkeSa(mSpyLocalInitIkeSaRecord);
3662         doReturn(1).when(mSpyLocalInitIkeSaRecord).compareTo(mSpyRemoteInitIkeSaRecord);
3663 
3664         // Send Rekey request on mSpyCurrentIkeSaRecord
3665         mIkeSessionStateMachine.sendMessage(
3666                 IkeSessionStateMachine.CMD_EXECUTE_LOCAL_REQ,
3667                 new IkeLocalRequest(IkeSessionStateMachine.CMD_LOCAL_REQUEST_REKEY_IKE));
3668 
3669         // Receive Rekey request on mSpyCurrentIkeSaRecord
3670         ReceivedIkePacket dummyRekeyIkeRequestReceivedPacket = makeRekeyIkeRequest();
3671         mIkeSessionStateMachine.sendMessage(
3672                 IkeSessionStateMachine.CMD_RECEIVE_IKE_PACKET, dummyRekeyIkeRequestReceivedPacket);
3673         mLooper.dispatchAll();
3674         verifyIncrementRemoteReqMsgId();
3675 
3676         // Receive Rekey response on mSpyCurrentIkeSaRecord
3677         ReceivedIkePacket dummyRekeyIkeRespReceivedPacket = makeRekeyIkeResponse();
3678         mIkeSessionStateMachine.sendMessage(
3679                 IkeSessionStateMachine.CMD_RECEIVE_IKE_PACKET, dummyRekeyIkeRespReceivedPacket);
3680         mLooper.dispatchAll();
3681         verifyIncrementLocaReqMsgId();
3682         verify(mSpyCurrentIkeSocket)
3683                 .registerIke(
3684                         eq(mSpyLocalInitIkeSaRecord.getLocalSpi()), eq(mIkeSessionStateMachine));
3685 
3686         // Receive Delete response on mSpyCurrentIkeSaRecord
3687         ReceivedIkePacket dummyDeleteIkeRespReceivedPacket =
3688                 makeDeleteIkeResponse(mSpyCurrentIkeSaRecord);
3689         mIkeSessionStateMachine.sendMessage(
3690                 IkeSessionStateMachine.CMD_RECEIVE_IKE_PACKET, dummyDeleteIkeRespReceivedPacket);
3691         mLooper.dispatchAll();
3692         verifyIncrementLocaReqMsgId();
3693 
3694         // Verify
3695         verifyDecodeEncryptedMessage(mSpyCurrentIkeSaRecord, dummyRekeyIkeRequestReceivedPacket);
3696         verifyDecodeEncryptedMessage(mSpyCurrentIkeSaRecord, dummyRekeyIkeRespReceivedPacket);
3697         verifyDecodeEncryptedMessage(mSpyCurrentIkeSaRecord, dummyDeleteIkeRespReceivedPacket);
3698         assertTrue(
3699                 mIkeSessionStateMachine.getCurrentState() instanceof IkeSessionStateMachine.Idle);
3700 
3701         verifyRekeyReplaceSa(mSpyLocalInitIkeSaRecord);
3702         verify(mMockIkeSessionCallback, never()).onClosed();
3703     }
3704 
3705     @Test
testOpenIkeSession()3706     public void testOpenIkeSession() throws Exception {
3707         assertTrue(
3708                 mIkeSessionStateMachine.getCurrentState()
3709                         instanceof IkeSessionStateMachine.Initial);
3710 
3711         mIkeSessionStateMachine.openSession();
3712         mLooper.dispatchAll();
3713 
3714         assertTrue(
3715                 mIkeSessionStateMachine.getCurrentState()
3716                         instanceof IkeSessionStateMachine.CreateIkeLocalIkeInit);
3717     }
3718 
3719     @Test
testIkeInitSchedulesRekey()3720     public void testIkeInitSchedulesRekey() throws Exception {
3721         setupFirstIkeSa();
3722 
3723         // Send IKE INIT request
3724         mIkeSessionStateMachine.sendMessage(IkeSessionStateMachine.CMD_LOCAL_REQUEST_CREATE_IKE);
3725 
3726         // Receive IKE INIT response
3727         ReceivedIkePacket dummyReceivedIkePacket = makeIkeInitResponse();
3728         mIkeSessionStateMachine.sendMessage(
3729                 IkeSessionStateMachine.CMD_RECEIVE_IKE_PACKET, dummyReceivedIkePacket);
3730 
3731         // Mock IKE AUTH and transition to Idle
3732         mIkeSessionStateMachine.sendMessage(
3733                 IkeSessionStateMachine.CMD_FORCE_TRANSITION, mIkeSessionStateMachine.mIdle);
3734         mLooper.dispatchAll();
3735         mIkeSessionStateMachine.mSaProposal = buildSaProposal();
3736 
3737         // Move time forward to trigger rekey
3738         mLooper.moveTimeForward(
3739                 mIkeSessionStateMachine.mIkeSessionParams.getSoftLifetimeMsInternal());
3740         mLooper.dispatchAll();
3741 
3742         assertTrue(
3743                 mIkeSessionStateMachine.getCurrentState()
3744                         instanceof IkeSessionStateMachine.RekeyIkeLocalCreate);
3745     }
3746 
3747     @Test
testRekeyCreateIkeSchedulesRekey()3748     public void testRekeyCreateIkeSchedulesRekey() throws Exception {
3749         setupIdleStateMachine();
3750 
3751         // Send Rekey-Create request
3752         mIkeSessionStateMachine.sendMessage(
3753                 IkeSessionStateMachine.CMD_EXECUTE_LOCAL_REQ,
3754                 new IkeLocalRequest(IkeSessionStateMachine.CMD_LOCAL_REQUEST_REKEY_IKE));
3755         mLooper.dispatchAll();
3756 
3757         // Prepare "rekeyed" SA
3758         setupRekeyedIkeSa(mSpyLocalInitIkeSaRecord);
3759 
3760         // Receive Rekey response
3761         ReceivedIkePacket dummyRekeyIkeRespReceivedPacket = makeRekeyIkeResponse();
3762         mIkeSessionStateMachine.sendMessage(
3763                 IkeSessionStateMachine.CMD_RECEIVE_IKE_PACKET, dummyRekeyIkeRespReceivedPacket);
3764         mLooper.dispatchAll();
3765 
3766         // Mock rekey delete and transition to Idle
3767         mIkeSessionStateMachine.mCurrentIkeSaRecord = mSpyLocalInitIkeSaRecord;
3768         mIkeSessionStateMachine.sendMessage(
3769                 IkeSessionStateMachine.CMD_FORCE_TRANSITION, mIkeSessionStateMachine.mIdle);
3770         mLooper.dispatchAll();
3771 
3772         // Move time forward to trigger rekey
3773         mLooper.moveTimeForward(
3774                 mIkeSessionStateMachine.mIkeSessionParams.getSoftLifetimeMsInternal());
3775         mLooper.dispatchAll();
3776 
3777         assertTrue(
3778                 mIkeSessionStateMachine.getCurrentState()
3779                         instanceof IkeSessionStateMachine.RekeyIkeLocalCreate);
3780     }
3781 
3782     @Test
testBuildEncryptedInformationalMessage()3783     public void testBuildEncryptedInformationalMessage() throws Exception {
3784         IkeNotifyPayload payload = new IkeNotifyPayload(ERROR_TYPE_INVALID_SYNTAX, new byte[0]);
3785 
3786         boolean isResp = false;
3787         IkeMessage generated =
3788                 mIkeSessionStateMachine.buildEncryptedInformationalMessage(
3789                         mSpyCurrentIkeSaRecord, new IkeInformationalPayload[] {payload}, isResp, 0);
3790 
3791         assertEquals(mSpyCurrentIkeSaRecord.getInitiatorSpi(), generated.ikeHeader.ikeInitiatorSpi);
3792         assertEquals(mSpyCurrentIkeSaRecord.getResponderSpi(), generated.ikeHeader.ikeResponderSpi);
3793         assertEquals(
3794                 mSpyCurrentIkeSaRecord.getLocalRequestMessageId(), generated.ikeHeader.messageId);
3795         assertEquals(isResp, generated.ikeHeader.isResponseMsg);
3796         assertEquals(IkePayload.PAYLOAD_TYPE_SK, generated.ikeHeader.nextPayloadType);
3797 
3798         List<IkeNotifyPayload> generatedPayloads =
3799                 generated.getPayloadListForType(
3800                         IkePayload.PAYLOAD_TYPE_NOTIFY, IkeNotifyPayload.class);
3801         assertEquals(1, generatedPayloads.size());
3802 
3803         IkeNotifyPayload generatedPayload = generatedPayloads.get(0);
3804         assertArrayEquals(new byte[0], generatedPayload.notifyData);
3805         assertEquals(ERROR_TYPE_INVALID_SYNTAX, generatedPayload.notifyType);
3806     }
3807 
verifyLastSentRespAllPackets(byte[][] expectedPackets, IkeSaRecord saRecord)3808     private void verifyLastSentRespAllPackets(byte[][] expectedPackets, IkeSaRecord saRecord) {
3809         if (expectedPackets == null) {
3810             assertNull(saRecord.getLastSentRespAllPackets());
3811             return;
3812         }
3813 
3814         assertEquals(expectedPackets.length, saRecord.getLastSentRespAllPackets().size());
3815         for (int i = 0; i < expectedPackets.length; i++) {
3816             assertArrayEquals(expectedPackets[i], saRecord.getLastSentRespAllPackets().get(i));
3817         }
3818     }
3819 
3820     @Test
testEncryptedRetransmitterImmediatelySendsRequest()3821     public void testEncryptedRetransmitterImmediatelySendsRequest() throws Exception {
3822         setupIdleStateMachine();
3823         byte[][] dummyLastRespBytes =
3824                 new byte[][] {"testRetransmitterSendsRequestLastResp".getBytes()};
3825         mSpyCurrentIkeSaRecord.updateLastSentRespAllPackets(Arrays.asList(dummyLastRespBytes));
3826 
3827         IkeMessage spyIkeReqMessage =
3828                 spy(
3829                         new IkeMessage(
3830                                 new IkeHeader(
3831                                         mSpyCurrentIkeSaRecord.getInitiatorSpi(),
3832                                         mSpyCurrentIkeSaRecord.getResponderSpi(),
3833                                         IkePayload.PAYLOAD_TYPE_SK,
3834                                         EXCHANGE_TYPE_INFORMATIONAL,
3835                                         false /*isResp*/,
3836                                         mSpyCurrentIkeSaRecord.isLocalInit,
3837                                         mSpyCurrentIkeSaRecord.getLocalRequestMessageId()),
3838                                 new LinkedList<>()));
3839 
3840         // Use something unique as a sentinel value
3841         byte[][] dummyReqBytesList =
3842                 new byte[][] {
3843                     "testRetransmitterSendsReqFrag1".getBytes(),
3844                     "testRetransmitterSendsReqFrag2".getBytes()
3845                 };
3846 
3847         doReturn(dummyReqBytesList)
3848                 .when(spyIkeReqMessage)
3849                 .encryptAndEncode(any(), any(), eq(mSpyCurrentIkeSaRecord), anyBoolean(), anyInt());
3850 
3851         IkeSessionStateMachine.EncryptedRetransmitter retransmitter =
3852                 mIkeSessionStateMachine.new EncryptedRetransmitter(spyIkeReqMessage);
3853 
3854         // Verify message is sent out, and that request does not change cached retransmit-response
3855         // mLastSentIkeResp.
3856         verify(mSpyCurrentIkeSocket).sendIkePacket(eq(dummyReqBytesList[0]), eq(REMOTE_ADDRESS));
3857         verify(mSpyCurrentIkeSocket).sendIkePacket(eq(dummyReqBytesList[1]), eq(REMOTE_ADDRESS));
3858         verifyLastSentRespAllPackets(dummyLastRespBytes, mSpyCurrentIkeSaRecord);
3859     }
3860 
3861     // TODO: b/141275871 Test retransmisstions are fired for correct times within certain time.
3862 
3863     @Test
testCacheLastRequestAndResponse()3864     public void testCacheLastRequestAndResponse() throws Exception {
3865         setupIdleStateMachine();
3866         mSpyCurrentIkeSaRecord.updateLastReceivedReqFirstPacket(null /*reqPacket*/);
3867         mSpyCurrentIkeSaRecord.updateLastSentRespAllPackets(null /*respPacketList*/);
3868 
3869         byte[] dummyIkeReqFirstPacket = "testLastSentRequest".getBytes();
3870         byte[][] dummyIkeResp =
3871                 new byte[][] {
3872                     "testLastSentRespFrag1".getBytes(), "testLastSentRespFrag2".getBytes()
3873                 };
3874 
3875         doReturn(dummyIkeResp)
3876                 .when(mMockIkeMessageHelper)
3877                 .encryptAndEncode(
3878                         any(),
3879                         any(),
3880                         eq(mSpyCurrentIkeSaRecord),
3881                         any(IkeMessage.class),
3882                         anyBoolean(),
3883                         anyInt());
3884 
3885         // Receive a DPD request, expect to send dummyIkeResp
3886         ReceivedIkePacket dummyDpdRequest =
3887                 makeDpdIkeRequest(
3888                         mSpyCurrentIkeSaRecord.getRemoteRequestMessageId(), dummyIkeReqFirstPacket);
3889         mIkeSessionStateMachine.sendMessage(
3890                 IkeSessionStateMachine.CMD_RECEIVE_IKE_PACKET, dummyDpdRequest);
3891         mLooper.dispatchAll();
3892 
3893         verify(mSpyCurrentIkeSocket).sendIkePacket(eq(dummyIkeResp[0]), eq(REMOTE_ADDRESS));
3894         verify(mSpyCurrentIkeSocket).sendIkePacket(eq(dummyIkeResp[1]), eq(REMOTE_ADDRESS));
3895 
3896         verifyLastSentRespAllPackets(dummyIkeResp, mSpyCurrentIkeSaRecord);
3897         assertTrue(mSpyCurrentIkeSaRecord.isRetransmittedRequest(dummyIkeReqFirstPacket));
3898 
3899         assertTrue(
3900                 mIkeSessionStateMachine.getCurrentState() instanceof IkeSessionStateMachine.Idle);
3901     }
3902 
3903     @Test
testReplyRetransmittedRequest()3904     public void testReplyRetransmittedRequest() throws Exception {
3905         setupIdleStateMachine();
3906 
3907         // Mock last sent request and response
3908         byte[] dummyIkeReqFirstPacket = "testRcvRetransmittedRequestReq".getBytes();
3909         byte[][] dummyIkeResp = new byte[][] {"testRcvRetransmittedRequestResp".getBytes()};
3910 
3911         mSpyCurrentIkeSaRecord.updateLastReceivedReqFirstPacket(dummyIkeReqFirstPacket);
3912         mSpyCurrentIkeSaRecord.updateLastSentRespAllPackets(Arrays.asList(dummyIkeResp));
3913         mSpyCurrentIkeSaRecord.incrementRemoteRequestMessageId();
3914 
3915         // Build request with last validated message ID
3916         ReceivedIkePacket request =
3917                 makeDpdIkeRequest(
3918                         mSpyCurrentIkeSaRecord.getRemoteRequestMessageId() - 1,
3919                         dummyIkeReqFirstPacket);
3920 
3921         mIkeSessionStateMachine.sendMessage(IkeSessionStateMachine.CMD_RECEIVE_IKE_PACKET, request);
3922 
3923         mLooper.dispatchAll();
3924 
3925         verifyLastSentRespAllPackets(dummyIkeResp, mSpyCurrentIkeSaRecord);
3926         verify(mSpyCurrentIkeSocket).sendIkePacket(eq(dummyIkeResp[0]), eq(REMOTE_ADDRESS));
3927 
3928         assertTrue(
3929                 mIkeSessionStateMachine.getCurrentState() instanceof IkeSessionStateMachine.Idle);
3930     }
3931 
3932     @Test
testDiscardFakeRetransmittedRequest()3933     public void testDiscardFakeRetransmittedRequest() throws Exception {
3934         setupIdleStateMachine();
3935 
3936         // Mock last sent request and response
3937         byte[] dummyIkeReqFirstPacket = "testDiscardFakeRetransmittedRequestReq".getBytes();
3938         byte[][] dummyIkeResp = new byte[][] {"testDiscardFakeRetransmittedRequestResp".getBytes()};
3939         mSpyCurrentIkeSaRecord.updateLastReceivedReqFirstPacket(dummyIkeReqFirstPacket);
3940         mSpyCurrentIkeSaRecord.updateLastSentRespAllPackets(Arrays.asList(dummyIkeResp));
3941         mSpyCurrentIkeSaRecord.incrementRemoteRequestMessageId();
3942 
3943         // Build request with last validated message ID but different bytes
3944         ReceivedIkePacket request =
3945                 makeDpdIkeRequest(
3946                         mSpyCurrentIkeSaRecord.getRemoteRequestMessageId() - 1, new byte[0]);
3947 
3948         mIkeSessionStateMachine.sendMessage(IkeSessionStateMachine.CMD_RECEIVE_IKE_PACKET, request);
3949 
3950         mLooper.dispatchAll();
3951 
3952         verifyLastSentRespAllPackets(dummyIkeResp, mSpyCurrentIkeSaRecord);
3953         verify(mSpyCurrentIkeSocket, never()).sendIkePacket(any(), any());
3954 
3955         assertTrue(
3956                 mIkeSessionStateMachine.getCurrentState() instanceof IkeSessionStateMachine.Idle);
3957     }
3958 
3959     @Test
testDiscardRetransmittedResponse()3960     public void testDiscardRetransmittedResponse() throws Exception {
3961         mockIkeInitAndTransitionToIkeAuth(mIkeSessionStateMachine.mCreateIkeLocalIkeAuth);
3962         verifyRetransmissionStarted();
3963 
3964         // Build and send fake response with last validated message ID to IKE state machine
3965         ReceivedIkePacket resp =
3966                 makeDummyEncryptedReceivedIkePacketWithPayloadList(
3967                         mSpyCurrentIkeSaRecord,
3968                         IkeHeader.EXCHANGE_TYPE_IKE_SA_INIT,
3969                         true /*isResp*/,
3970                         mSpyCurrentIkeSaRecord.getLocalRequestMessageId() - 1,
3971                         new LinkedList<>(),
3972                         new byte[0]);
3973 
3974         mIkeSessionStateMachine.sendMessage(IkeSessionStateMachine.CMD_RECEIVE_IKE_PACKET, resp);
3975         mLooper.dispatchAll();
3976 
3977         // Verify current state does not change
3978         verifyRetransmissionStarted();
3979         assertTrue(
3980                 mIkeSessionStateMachine.getCurrentState()
3981                         instanceof IkeSessionStateMachine.CreateIkeLocalIkeAuth);
3982     }
3983 
3984     @Test
testDeleteIkeLocalDeleteRequest()3985     public void testDeleteIkeLocalDeleteRequest() throws Exception {
3986         setupIdleStateMachine();
3987 
3988         mIkeSessionStateMachine.sendMessage(
3989                 IkeSessionStateMachine.CMD_EXECUTE_LOCAL_REQ,
3990                 new IkeLocalRequest(IkeSessionStateMachine.CMD_LOCAL_REQUEST_DELETE_IKE));
3991         mLooper.dispatchAll();
3992         verifyRetransmissionStarted();
3993 
3994         // Verify outbound message
3995         IkeMessage delMsg = verifyEncryptAndEncodeAndGetMessage(mSpyCurrentIkeSaRecord);
3996 
3997         IkeHeader ikeHeader = delMsg.ikeHeader;
3998         assertEquals(IkePayload.PAYLOAD_TYPE_SK, ikeHeader.nextPayloadType);
3999         assertEquals(IkeHeader.EXCHANGE_TYPE_INFORMATIONAL, ikeHeader.exchangeType);
4000         assertFalse(ikeHeader.isResponseMsg);
4001         assertTrue(ikeHeader.fromIkeInitiator);
4002 
4003         List<IkeDeletePayload> deletePayloadList =
4004                 delMsg.getPayloadListForType(
4005                         IkePayload.PAYLOAD_TYPE_DELETE, IkeDeletePayload.class);
4006         assertEquals(1, deletePayloadList.size());
4007 
4008         IkeDeletePayload deletePayload = deletePayloadList.get(0);
4009         assertEquals(IkePayload.PROTOCOL_ID_IKE, deletePayload.protocolId);
4010         assertEquals(0, deletePayload.numSpi);
4011         assertEquals(0, deletePayload.spiSize);
4012         assertArrayEquals(new int[0], deletePayload.spisToDelete);
4013     }
4014 
4015     @Test
testDeleteIkeLocalDeleteResponse()4016     public void testDeleteIkeLocalDeleteResponse() throws Exception {
4017         setupIdleStateMachine();
4018 
4019         mIkeSessionStateMachine.sendMessage(
4020                 IkeSessionStateMachine.CMD_EXECUTE_LOCAL_REQ,
4021                 new IkeLocalRequest(IkeSessionStateMachine.CMD_LOCAL_REQUEST_DELETE_IKE));
4022         mLooper.dispatchAll();
4023         verifyRetransmissionStarted();
4024 
4025         ReceivedIkePacket received = makeDeleteIkeResponse(mSpyCurrentIkeSaRecord);
4026         mIkeSessionStateMachine.sendMessage(
4027                 IkeSessionStateMachine.CMD_RECEIVE_IKE_PACKET, received);
4028         mLooper.dispatchAll();
4029         verifyIncrementLocaReqMsgId();
4030 
4031         verifyNotifyUserCloseSession();
4032 
4033         // Verify state machine quit properly
4034         assertNull(mIkeSessionStateMachine.getCurrentState());
4035     }
4036 
4037     @Test
testDeleteIkeLocalDeleteResponseWithParsingError()4038     public void testDeleteIkeLocalDeleteResponseWithParsingError() throws Exception {
4039         setupIdleStateMachine();
4040 
4041         mIkeSessionStateMachine.sendMessage(
4042                 IkeSessionStateMachine.CMD_EXECUTE_LOCAL_REQ,
4043                 new IkeLocalRequest(IkeSessionStateMachine.CMD_LOCAL_REQUEST_DELETE_IKE));
4044         mLooper.dispatchAll();
4045         verifyRetransmissionStarted();
4046         resetMockIkeMessageHelper();
4047 
4048         // Mock receiving response with syntax error
4049         ReceivedIkePacket mockInvalidPacket =
4050                 makeDummyReceivedIkePacketWithInvalidSyntax(
4051                         mSpyCurrentIkeSaRecord,
4052                         true /*isResp*/,
4053                         IkeHeader.EXCHANGE_TYPE_INFORMATIONAL);
4054         mIkeSessionStateMachine.sendMessage(CMD_RECEIVE_IKE_PACKET, mockInvalidPacket);
4055         mLooper.dispatchAll();
4056 
4057         // Verify no more request out
4058         verifyEncryptAndEncodeNeverCalled(mSpyCurrentIkeSaRecord);
4059 
4060         // Verify state machine quit properly
4061         verify(mMockIkeSessionCallback).onClosedExceptionally(any(InvalidSyntaxException.class));
4062         assertNull(mIkeSessionStateMachine.getCurrentState());
4063     }
4064 
4065     @Test
testDeleteIkeLocalDeleteHandlesInvalidResp()4066     public void testDeleteIkeLocalDeleteHandlesInvalidResp() throws Exception {
4067         setupIdleStateMachine();
4068 
4069         // Send delete request
4070         mIkeSessionStateMachine.sendMessage(
4071                 IkeSessionStateMachine.CMD_EXECUTE_LOCAL_REQ,
4072                 new IkeLocalRequest(IkeSessionStateMachine.CMD_LOCAL_REQUEST_DELETE_IKE));
4073         mLooper.dispatchAll();
4074 
4075         // Receive response with wrong exchange type
4076         ReceivedIkePacket resp =
4077                 makeDummyReceivedIkePacketWithInvalidSyntax(
4078                         mSpyCurrentIkeSaRecord,
4079                         true /*isResp*/,
4080                         IkeHeader.EXCHANGE_TYPE_CREATE_CHILD_SA);
4081         mIkeSessionStateMachine.sendMessage(CMD_RECEIVE_IKE_PACKET, resp);
4082         mLooper.dispatchAll();
4083 
4084         // Verify state machine quit properly
4085         verify(mMockIkeSessionCallback).onClosedExceptionally(any(InvalidSyntaxException.class));
4086         assertNull(mIkeSessionStateMachine.getCurrentState());
4087     }
4088 
4089     @Test
testDeleteIkeLocalDeleteReceivedNonDeleteRequest()4090     public void testDeleteIkeLocalDeleteReceivedNonDeleteRequest() throws Exception {
4091         setupIdleStateMachine();
4092 
4093         mIkeSessionStateMachine.sendMessage(
4094                 IkeSessionStateMachine.CMD_EXECUTE_LOCAL_REQ,
4095                 new IkeLocalRequest(IkeSessionStateMachine.CMD_LOCAL_REQUEST_DELETE_IKE));
4096         mLooper.dispatchAll();
4097         verifyRetransmissionStarted();
4098 
4099         // Verify delete sent out.
4100         verifyEncryptAndEncodeAndGetMessage(mSpyCurrentIkeSaRecord);
4101 
4102         resetMockIkeMessageHelper(); // Discard value.
4103 
4104         ReceivedIkePacket received = makeRekeyIkeRequest();
4105         mIkeSessionStateMachine.sendMessage(
4106                 IkeSessionStateMachine.CMD_RECEIVE_IKE_PACKET, received);
4107 
4108         mLooper.dispatchAll();
4109         verifyRetransmissionStarted();
4110         verifyIncrementRemoteReqMsgId();
4111 
4112         verifySendTempFailResponse();
4113     }
4114 
verifySendTempFailResponse()4115     private void verifySendTempFailResponse() {
4116         IkeMessage resp = verifyEncryptAndEncodeAndGetMessage(mSpyCurrentIkeSaRecord);
4117 
4118         IkeHeader ikeHeader = resp.ikeHeader;
4119         assertEquals(IkePayload.PAYLOAD_TYPE_SK, ikeHeader.nextPayloadType);
4120         assertEquals(IkeHeader.EXCHANGE_TYPE_INFORMATIONAL, ikeHeader.exchangeType);
4121         assertTrue(ikeHeader.isResponseMsg);
4122         assertEquals(mSpyCurrentIkeSaRecord.isLocalInit, ikeHeader.fromIkeInitiator);
4123 
4124         List<IkeNotifyPayload> notificationPayloadList =
4125                 resp.getPayloadListForType(IkePayload.PAYLOAD_TYPE_NOTIFY, IkeNotifyPayload.class);
4126         assertEquals(1, notificationPayloadList.size());
4127 
4128         IkeNotifyPayload notifyPayload = notificationPayloadList.get(0);
4129         assertEquals(IkeProtocolException.ERROR_TYPE_TEMPORARY_FAILURE, notifyPayload.notifyType);
4130     }
4131 
4132     @Test
testDeleteIkeRemoteDelete()4133     public void testDeleteIkeRemoteDelete() throws Exception {
4134         setupIdleStateMachine();
4135         mIkeSessionStateMachine.sendMessage(
4136                 IkeSessionStateMachine.CMD_RECEIVE_IKE_PACKET,
4137                 makeDeleteIkeRequest(mSpyCurrentIkeSaRecord));
4138 
4139         mLooper.dispatchAll();
4140         verifyIncrementRemoteReqMsgId();
4141 
4142         // Verify outbound message
4143         IkeMessage delMsg = verifyEncryptAndEncodeAndGetMessage(mSpyCurrentIkeSaRecord);
4144 
4145         IkeHeader ikeHeader = delMsg.ikeHeader;
4146         assertEquals(IkePayload.PAYLOAD_TYPE_SK, ikeHeader.nextPayloadType);
4147         assertEquals(IkeHeader.EXCHANGE_TYPE_INFORMATIONAL, ikeHeader.exchangeType);
4148         assertTrue(ikeHeader.isResponseMsg);
4149         assertEquals(mSpyCurrentIkeSaRecord.isLocalInit, ikeHeader.fromIkeInitiator);
4150 
4151         assertTrue(delMsg.ikePayloadList.isEmpty());
4152 
4153         verifyNotifyUserCloseSession();
4154 
4155         // Verify state machine quit properly
4156         assertNull(mIkeSessionStateMachine.getCurrentState());
4157     }
4158 
4159     @Test
testKillSessionDeleteIkeRequestSent()4160     public void testKillSessionDeleteIkeRequestSent() throws Exception {
4161         setupIdleStateMachine();
4162 
4163         mIkeSessionStateMachine.killSession();
4164         mLooper.dispatchAll();
4165 
4166         verify(mSpyCurrentIkeSaRecord).close();
4167         verify(mSpyCurrentIkeSocket).unregisterIke(mSpyCurrentIkeSaRecord.getInitiatorSpi());
4168         verifyNotifyUserCloseSession();
4169 
4170         // Verify outbound request
4171         IkeMessage req = verifyEncryptAndEncodeAndGetMessage(mSpyCurrentIkeSaRecord);
4172         IkeHeader ikeHeader = req.ikeHeader;
4173         assertEquals(IkePayload.PAYLOAD_TYPE_SK, ikeHeader.nextPayloadType);
4174         assertEquals(IkeHeader.EXCHANGE_TYPE_INFORMATIONAL, ikeHeader.exchangeType);
4175         assertFalse(ikeHeader.isResponseMsg);
4176         assertEquals(1, req.ikePayloadList.size());
4177         assertEquals(IkePayload.PAYLOAD_TYPE_DELETE, req.ikePayloadList.get(0).payloadType);
4178 
4179         // Verify state machine quit properly
4180         assertNull(mIkeSessionStateMachine.getCurrentState());
4181         verify(mMockBusyWakelock).release();
4182     }
4183 
4184     @Test
testKillSessionNoDeleteIkeRequestSent()4185     public void testKillSessionNoDeleteIkeRequestSent() throws Exception {
4186         setupIdleStateMachine();
4187 
4188         // Transition to state that does not send IKE delete requests
4189         mIkeSessionStateMachine.sendMessage(
4190                 IkeSessionStateMachine.CMD_FORCE_TRANSITION,
4191                 mIkeSessionStateMachine.mCreateIkeLocalIkeInit);
4192 
4193         mIkeSessionStateMachine.killSession();
4194         mLooper.dispatchAll();
4195 
4196         verify(mSpyCurrentIkeSaRecord).close();
4197         verify(mSpyCurrentIkeSocket).unregisterIke(mSpyCurrentIkeSaRecord.getInitiatorSpi());
4198         verifyNotifyUserCloseSession();
4199 
4200         // Verify no outbound request
4201         verifyEncryptAndEncodeNeverCalled();
4202 
4203         // Verify state machine quit properly
4204         assertNull(mIkeSessionStateMachine.getCurrentState());
4205         verify(mMockBusyWakelock).release();
4206     }
4207 
4208     @Test
testReceiveDpd()4209     public void testReceiveDpd() throws Exception {
4210         setupIdleStateMachine();
4211 
4212         // Receive a DPD request, expect to stay in IDLE state
4213         ReceivedIkePacket dummyDpdRequest = makeDpdIkeRequest(mSpyCurrentIkeSaRecord);
4214         mIkeSessionStateMachine.sendMessage(
4215                 IkeSessionStateMachine.CMD_RECEIVE_IKE_PACKET, dummyDpdRequest);
4216         mLooper.dispatchAll();
4217         assertTrue(
4218                 mIkeSessionStateMachine.getCurrentState() instanceof IkeSessionStateMachine.Idle);
4219 
4220         verifyDecodeEncryptedMessage(mSpyCurrentIkeSaRecord, dummyDpdRequest);
4221 
4222         // Verify outbound response
4223         IkeMessage resp = verifyEncryptAndEncodeAndGetMessage(mSpyCurrentIkeSaRecord);
4224         IkeHeader ikeHeader = resp.ikeHeader;
4225         assertEquals(IkePayload.PAYLOAD_TYPE_SK, ikeHeader.nextPayloadType);
4226         assertEquals(IkeHeader.EXCHANGE_TYPE_INFORMATIONAL, ikeHeader.exchangeType);
4227         assertTrue(ikeHeader.isResponseMsg);
4228         assertEquals(mSpyCurrentIkeSaRecord.isLocalInit, ikeHeader.fromIkeInitiator);
4229         assertTrue(resp.ikePayloadList.isEmpty());
4230     }
4231 
4232     @Test
testReceiveDpdNonIdle()4233     public void testReceiveDpdNonIdle() throws Exception {
4234         setupIdleStateMachine();
4235 
4236         // Move to a non-idle state. Use RekeyIkeRemoteDelete, as it doesn't send out any requests.
4237         mIkeSessionStateMachine.sendMessage(
4238                 IkeSessionStateMachine.CMD_FORCE_TRANSITION,
4239                 mIkeSessionStateMachine.mRekeyIkeRemoteDelete);
4240         mLooper.dispatchAll();
4241 
4242         // In a rekey state, receiving (and handling) a DPD should not result in a change of states
4243         ReceivedIkePacket dummyDpdRequest = makeDpdIkeRequest(mSpyCurrentIkeSaRecord);
4244         mIkeSessionStateMachine.sendMessage(
4245                 IkeSessionStateMachine.CMD_RECEIVE_IKE_PACKET, dummyDpdRequest);
4246         mLooper.dispatchAll();
4247         assertTrue(
4248                 mIkeSessionStateMachine.getCurrentState()
4249                         instanceof IkeSessionStateMachine.RekeyIkeRemoteDelete);
4250 
4251         verifyDecodeEncryptedMessage(mSpyCurrentIkeSaRecord, dummyDpdRequest);
4252 
4253         // Verify outbound response
4254         IkeMessage resp = verifyEncryptAndEncodeAndGetMessage(mSpyCurrentIkeSaRecord);
4255         IkeHeader ikeHeader = resp.ikeHeader;
4256         assertEquals(IkePayload.PAYLOAD_TYPE_SK, ikeHeader.nextPayloadType);
4257         assertEquals(IkeHeader.EXCHANGE_TYPE_INFORMATIONAL, ikeHeader.exchangeType);
4258         assertTrue(ikeHeader.isResponseMsg);
4259         assertEquals(mSpyCurrentIkeSaRecord.isLocalInit, ikeHeader.fromIkeInitiator);
4260         assertTrue(resp.ikePayloadList.isEmpty());
4261     }
4262 
executeAndVerifySendLocalDPD()4263     private void executeAndVerifySendLocalDPD() throws Exception {
4264         setupIdleStateMachine();
4265 
4266         mIkeSessionStateMachine.sendMessage(
4267                 CMD_FORCE_TRANSITION, mIkeSessionStateMachine.mDpdIkeLocalInfo);
4268         mLooper.dispatchAll();
4269 
4270         verifyEmptyInformationalSent(1, false /* expectedResp*/);
4271         resetMockIkeMessageHelper();
4272     }
4273 
4274     @Test
testDpdIkeLocalInfoRcvDpdReq()4275     public void testDpdIkeLocalInfoRcvDpdReq() throws Exception {
4276         executeAndVerifySendLocalDPD();
4277         mIkeSessionStateMachine.sendMessage(
4278                 CMD_RECEIVE_IKE_PACKET, makeDpdIkeRequest(mSpyCurrentIkeSaRecord));
4279         mLooper.dispatchAll();
4280 
4281         verifyEmptyInformationalSent(1, true /* expectedResp*/);
4282         assertTrue(
4283                 mIkeSessionStateMachine.getCurrentState()
4284                         instanceof IkeSessionStateMachine.DpdIkeLocalInfo);
4285     }
4286 
4287     @Test
testDpdIkeLocalInfoRcvDeleteIkeReq()4288     public void testDpdIkeLocalInfoRcvDeleteIkeReq() throws Exception {
4289         executeAndVerifySendLocalDPD();
4290         mIkeSessionStateMachine.sendMessage(
4291                 CMD_RECEIVE_IKE_PACKET, makeDeleteIkeRequest(mSpyCurrentIkeSaRecord));
4292         mLooper.dispatchAll();
4293 
4294         verifyEmptyInformationalSent(1, true /* expectedResp*/);
4295         assertNull(mIkeSessionStateMachine.getCurrentState());
4296     }
4297 
4298     @Test
testDpdIkeLocalInfoRcvRekeyIkeReq()4299     public void testDpdIkeLocalInfoRcvRekeyIkeReq() throws Exception {
4300         executeAndVerifySendLocalDPD();
4301         mIkeSessionStateMachine.sendMessage(CMD_RECEIVE_IKE_PACKET, makeRekeyIkeRequest());
4302         mLooper.dispatchAll();
4303 
4304         verifySendTempFailResponse();
4305         assertTrue(
4306                 mIkeSessionStateMachine.getCurrentState()
4307                         instanceof IkeSessionStateMachine.DpdIkeLocalInfo);
4308     }
4309 
4310     @Test
testIdleTriggersNewRequests()4311     public void testIdleTriggersNewRequests() throws Exception {
4312         setupIdleStateMachine();
4313 
4314         mIkeSessionStateMachine.sendMessage(
4315                 IkeSessionStateMachine.CMD_EXECUTE_LOCAL_REQ,
4316                 new IkeLocalRequest(IkeSessionStateMachine.CMD_LOCAL_REQUEST_REKEY_IKE));
4317         mLooper.dispatchAll();
4318 
4319         // Verify that the command is executed, and the state machine transitions to the right state
4320         assertTrue(
4321                 mIkeSessionStateMachine.getCurrentState()
4322                         instanceof IkeSessionStateMachine.RekeyIkeLocalCreate);
4323         verifyRetransmissionStarted();
4324     }
4325 
4326     @Test
testNonIdleStateDoesNotTriggerNewRequests()4327     public void testNonIdleStateDoesNotTriggerNewRequests() throws Exception {
4328         setupIdleStateMachine();
4329 
4330         // Force ourselves into a non-idle state
4331         mIkeSessionStateMachine.sendMessage(
4332                 IkeSessionStateMachine.CMD_FORCE_TRANSITION, mIkeSessionStateMachine.mReceiving);
4333         mLooper.dispatchAll();
4334         verifyEncryptAndEncodeNeverCalled();
4335 
4336         // Queue a local request, and expect that it is not run (yet)
4337         mIkeSessionStateMachine.sendMessage(
4338                 IkeSessionStateMachine.CMD_LOCAL_REQUEST_REKEY_IKE,
4339                 new IkeLocalRequest(IkeSessionStateMachine.CMD_LOCAL_REQUEST_REKEY_IKE));
4340         mLooper.dispatchAll();
4341 
4342         // Verify that the state machine is still in the Receiving state
4343         verifyEncryptAndEncodeNeverCalled();
4344         assertTrue(
4345                 mIkeSessionStateMachine.getCurrentState()
4346                         instanceof IkeSessionStateMachine.Receiving);
4347 
4348         // Go back to Idle, and expect to immediately transition to RekeyIkeLocalCreate from the
4349         // queued request
4350         mIkeSessionStateMachine.sendMessage(
4351                 IkeSessionStateMachine.CMD_FORCE_TRANSITION, mIkeSessionStateMachine.mIdle);
4352         mLooper.dispatchAll();
4353         assertTrue(
4354                 mIkeSessionStateMachine.getCurrentState()
4355                         instanceof IkeSessionStateMachine.RekeyIkeLocalCreate);
4356         verifyEncryptAndEncodeAndGetMessage(mSpyCurrentIkeSaRecord);
4357     }
4358 
4359     @Test
testOpenChildSessionValidatesArgs()4360     public void testOpenChildSessionValidatesArgs() throws Exception {
4361         setupIdleStateMachine();
4362 
4363         // Expect failure - no callbacks provided
4364         try {
4365             mIkeSessionStateMachine.openChildSession(mChildSessionParams, null);
4366         } catch (IllegalArgumentException expected) {
4367         }
4368 
4369         // Expect failure - callbacks already registered
4370         try {
4371             mIkeSessionStateMachine.openChildSession(
4372                     mChildSessionParams, mMockChildSessionCallback);
4373         } catch (IllegalArgumentException expected) {
4374         }
4375     }
4376 
4377     @Test
testOpenChildSession()4378     public void testOpenChildSession() throws Exception {
4379         setupIdleStateMachine();
4380 
4381         ChildSessionCallback cb = mock(ChildSessionCallback.class);
4382         mIkeSessionStateMachine.openChildSession(mChildSessionParams, cb);
4383 
4384         // Test that inserting the same cb returns an error, even before the state
4385         // machine has a chance to process it.
4386         try {
4387             mIkeSessionStateMachine.openChildSession(mChildSessionParams, cb);
4388         } catch (IllegalArgumentException expected) {
4389         }
4390 
4391         verify(mMockChildSessionFactoryHelper)
4392                 .makeChildSessionStateMachine(
4393                         eq(mLooper.getLooper()),
4394                         eq(mSpyContext),
4395                         anyInt(),
4396                         any(AlarmManager.class),
4397                         any(RandomnessFactory.class),
4398                         any(IpSecSpiGenerator.class),
4399                         eq(mChildSessionParams),
4400                         eq(mSpyUserCbExecutor),
4401                         eq(cb),
4402                         any());
4403 
4404         // Verify state in IkeSessionStateMachine
4405         mLooper.dispatchAll();
4406         assertTrue(
4407                 mIkeSessionStateMachine.getCurrentState()
4408                         instanceof IkeSessionStateMachine.ChildProcedureOngoing);
4409 
4410         synchronized (mIkeSessionStateMachine.mChildCbToSessions) {
4411             assertTrue(mIkeSessionStateMachine.mChildCbToSessions.containsKey(cb));
4412         }
4413     }
4414 
4415     @Test
testCloseChildSessionValidatesArgs()4416     public void testCloseChildSessionValidatesArgs() throws Exception {
4417         setupIdleStateMachine();
4418 
4419         // Expect failure - callbacks not registered
4420         try {
4421             mIkeSessionStateMachine.closeChildSession(mock(ChildSessionCallback.class));
4422         } catch (IllegalArgumentException expected) {
4423         }
4424     }
4425 
4426     @Test
testCloseChildSession()4427     public void testCloseChildSession() throws Exception {
4428         setupIdleStateMachine();
4429 
4430         mIkeSessionStateMachine.closeChildSession(mMockChildSessionCallback);
4431         mLooper.dispatchAll();
4432 
4433         assertTrue(
4434                 mIkeSessionStateMachine.getCurrentState()
4435                         instanceof IkeSessionStateMachine.ChildProcedureOngoing);
4436     }
4437 
4438     @Test
testCloseImmediatelyAfterOpenChildSession()4439     public void testCloseImmediatelyAfterOpenChildSession() throws Exception {
4440         setupIdleStateMachine();
4441 
4442         ChildSessionCallback cb = mock(ChildSessionCallback.class);
4443         mIkeSessionStateMachine.openChildSession(mChildSessionParams, cb);
4444 
4445         // Verify that closing the session immediately still picks up the child callback
4446         // even before the looper has a chance to run.
4447         mIkeSessionStateMachine.closeChildSession(mMockChildSessionCallback);
4448     }
4449 
4450     @Test
testOnChildSessionClosed()4451     public void testOnChildSessionClosed() throws Exception {
4452         setupIdleStateMachine();
4453 
4454         mDummyChildSmCallback.onChildSessionClosed(mMockChildSessionCallback);
4455 
4456         synchronized (mIkeSessionStateMachine.mChildCbToSessions) {
4457             assertFalse(
4458                     mIkeSessionStateMachine.mChildCbToSessions.containsKey(
4459                             mMockChildSessionCallback));
4460         }
4461     }
4462 
4463     @Test
testHandleUnexpectedExceptionInEnterState()4464     public void testHandleUnexpectedExceptionInEnterState() throws Exception {
4465         Log spyIkeLog = TestUtils.makeSpyLogDoLogErrorForWtf(TAG);
4466         IkeManager.setIkeLog(spyIkeLog);
4467 
4468         IkeSessionParams mockSessionParams = mock(IkeSessionParams.class);
4469         when(mockSessionParams.getSaProposalsInternal()).thenThrow(mock(RuntimeException.class));
4470 
4471         DhGroupTransform dhGroupTransform = new DhGroupTransform(SaProposal.DH_GROUP_2048_BIT_MODP);
4472         IkeSaProposal mockSaProposal = mock(IkeSaProposal.class);
4473         when(mockSaProposal.getDhGroupTransforms())
4474                 .thenReturn(new DhGroupTransform[] {dhGroupTransform});
4475         when(mockSessionParams.getSaProposals()).thenReturn(Arrays.asList(mockSaProposal));
4476         IkeSessionStateMachine ikeSession =
4477                 new IkeSessionStateMachine(
4478                         mLooper.getLooper(),
4479                         mSpyContext,
4480                         mIpSecManager,
4481                         mockSessionParams,
4482                         mChildSessionParams,
4483                         mSpyUserCbExecutor,
4484                         mMockIkeSessionCallback,
4485                         mMockChildSessionCallback,
4486                         mMockEapAuthenticatorFactory);
4487         // Send IKE INIT request
4488         mIkeSessionStateMachine.sendMessage(IkeSessionStateMachine.CMD_LOCAL_REQUEST_CREATE_IKE);
4489         mLooper.dispatchAll();
4490 
4491         assertNull(ikeSession.getCurrentState());
4492         verify(mSpyUserCbExecutor).execute(any(Runnable.class));
4493         verify(mMockIkeSessionCallback).onClosedExceptionally(any(IkeInternalException.class));
4494         verify(spyIkeLog).wtf(anyString(), anyString(), any(RuntimeException.class));
4495     }
4496 
4497     @Test
testHandleUnexpectedExceptionInProcessStateMsg()4498     public void testHandleUnexpectedExceptionInProcessStateMsg() throws Exception {
4499         Log spyIkeLog = TestUtils.makeSpyLogDoLogErrorForWtf(TAG);
4500         IkeManager.setIkeLog(spyIkeLog);
4501 
4502         setupIdleStateMachine();
4503         mIkeSessionStateMachine.sendMessage(
4504                 IkeSessionStateMachine.CMD_RECEIVE_IKE_PACKET, null /*receivedIkePacket*/);
4505         mLooper.dispatchAll();
4506 
4507         assertNull(mIkeSessionStateMachine.getCurrentState());
4508         verify(mSpyUserCbExecutor).execute(any(Runnable.class));
4509         verify(mMockIkeSessionCallback).onClosedExceptionally(any(IkeInternalException.class));
4510         verify(spyIkeLog).wtf(anyString(), anyString(), any(RuntimeException.class));
4511     }
4512 
4513     @Test
testCreateIkeLocalIkeInitRcvErrorNotify()4514     public void testCreateIkeLocalIkeInitRcvErrorNotify() throws Exception {
4515         // Send IKE INIT request
4516         mIkeSessionStateMachine.sendMessage(IkeSessionStateMachine.CMD_LOCAL_REQUEST_CREATE_IKE);
4517         mLooper.dispatchAll();
4518         verifyRetransmissionStarted();
4519 
4520         // Receive IKE INIT response with erro notification.
4521         List<IkePayload> payloads = new LinkedList<>();
4522         payloads.add(new IkeNotifyPayload(IkeProtocolException.ERROR_TYPE_NO_PROPOSAL_CHOSEN));
4523         ReceivedIkePacket resp =
4524                 makeDummyUnencryptedReceivedIkePacket(
4525                         1L /*initiator SPI*/,
4526                         2L /*respodner SPI*/,
4527                         IkeHeader.EXCHANGE_TYPE_IKE_SA_INIT,
4528                         true /*isResp*/,
4529                         false /*fromIkeInit*/,
4530                         payloads);
4531 
4532         mIkeSessionStateMachine.sendMessage(IkeSessionStateMachine.CMD_RECEIVE_IKE_PACKET, resp);
4533         mLooper.dispatchAll();
4534 
4535         // Fires user error callbacks
4536         verify(mMockIkeSessionCallback)
4537                 .onClosedExceptionally(
4538                         argThat(err -> err instanceof NoValidProposalChosenException));
4539         // Verify state machine quit properly
4540         assertNull(mIkeSessionStateMachine.getCurrentState());
4541     }
4542 
mockSendRekeyChildReq()4543     private void mockSendRekeyChildReq() throws Exception {
4544         setupIdleStateMachine();
4545 
4546         ChildLocalRequest childLocalRequest =
4547                 new ChildLocalRequest(
4548                         IkeSessionStateMachine.CMD_LOCAL_REQUEST_REKEY_CHILD,
4549                         mMockChildSessionCallback,
4550                         null /*childParams*/);
4551 
4552         mIkeSessionStateMachine.sendMessage(
4553                 IkeSessionStateMachine.CMD_EXECUTE_LOCAL_REQ, childLocalRequest);
4554         mLooper.dispatchAll();
4555 
4556         assertTrue(
4557                 mIkeSessionStateMachine.getCurrentState()
4558                         instanceof IkeSessionStateMachine.ChildProcedureOngoing);
4559         verify(mMockChildSessionStateMachine).rekeyChildSession();
4560 
4561         // Mocking sending request
4562         mDummyChildSmCallback.onOutboundPayloadsReady(
4563                 IkeHeader.EXCHANGE_TYPE_CREATE_CHILD_SA,
4564                 false /*isResp*/,
4565                 new LinkedList<>(),
4566                 mMockChildSessionStateMachine);
4567         mLooper.dispatchAll();
4568     }
4569 
mockRcvTempFail()4570     private void mockRcvTempFail() throws Exception {
4571         ReceivedIkePacket resp =
4572                 makeResponseWithErrorNotify(new IkeNotifyPayload(ERROR_TYPE_TEMPORARY_FAILURE));
4573 
4574         mIkeSessionStateMachine.sendMessage(IkeSessionStateMachine.CMD_RECEIVE_IKE_PACKET, resp);
4575         mIkeSessionStateMachine.sendMessage(
4576                 IkeSessionStateMachine.CMD_FORCE_TRANSITION, mIkeSessionStateMachine.mIdle);
4577         mLooper.dispatchAll();
4578     }
4579 
4580     @Ignore
disableTestTempFailureHandlerTimeout()4581     public void disableTestTempFailureHandlerTimeout() throws Exception {
4582         long currentTime = 0;
4583         int retryCnt = 0;
4584 
4585         mockSendRekeyChildReq();
4586 
4587         while (currentTime + RETRY_INTERVAL_MS < TEMP_FAILURE_RETRY_TIMEOUT_MS) {
4588             mockRcvTempFail();
4589 
4590             mLooper.moveTimeForward(RETRY_INTERVAL_MS);
4591             currentTime += RETRY_INTERVAL_MS;
4592             mLooper.dispatchAll();
4593 
4594             retryCnt++;
4595             verify(mMockChildSessionStateMachine, times(1 + retryCnt)).rekeyChildSession();
4596         }
4597 
4598         mLooper.moveTimeForward(RETRY_INTERVAL_MS);
4599         mLooper.dispatchAll();
4600 
4601         assertNull(mIkeSessionStateMachine.getCurrentState());
4602         verify(mMockIkeSessionCallback).onClosedExceptionally(any(IkeInternalException.class));
4603     }
4604 
4605     @Test
testTempFailureHandlerCancelTimer()4606     public void testTempFailureHandlerCancelTimer() throws Exception {
4607         mockRescheduleRekey(mSpyCurrentIkeSaRecord);
4608         setupIdleStateMachine();
4609 
4610         // Send Rekey-Create request
4611         mIkeSessionStateMachine.sendMessage(
4612                 IkeSessionStateMachine.CMD_EXECUTE_LOCAL_REQ,
4613                 new IkeLocalRequest(IkeSessionStateMachine.CMD_LOCAL_REQUEST_REKEY_IKE));
4614         mLooper.dispatchAll();
4615         verifyRetransmissionStarted();
4616 
4617         // Mock sending TEMPORARY_FAILURE response
4618         mockRcvTempFail();
4619         mLooper.dispatchAll();
4620         verify(mSpyCurrentIkeSaRecord).rescheduleRekey(eq(RETRY_INTERVAL_MS));
4621         assertTrue(
4622                 mIkeSessionStateMachine.getCurrentState() instanceof IkeSessionStateMachine.Idle);
4623 
4624         // Move time forward to trigger retry
4625         mLooper.moveTimeForward(IkeSessionStateMachine.RETRY_INTERVAL_MS);
4626         mLooper.dispatchAll();
4627         assertTrue(
4628                 mIkeSessionStateMachine.getCurrentState()
4629                         instanceof IkeSessionStateMachine.RekeyIkeLocalCreate);
4630 
4631         // Prepare "rekeyed" SA
4632         setupRekeyedIkeSa(mSpyLocalInitIkeSaRecord);
4633 
4634         // Receive valid Rekey-Create response
4635         ReceivedIkePacket dummyRekeyIkeRespReceivedPacket = makeRekeyIkeResponse();
4636         mIkeSessionStateMachine.sendMessage(
4637                 IkeSessionStateMachine.CMD_RECEIVE_IKE_PACKET, dummyRekeyIkeRespReceivedPacket);
4638         mLooper.dispatchAll();
4639 
4640         // Receive Delete response
4641         ReceivedIkePacket dummyDeleteIkeRespReceivedPacket =
4642                 makeDeleteIkeResponse(mSpyCurrentIkeSaRecord);
4643         mIkeSessionStateMachine.sendMessage(
4644                 IkeSessionStateMachine.CMD_RECEIVE_IKE_PACKET, dummyDeleteIkeRespReceivedPacket);
4645         mLooper.dispatchAll();
4646         assertTrue(
4647                 mIkeSessionStateMachine.getCurrentState() instanceof IkeSessionStateMachine.Idle);
4648 
4649         // Move time forward
4650         mLooper.moveTimeForward(IkeSessionStateMachine.TEMP_FAILURE_RETRY_TIMEOUT_MS);
4651         mLooper.dispatchAll();
4652 
4653         // Validate IKE Session is not closed
4654         assertTrue(
4655                 mIkeSessionStateMachine.getCurrentState() instanceof IkeSessionStateMachine.Idle);
4656     }
4657 
4658     @Ignore
disableTestIdleReceiveRequestWithFatalError()4659     public void disableTestIdleReceiveRequestWithFatalError() throws Exception {
4660         setupIdleStateMachine();
4661 
4662         // Mock receiving packet with syntax error
4663         ReceivedIkePacket mockInvalidPacket =
4664                 makeDummyReceivedIkePacketWithInvalidSyntax(
4665                         mSpyCurrentIkeSaRecord,
4666                         false /*isResp*/,
4667                         IkeHeader.EXCHANGE_TYPE_CREATE_CHILD_SA);
4668         mIkeSessionStateMachine.sendMessage(CMD_RECEIVE_IKE_PACKET, mockInvalidPacket);
4669         mLooper.dispatchAll();
4670 
4671         // Verify Delete request was sent
4672         List<IkePayload> payloads = verifyOutInfoMsgHeaderAndGetPayloads(true /*isResp*/);
4673         assertEquals(1, payloads.size());
4674 
4675         IkePayload payload = payloads.get(0);
4676         assertEquals(IkePayload.PAYLOAD_TYPE_NOTIFY, payload.payloadType);
4677         assertEquals(ERROR_TYPE_INVALID_SYNTAX, ((IkeNotifyPayload) payload).notifyType);
4678 
4679         // Verify IKE Session is closed properly
4680         assertNull(mIkeSessionStateMachine.getCurrentState());
4681         verify(mMockIkeSessionCallback).onClosedExceptionally(any(InvalidSyntaxException.class));
4682     }
4683 
4684     @Test
testHandlesInvalidRequest()4685     public void testHandlesInvalidRequest() throws Exception {
4686         setupIdleStateMachine();
4687 
4688         mIkeSessionStateMachine.sendMessage(
4689                 IkeSessionStateMachine.CMD_FORCE_TRANSITION,
4690                 mIkeSessionStateMachine.mChildProcedureOngoing);
4691 
4692         // Receive an IKE AUTH request
4693         ReceivedIkePacket request =
4694                 makeDummyEncryptedReceivedIkePacketWithPayloadList(
4695                         mSpyCurrentIkeSaRecord,
4696                         IkeHeader.EXCHANGE_TYPE_IKE_AUTH,
4697                         false /*isResp*/,
4698                         new LinkedList<IkePayload>());
4699         mIkeSessionStateMachine.sendMessage(IkeSessionStateMachine.CMD_RECEIVE_IKE_PACKET, request);
4700         mLooper.dispatchAll();
4701 
4702         // Verify error notification was sent
4703         List<IkePayload> ikePayloadList = verifyOutInfoMsgHeaderAndGetPayloads(true /*isResp*/);
4704         assertEquals(1, ikePayloadList.size());
4705         assertEquals(
4706                 ERROR_TYPE_INVALID_SYNTAX, ((IkeNotifyPayload) ikePayloadList.get(0)).notifyType);
4707 
4708         // Verify IKE Session has quit
4709         assertNull(mIkeSessionStateMachine.getCurrentState());
4710         verify(mMockIkeSessionCallback).onClosedExceptionally(any(InvalidSyntaxException.class));
4711     }
4712 
4713     @Test
testIdleHandlesDecryptPacketFailed()4714     public void testIdleHandlesDecryptPacketFailed() throws Exception {
4715         setupIdleStateMachine();
4716 
4717         ReceivedIkePacket packet =
4718                 makeDummyReceivedIkePacketWithUnprotectedError(
4719                         mSpyCurrentIkeSaRecord,
4720                         false /*isResp*/,
4721                         EXCHANGE_TYPE_INFORMATIONAL,
4722                         mock(IkeException.class));
4723         mIkeSessionStateMachine.sendMessage(IkeSessionStateMachine.CMD_RECEIVE_IKE_PACKET, packet);
4724         mLooper.dispatchAll();
4725 
4726         assertTrue(
4727                 mIkeSessionStateMachine.getCurrentState() instanceof IkeSessionStateMachine.Idle);
4728     }
4729 
4730     @Test
testHandlesUnencryptedPacket()4731     public void testHandlesUnencryptedPacket() throws Exception {
4732         setupIdleStateMachine();
4733         IkeMessage.setIkeMessageHelper(new IkeMessageHelper());
4734 
4735         ReceivedIkePacket packet =
4736                 makeDummyUnencryptedReceivedIkePacket(
4737                         mSpyCurrentIkeSaRecord.getLocalSpi(),
4738                         mSpyCurrentIkeSaRecord.getRemoteSpi(),
4739                         IkeHeader.EXCHANGE_TYPE_INFORMATIONAL,
4740                         false /*isResp*/,
4741                         false /*fromIkeInit*/,
4742                         new LinkedList<>());
4743 
4744         mIkeSessionStateMachine.sendMessage(IkeSessionStateMachine.CMD_RECEIVE_IKE_PACKET, packet);
4745         mLooper.dispatchAll();
4746 
4747         assertTrue(
4748                 mIkeSessionStateMachine.getCurrentState() instanceof IkeSessionStateMachine.Idle);
4749 
4750         // Reset the IkeMessageHelper to be a mock. This is needed for #killSession (called in
4751         // #tearDown), which attempts to notify the remote about the IKE session dying in the Idle
4752         // state.
4753         IkeMessage.setIkeMessageHelper(mMockIkeMessageHelper);
4754         resetMockIkeMessageHelper();
4755     }
4756 
4757     @Test
testEapOnlyOption()4758     public void testEapOnlyOption() throws Exception {
4759         mIkeSessionStateMachine.quitNow();
4760         IkeSessionParams ikeSessionParams =
4761                 buildIkeSessionParamsCommon()
4762                         .setAuthEap(mRootCertificate, mEapSessionConfig)
4763                         .addIkeOption(IKE_OPTION_EAP_ONLY_AUTH)
4764                         .build();
4765         mIkeSessionStateMachine = makeAndStartIkeSession(ikeSessionParams);
4766 
4767         mockIkeInitAndTransitionToIkeAuth(mIkeSessionStateMachine.mCreateIkeLocalIkeAuth);
4768 
4769         IkeMessage ikeAuthReqMessage = verifyAuthReqAndGetMsg();
4770         List<IkeNotifyPayload> notifyPayloads =
4771                 ikeAuthReqMessage.getPayloadListForType(
4772                         IkePayload.PAYLOAD_TYPE_NOTIFY, IkeNotifyPayload.class);
4773         assertTrue(hasEapOnlyNotifyPayload(notifyPayloads));
4774     }
4775 
makeConfigPayload()4776     private IkeConfigPayload makeConfigPayload() throws Exception {
4777         return (IkeConfigPayload)
4778                 IkeTestUtils.hexStringToIkePayload(
4779                         IkePayload.PAYLOAD_TYPE_CP, true /*isResp*/, CP_PAYLOAD_HEX_STRING);
4780     }
4781 
hasEapOnlyNotifyPayload(List<IkeNotifyPayload> notifyPayloads)4782     private boolean hasEapOnlyNotifyPayload(List<IkeNotifyPayload> notifyPayloads) {
4783         for (IkeNotifyPayload payload : notifyPayloads) {
4784             if (payload.notifyType == NOTIFY_TYPE_EAP_ONLY_AUTHENTICATION) {
4785                 return true;
4786             }
4787         }
4788 
4789         return false;
4790     }
4791 
4792     @Test
testAcquireAndReleaseLocalReqWakeLock()4793     public void testAcquireAndReleaseLocalReqWakeLock() throws Exception {
4794         setupIdleStateMachine();
4795 
4796         ChildSessionCallback cb = mock(ChildSessionCallback.class);
4797         mIkeSessionStateMachine.openChildSession(mChildSessionParams, cb);
4798 
4799         mLooper.dispatchAll();
4800         assertTrue(
4801                 mIkeSessionStateMachine.getCurrentState()
4802                         instanceof IkeSessionStateMachine.ChildProcedureOngoing);
4803         verify(mMockLocalRequestWakelock).acquire();
4804         verify(mMockLocalRequestWakelock).release();
4805     }
4806 
4807     @Test
testQuitClearAllLocalReqWakeLocks()4808     public void testQuitClearAllLocalReqWakeLocks() throws Exception {
4809         final int localReqCnt = 3;
4810         setupIdleStateMachine();
4811 
4812         // Leave a Idle state so that the LocalRequest won't be executed
4813         mIkeSessionStateMachine.sendMessage(
4814                 IkeSessionStateMachine.CMD_FORCE_TRANSITION, mIkeSessionStateMachine.mReceiving);
4815         mLooper.dispatchAll();
4816 
4817         // Only in test that all local requests will get the same WakeLock instance but in function
4818         // code each local request will have a separate WakeLock.
4819         for (int i = 0; i < localReqCnt; i++) {
4820             mIkeSessionStateMachine.openChildSession(
4821                     mChildSessionParams, mock(ChildSessionCallback.class));
4822         }
4823         mLooper.dispatchAll();
4824         verify(mMockLocalRequestWakelock, times(localReqCnt)).acquire();
4825 
4826         mIkeSessionStateMachine.killSession();
4827         mLooper.dispatchAll();
4828         verify(mMockLocalRequestWakelock, times(localReqCnt)).release();
4829     }
4830 }
4831