blob: 13f953a50d5d65264575283251f21a22e725c56d [file] [log] [blame]
/*
* Copyright (C) 2020 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package android.net.ipsec.ike.cts;
import static android.app.AppOpsManager.OP_MANAGE_IPSEC_TUNNELS;
import static android.net.ipsec.ike.exceptions.IkeProtocolException.ERROR_TYPE_AUTHENTICATION_FAILED;
import static android.net.ipsec.ike.exceptions.IkeProtocolException.ERROR_TYPE_NO_PROPOSAL_CHOSEN;
import static android.net.ipsec.ike.exceptions.IkeProtocolException.ERROR_TYPE_TS_UNACCEPTABLE;
import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;
import android.net.LinkAddress;
import android.net.ipsec.ike.ChildSessionParams;
import android.net.ipsec.ike.IkeFqdnIdentification;
import android.net.ipsec.ike.IkeSession;
import android.net.ipsec.ike.IkeSessionParams;
import android.net.ipsec.ike.exceptions.IkeProtocolException;
import android.platform.test.annotations.AppModeFull;
import androidx.test.ext.junit.runners.AndroidJUnit4;
import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.Test;
import org.junit.runner.RunWith;
import java.net.InetAddress;
import java.util.ArrayList;
import java.util.Arrays;
@RunWith(AndroidJUnit4.class)
@AppModeFull(reason = "MANAGE_IPSEC_TUNNELS permission can't be granted to instant apps")
public class IkeSessionPskTest extends IkeSessionTestBase {
// Test vectors for success workflow
private static final String SUCCESS_IKE_INIT_RESP =
"46B8ECA1E0D72A18B45427679F9245D421202220000000000000015022000030"
+ "0000002C010100040300000C0100000C800E0080030000080300000203000008"
+ "0200000200000008040000022800008800020000A7AA3435D088EC1A2B7C2A47"
+ "1FA1B85F1066C9B2006E7C353FB5B5FDBC2A88347ED2C6F5B7A265D03AE34039"
+ "6AAC0145CFCC93F8BDB219DDFF22A603B8856A5DC59B6FAB7F17C5660CF38670"
+ "8794FC72F273ADEB7A4F316519794AED6F8AB61F95DFB360FAF18C6C8CABE471"
+ "6E18FE215348C2E582171A57FC41146B16C4AFE429000024A634B61C0E5C90C6"
+ "8D8818B0955B125A9B1DF47BBD18775710792E651083105C2900001C00004004"
+ "406FA3C5685A16B9B72C7F2EEE9993462C619ABE2900001C00004005AF905A87"
+ "0A32222AA284A7070585601208A282F0290000080000402E290000100000402F"
+ "00020003000400050000000800004014";
private static final String SUCCESS_IKE_AUTH_RESP =
"46B8ECA1E0D72A18B45427679F9245D42E20232000000001000000EC240000D0"
+ "0D06D37198F3F0962DE8170D66F1A9008267F98CDD956D984BDCED2FC7FAF84A"
+ "A6664EF25049B46B93C9ED420488E0C172AA6635BF4011C49792EF2B88FE7190"
+ "E8859FEEF51724FD20C46E7B9A9C3DC4708EF7005707A18AB747C903ABCEAC5C"
+ "6ECF5A5FC13633DCE3844A920ED10EF202F115DBFBB5D6D2D7AB1F34EB08DE7C"
+ "A54DCE0A3A582753345CA2D05A0EFDB9DC61E81B2483B7D13EEE0A815D37252C"
+ "23D2F29E9C30658227D2BB0C9E1A481EAA80BC6BE9006BEDC13E925A755A0290"
+ "AEC4164D29997F52ED7DCC2E";
private static final String SUCCESS_CREATE_CHILD_RESP =
"46B8ECA1E0D72A18B45427679F9245D42E20242000000002000000CC210000B0"
+ "484565D4AF6546274674A8DE339E9C9584EE2326AB9260F41C4D0B6C5B02D1D"
+ "2E8394E3CDE3094895F2ACCABCDCA8E82960E5196E9622BD13745FC8D6A2BED"
+ "E561FF5D9975421BC463C959A3CBA3478256B6D278159D99B512DDF56AC1658"
+ "63C65A986F395FE8B1476124B91F83FD7865304EB95B22CA4DD9601DA7A2533"
+ "ABF4B36EB1B8CD09522F6A600032316C74E562E6756D9D49D945854E2ABDC4C"
+ "3AF36305353D60D40B58BE44ABF82";
private static final String SUCCESS_DELETE_CHILD_RESP =
"46B8ECA1E0D72A18B45427679F9245D42E202520000000030000004C2A000030"
+ "0C5CEB882DBCA65CE32F4C53909335F1365C91C555316C5E9D9FB553F7AA916"
+ "EF3A1D93460B7FABAF0B4B854";
private static final String SUCCESS_DELETE_IKE_RESP =
"46B8ECA1E0D72A18B45427679F9245D42E202520000000040000004C00000030"
+ "9352D71100777B00ABCC6BD7DBEA697827FFAAA48DF9A54D1D68161939F5DC8"
+ "6743A7CEB2BE34AC00095A5B8";
private IkeSession openIkeSessionWithTunnelModeChild(InetAddress remoteAddress) {
return openIkeSession(remoteAddress, buildTunnelModeChildSessionParams());
}
private IkeSession openIkeSessionWithTransportModeChild(InetAddress remoteAddress) {
return openIkeSession(remoteAddress, buildTransportModeChildParamsWithDefaultTs());
}
private IkeSession openIkeSession(InetAddress remoteAddress, ChildSessionParams childParams) {
IkeSessionParams ikeParams =
new IkeSessionParams.Builder(sContext)
.setNetwork(mTunNetwork)
.setServerHostname(remoteAddress.getHostAddress())
.addSaProposal(SaProposalTest.buildIkeSaProposalWithNormalModeCipher())
.addSaProposal(SaProposalTest.buildIkeSaProposalWithCombinedModeCipher())
.setLocalIdentification(new IkeFqdnIdentification(LOCAL_HOSTNAME))
.setRemoteIdentification(new IkeFqdnIdentification(REMOTE_HOSTNAME))
.setAuthPsk(IKE_PSK)
.build();
return new IkeSession(
sContext,
ikeParams,
childParams,
mUserCbExecutor,
mIkeSessionCallback,
mFirstChildSessionCallback);
}
@BeforeClass
public static void setUpTunnelPermissionBeforeClass() throws Exception {
// Under normal circumstances, the MANAGE_IPSEC_TUNNELS appop would be auto-granted, and
// a standard permission is insufficient. So we shell out the appop, to give us the
// right appop permissions.
setAppOp(OP_MANAGE_IPSEC_TUNNELS, true);
}
// This method is guaranteed to run in subclasses and will run after subclasses' @AfterClass
// methods.
@AfterClass
public static void tearDownTunnelPermissionAfterClass() throws Exception {
setAppOp(OP_MANAGE_IPSEC_TUNNELS, false);
}
@Test
public void testIkeSessionSetupAndChildSessionSetupWithTunnelMode() throws Exception {
if (!hasTunnelsFeature()) return;
// Open IKE Session
IkeSession ikeSession = openIkeSessionWithTunnelModeChild(mRemoteAddress);
performSetupIkeAndFirstChildBlocking(SUCCESS_IKE_INIT_RESP, SUCCESS_IKE_AUTH_RESP);
// IKE INIT and IKE AUTH takes two exchanges. Message ID starts from 2
int expectedMsgId = 2;
verifyIkeSessionSetupBlocking();
verifyChildSessionSetupBlocking(
mFirstChildSessionCallback,
Arrays.asList(TUNNEL_MODE_INBOUND_TS),
Arrays.asList(TUNNEL_MODE_OUTBOUND_TS),
Arrays.asList(EXPECTED_INTERNAL_LINK_ADDR));
IpSecTransformCallRecord firstTransformRecordA =
mFirstChildSessionCallback.awaitNextCreatedIpSecTransform();
IpSecTransformCallRecord firstTransformRecordB =
mFirstChildSessionCallback.awaitNextCreatedIpSecTransform();
verifyCreateIpSecTransformPair(firstTransformRecordA, firstTransformRecordB);
// Open additional Child Session
TestChildSessionCallback additionalChildCb = new TestChildSessionCallback();
ikeSession.openChildSession(buildTunnelModeChildSessionParams(), additionalChildCb);
mTunUtils.awaitReqAndInjectResp(
IKE_DETERMINISTIC_INITIATOR_SPI,
expectedMsgId++,
true /* expectedUseEncap */,
SUCCESS_CREATE_CHILD_RESP);
// Verify opening additional Child Session
verifyChildSessionSetupBlocking(
additionalChildCb,
Arrays.asList(TUNNEL_MODE_INBOUND_TS),
Arrays.asList(TUNNEL_MODE_OUTBOUND_TS),
new ArrayList<LinkAddress>());
IpSecTransformCallRecord additionalTransformRecordA =
additionalChildCb.awaitNextCreatedIpSecTransform();
IpSecTransformCallRecord additionalTransformRecordB =
additionalChildCb.awaitNextCreatedIpSecTransform();
verifyCreateIpSecTransformPair(additionalTransformRecordA, additionalTransformRecordB);
// Close additional Child Session
ikeSession.closeChildSession(additionalChildCb);
mTunUtils.awaitReqAndInjectResp(
IKE_DETERMINISTIC_INITIATOR_SPI,
expectedMsgId++,
true /* expectedUseEncap */,
SUCCESS_DELETE_CHILD_RESP);
verifyDeleteIpSecTransformPair(
additionalChildCb, additionalTransformRecordA, additionalTransformRecordB);
additionalChildCb.awaitOnClosed();
// Close IKE Session
ikeSession.close();
performCloseIkeBlocking(expectedMsgId++, SUCCESS_DELETE_IKE_RESP);
verifyCloseIkeAndChildBlocking(firstTransformRecordA, firstTransformRecordB);
}
@Test
public void testIkeSessionSetupAndChildSessionSetupWithTunnelModeV6() throws Exception {
if (!hasTunnelsFeature()) return;
final String ikeInitResp =
"46B8ECA1E0D72A186F7B6C2CEB77EB9021202220000000000000011822000030"
+ "0000002C010100040300000C0100000C800E0100030000080300000C03000008"
+ "0200000500000008040000022800008800020000DABAA04B38B491E2403F2125"
+ "96ECF1C8EF7B1DC19A422FDD46E1756C826BB3A16404361B775D9950577B5CDF"
+ "6AAA1642BD1427BDA8BC55354A97C1025E19C1E2EE2DF8A0C9406E545D829F52"
+ "75695008E3B742984B8DD1770F3514213B0DF3EE8B199416DF200D248115C057"
+ "1C193E4F96802E5EF48DD99CAC251882A8F7CCC329000024BC6F0F1D3653C2C7"
+ "679E02CDB6A3B32B2FEE9AF52F0326D4D9AE073D56CE8922290000080000402E"
+ "290000100000402F00020003000400050000000800004014";
final String ikeAuthResp =
"46B8ECA1E0D72A186F7B6C2CEB77EB902E202320000000010000015024000134"
+ "4D115AFDCDAD0310760BB664EB7D405A340869AD6EDF0AAEAD0663A9253DADCB"
+ "73EBE5CD29D4FA1CDEADE0B94391B5C4CF77BCC1596ACE3CE6A7891E44888FA5"
+ "46632C0EF4E6193C023C9DC59142C37D1C49D6EF5CD324EC6FC35C89E1721C78"
+ "91FDCDB723D8062709950F4AA9273D26A54C9C7E86862DBC15F7B6641D2B9BAD"
+ "E55069008201D12968D97B537B1518FE87B0FFA03C3EE6012C06721B1E2A3F68"
+ "92108BC4A4F7063F7F94562D8B60F291A1377A836CF12BCDA7E15C1A8F3C77BB"
+ "6DB7F2C833CCE4CDDED7506536621A3356CE2BC1874E7B1A1A9B447D7DF6AB09"
+ "638B8AD94A781B28BB91B514B611B24DF8E8A047A10AE27BBF15C754D3D2F792"
+ "D3E1CCADDAE934C98AE53A8FC3419C88AFF0355564F82A629C998012DA7BB704"
+ "5307270DF326377E3E1994476902035B";
final String deleteIkeResp =
"46B8ECA1E0D72A186F7B6C2CEB77EB902E202520000000020000005000000034"
+ "CF15C299F35688E5140A48B61C95F004121BF8236201415E5CD45BA41AAB16D4"
+ "90B44B9E6D5D92B5B97D24196A58C73F";
mLocalAddress = IPV6_ADDRESS_LOCAL;
mRemoteAddress = IPV6_ADDRESS_REMOTE;
// Teardown current test network that uses IPv4 address and set up new network with IPv6
// address.
tearDownTestNetwork();
setUpTestNetwork(mLocalAddress);
// Open IKE Session
IkeSession ikeSession = openIkeSessionWithTunnelModeChild(mRemoteAddress);
performSetupIkeAndFirstChildBlocking(
ikeInitResp,
1 /* expectedAuthReqPktCnt */,
false /* expectedAuthUseEncap */,
ikeAuthResp);
// Local request message ID starts from 2 because there is one IKE_INIT message and a single
// IKE_AUTH message.
int expectedMsgId = 2;
verifyIkeSessionSetupBlocking();
verifyChildSessionSetupBlocking(
mFirstChildSessionCallback,
Arrays.asList(TUNNEL_MODE_INBOUND_TS_V6),
Arrays.asList(TUNNEL_MODE_OUTBOUND_TS_V6),
Arrays.asList(EXPECTED_INTERNAL_LINK_ADDR_V6),
Arrays.asList(EXPECTED_DNS_SERVERS_ONE, EXPECTED_DNS_SERVERS_TWO));
IpSecTransformCallRecord firstTransformRecordA =
mFirstChildSessionCallback.awaitNextCreatedIpSecTransform();
IpSecTransformCallRecord firstTransformRecordB =
mFirstChildSessionCallback.awaitNextCreatedIpSecTransform();
verifyCreateIpSecTransformPair(firstTransformRecordA, firstTransformRecordB);
// Close IKE Session
ikeSession.close();
performCloseIkeBlocking(expectedMsgId++, false /* expectedUseEncap */, deleteIkeResp);
verifyCloseIkeAndChildBlocking(firstTransformRecordA, firstTransformRecordB);
}
@Test
public void testIkeSessionKillWithTunnelMode() throws Exception {
if (!hasTunnelsFeature()) return;
// Open IKE Session
IkeSession ikeSession = openIkeSessionWithTunnelModeChild(mRemoteAddress);
performSetupIkeAndFirstChildBlocking(SUCCESS_IKE_INIT_RESP, SUCCESS_IKE_AUTH_RESP);
ikeSession.kill();
mFirstChildSessionCallback.awaitOnClosed();
mIkeSessionCallback.awaitOnClosed();
}
@Test
public void testIkeInitFail() throws Exception {
final String ikeInitFailRespHex =
"46B8ECA1E0D72A180000000000000000292022200000000000000024000000080000000E";
// Open IKE Session
IkeSession ikeSession = openIkeSessionWithTransportModeChild(mRemoteAddress);
int expectedMsgId = 0;
mTunUtils.awaitReqAndInjectResp(
IKE_DETERMINISTIC_INITIATOR_SPI,
expectedMsgId++,
false /* expectedUseEncap */,
ikeInitFailRespHex);
mFirstChildSessionCallback.awaitOnClosed();
IkeProtocolException protocolException =
(IkeProtocolException) mIkeSessionCallback.awaitOnClosedException();
assertEquals(ERROR_TYPE_NO_PROPOSAL_CHOSEN, protocolException.getErrorType());
assertArrayEquals(EXPECTED_PROTOCOL_ERROR_DATA_NONE, protocolException.getErrorData());
}
@Test
public void testIkeAuthHandlesAuthFailNotification() throws Exception {
final String ikeInitRespHex =
"46B8ECA1E0D72A18CF94CE3159486F002120222000000000000001502200"
+ "00300000002C010100040300000C0100000C800E01000300000803000005"
+ "0300000802000004000000080400000228000088000200001821AA854691"
+ "FA3292DF710F0AC149ACBD0CB421608B8796C1912AF04C5B4B23936FDEC4"
+ "7CB640E3EAFB56BBB562825E87AF68B40E4BAB80A49BAD44407450A4195A"
+ "1DD54BD99F48D28C9F0FBA315A3401C1C3C4AD55911F514A8DF2D2467C46"
+ "A73DDC1452AE81336E0F0D5EC896D2E7A77628AF2F9089F48943399DF216"
+ "EFCD2900002418D2B7E4E6AF0FEFF5962CF8D68F7793B1293FEDE13331D4"
+ "AB0CE9436C2EE1EC2900001C0000400457BD9AEF5B362A83DD7F3DDAA4A9"
+ "9B6B4041DAF32900001C000040055A81893582701E44D4B6729A22FE06DE"
+ "82A03A36290000080000402E290000100000402F00020003000400050000"
+ "000800004014";
final String ikeAuthFailRespHex =
"46B8ECA1E0D72A18CF94CE3159486F002E202320000000010000004C2900"
+ "00301B9E4C8242D3BE62E7F0A537FE8B92C6EAB7153105DA421DCE43A06D"
+ "AB6E4808BAC0CA1DAD6ADD0A126A41BD";
// Open IKE Session
IkeSession ikeSession = openIkeSessionWithTransportModeChild(mRemoteAddress);
performSetupIkeAndFirstChildBlocking(ikeInitRespHex, ikeAuthFailRespHex);
mFirstChildSessionCallback.awaitOnClosed();
IkeProtocolException protocolException =
(IkeProtocolException) mIkeSessionCallback.awaitOnClosedException();
assertEquals(ERROR_TYPE_AUTHENTICATION_FAILED, protocolException.getErrorType());
assertArrayEquals(EXPECTED_PROTOCOL_ERROR_DATA_NONE, protocolException.getErrorData());
}
@Test
public void testIkeAuthHandlesFirstChildCreationFail() throws Exception {
final String ikeInitRespHex =
"46B8ECA1E0D72A18F5ABBF896A1240BE2120222000000000000001502200"
+ "00300000002C010100040300000C0100000C800E0100030000080300000C"
+ "03000008020000050000000804000002280000880002000074950F016B85"
+ "605E57E24651843AB70E41B552EDEE227DFE51E6CBEC00E75FFEFC7D5453"
+ "109B15F721FCD811FC9F113BE06050882F2FC5F5FF25857E555CCFB5AB64"
+ "8B0D1D7A819A3B05DE1FE89A4A627C60D5AA06CD0F66ACD3748722F9CD4F"
+ "F30AE7477CBC12049821F07AD6C9F0ED732321A6A36FA817722E025AC34B"
+ "ABE62900002432E3807F595070E95EDA341A787599B24B1151B535B0222B"
+ "65C003401B9B38F82900001C000040043BB760DB3037B51768DFFAB4B21D"
+ "B1716EA1C1382900001C0000400531098EB04DF1BE3F304606BD59B454A8"
+ "CC7E7311290000080000402E290000100000402F00020003000400050000"
+ "000800004014";
final String ikeAuthCreateChildFailHex =
"46B8ECA1E0D72A18F5ABBF896A1240BE2E20232000000001000000B02400"
+ "009400B0861242E0C88ECB3848D772B560CAD65B6AC9DFFDC8622A394B8E"
+ "64E550BDD69FCD7E768129787ED9062992C1D6DB0F0631C2E05765B403CF"
+ "EF1D0A055B32F6698FF7DB5B8FB1B6A83A81634D00E22C86E35B3BFBEC73"
+ "EAC6806678926945BC7A57003DC1A3528A1EC423EE56C1075B36C0B57A6B"
+ "C6DD990182F6FABFFA167D199C7D629E5B830AAD2AFBD31CEBA6";
// Open IKE Session
IkeSession ikeSession = openIkeSessionWithTransportModeChild(mRemoteAddress);
performSetupIkeAndFirstChildBlocking(ikeInitRespHex, ikeAuthCreateChildFailHex);
// Even though the child creation failed, the authentication succeeded, so the IKE Session's
// onOpened() callback is still expected
verifyIkeSessionSetupBlocking();
// Verify Child Creation failed
IkeProtocolException protocolException =
(IkeProtocolException) mFirstChildSessionCallback.awaitOnClosedException();
assertEquals(ERROR_TYPE_TS_UNACCEPTABLE, protocolException.getErrorType());
assertArrayEquals(EXPECTED_PROTOCOL_ERROR_DATA_NONE, protocolException.getErrorData());
ikeSession.kill();
mIkeSessionCallback.awaitOnClosed();
}
}