diff options
Diffstat (limited to 'tests')
22 files changed, 686 insertions, 182 deletions
diff --git a/tests/iketests/assets/key/end-cert-key-a.key b/tests/iketests/assets/key/end-cert-key-a.key new file mode 100644 index 00000000..a506a350 --- /dev/null +++ b/tests/iketests/assets/key/end-cert-key-a.key @@ -0,0 +1,10 @@ +-----BEGIN PRIVATE KEY----- +MIIBVAIBADANBgkqhkiG9w0BAQEFAASCAT4wggE6AgEAAkEAphl0fstit/XcelkX +2iKoosGsZ2U5rU+mYWR/9RJIY+qR3OYrBeqqtdvjPOu2fNjHEtsO//dCRvdxVWdx +20ADPQIDAQABAkApsawXg/Bk4zeUErc1D4wrRtiDH9rJkXvfaL3iA9PeGIU2j2ci +WwqbJY6HhGSJiNAKMVHRMRAtoaBeX80DOqH1AiEA0pWj6kItG2zTww09sqc6ymTc +1aknFaGuXZY+RO0MTF8CIQDJ68uKQ8LV6labUnnmLPUnIYfVPY8XTNpvkwazeTuV +4wIgDy60u637vI9zEQwCV8AQ0AjHlyvz4m5euOadJLEGgvcCIQCc9BpsySsjmFnl +tgBm+L8+wYOSL52QYP7SB5kH3M6CPQIgQQIVYRKf44G9agh09utnaiw11FCwRr0M +EKsdiVmkw+o= +-----END PRIVATE KEY-----
\ No newline at end of file diff --git a/tests/iketests/src/java/com/android/ike/eap/EapAkaTest.java b/tests/iketests/src/java/com/android/ike/eap/EapAkaTest.java index 996cc732..b1744e17 100644 --- a/tests/iketests/src/java/com/android/ike/eap/EapAkaTest.java +++ b/tests/iketests/src/java/com/android/ike/eap/EapAkaTest.java @@ -20,7 +20,6 @@ import static android.telephony.TelephonyManager.APPTYPE_USIM; import static com.android.ike.TestUtils.hexStringToByteArray; import static com.android.ike.eap.message.EapTestMessageDefinitions.EAP_REQUEST_SIM_START_PACKET; -import static com.android.ike.eap.message.EapTestMessageDefinitions.EAP_SUCCESS; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.mock; @@ -45,6 +44,10 @@ public class EapAkaTest extends EapMethodEndToEndTest { private static final int SUB_ID = 1; private static final String UNFORMATTED_IDENTITY = "123456789ABCDEF"; // IMSI + // EAP_IDENTITY = hex("test@android.net") + private static final byte[] EAP_IDENTITY = + hexStringToByteArray("7465737440616E64726F69642E6E6574"); + // TODO(b/140797965): find valid AUTN/RAND values for the CTS test sim // IK: 7320EE404E055EF2B5AB0F86E96C48BE // CK: E9D1707652E13BF3E05975F601678E5C @@ -69,6 +72,24 @@ public class EapAkaTest extends EapMethodEndToEndTest { + "94B578DE0A3686E17F96F14D5341FE75" + "2012944CA394E5288BA1B2C70CB65063"); + // IK: 7320EE404E055EF2B5AB0F86E96C48BE + // CK: E9D1707652E13BF3E05975F601678E5C + // MK: 8183017CD8ADDB4617F4A2274DD5BCEA99354FB7 + // K_encr: 891D5DB8CACAF657D68BE72371F927A2 + // K_aut: E042A1CC5672358685EC012881EA02DE + private static final byte[] MSK_WITHOUT_IDENTITY_REQ = + hexStringToByteArray( + "629DE03704E15EF1B8BADFF7FA5D84D5" + + "8574B6A3A46F274796346A86AE3455AC" + + "711E2D4D3F96EE71E664B1B947D7E9E7" + + "D227CBB6199A68BD7D43E6E4863D08D6"); + private static final byte[] EMSK_WITHOUT_IDENTITY_REQ = + hexStringToByteArray( + "30A6638AE3AB5C5D29554D8256C3A287" + + "FDF6255E4D726C0622DDF89609C16A8D" + + "563768166A8111A083547DE4C8E280D6" + + "113A608DE9227FC7C02679A1E04DB3CF"); + // Base 64 of: [Length][RAND_1][Length][AUTN] private static final String BASE64_CHALLENGE_1 = "ENailvAwowVgGzEdOKAEUFwQNakUPtnhAAEXleeF2vqtmw=="; @@ -86,6 +107,10 @@ public class EapAkaTest extends EapMethodEndToEndTest { private static final String REQUEST_MAC = "90C3554783D49A18F9EAA231F3C261EC"; private static final String RESPONSE_MAC = "D085987D3D15FA50A80D0CECFA2412EB"; + private static final String REQUEST_MAC_WITHOUT_IDENTITY_REQ = + "6AD7E3F43ED99384E751F55AB8EA48B4"; + private static final String RESPONSE_MAC_WITHOUT_IDENTITY_REQ = + "83E9F5B8B44BDE39B50538BF49864209"; private static final byte[] EAP_AKA_IDENTITY_REQUEST = hexStringToByteArray( @@ -111,6 +136,21 @@ public class EapAkaTest extends EapMethodEndToEndTest { + "17010000" // EAP-AKA | Challenge | 2B padding + "03050080" + RES // AT_RES attribute + "0B050000" + RESPONSE_MAC); // AT_MAC attribute + + private static final byte[] EAP_AKA_CHALLENGE_REQUEST_WITHOUT_IDENTITY_REQ = + hexStringToByteArray( + "01CE0044" // EAP-Request | ID | length in bytes + + "17010000" // EAP-AKA | Challenge | 2B padding + + "01050000" + RAND_1 // AT_RAND attribute + + "02050000" + AUTN // AT_AUTN attribute + + "0B050000" + REQUEST_MAC_WITHOUT_IDENTITY_REQ); // AT_MAC attribute + private static final byte[] EAP_AKA_CHALLENGE_RESPONSE_WITHOUT_IDENTITY_REQUEST = + hexStringToByteArray( + "02CE0030" // EAP-Response | ID | length in bytes + + "17010000" // EAP-AKA | Challenge | 2B padding + + "03050080" + RES // AT_RES attribute + + "0B050000" + RESPONSE_MAC_WITHOUT_IDENTITY_REQ); // AT_MAC attribute + private static final byte[] EAP_AKA_CHALLENGE_REQUEST_SYNC_FAIL = hexStringToByteArray( "01CE0044" // EAP-Request | ID | length in bytes @@ -121,8 +161,14 @@ public class EapAkaTest extends EapMethodEndToEndTest { private static final byte[] EAP_AKA_SYNC_FAIL_RESPONSE = hexStringToByteArray( "02CE0018" // EAP-Response | ID | length in bytes - + "17040000" // EAP-AKA | Challenge | 2B padding + + "17040000" // EAP-AKA | Synchronization-Failure | 2B padding + "0404" + AUTS); // AT_AUTS attribute + + private static final byte[] EAP_AKA_AUTHENTICATION_REJECT = + hexStringToByteArray( + "02CE0008" // EAP-Response | ID | length in bytes + + "17020000"); // EAP-AKA | Authentication-Reject | 2B padding + private static final byte[] EAP_RESPONSE_NAK_PACKET = hexStringToByteArray("021000060317"); // NAK with EAP-AKA listed @@ -136,7 +182,10 @@ public class EapAkaTest extends EapMethodEndToEndTest { mMockTelephonyManager = mock(TelephonyManager.class); mEapSessionConfig = - new EapSessionConfig.Builder().setEapAkaConfig(SUB_ID, APPTYPE_USIM).build(); + new EapSessionConfig.Builder() + .setEapIdentity(EAP_IDENTITY) + .setEapAkaConfig(SUB_ID, APPTYPE_USIM) + .build(); mEapAuthenticator = new EapAuthenticator( mTestLooper.getLooper(), @@ -154,8 +203,14 @@ public class EapAkaTest extends EapMethodEndToEndTest { @Test public void testEapAkaEndToEnd() { verifyEapAkaIdentity(); - verifyEapAkaChallenge(); - verifyEapSuccess(); + verifyEapAkaChallenge(BASE_64_RESPONSE_SUCCESS, EAP_AKA_CHALLENGE_RESPONSE); + verifyEapSuccess(MSK, EMSK); + } + + @Test + public void testEapAkaEndToEndWithoutIdentityRequest() { + verifyEapAkaChallengeWithoutIdentityReq(); + verifyEapSuccess(MSK_WITHOUT_IDENTITY_REQ, EMSK_WITHOUT_IDENTITY_REQ); } @Test @@ -164,34 +219,36 @@ public class EapAkaTest extends EapMethodEndToEndTest { verifyEapAkaIdentity(); verifyEapNotification(2); - verifyEapAkaChallenge(); + verifyEapAkaChallenge(BASE_64_RESPONSE_SUCCESS, EAP_AKA_CHALLENGE_RESPONSE); verifyEapNotification(3); - verifyEapSuccess(); + verifyEapSuccess(MSK, EMSK); } @Test public void testEapAkaUnsupportedType() { - // EAP-Request/SIM/Start (unsupported type) - mEapAuthenticator.processEapMessage(EAP_REQUEST_SIM_START_PACKET); - mTestLooper.dispatchAll(); - - // verify EAP-Response/Nak returned - verify(mMockCallback).onResponse(eq(EAP_RESPONSE_NAK_PACKET)); - verifyNoMoreInteractions( - mMockContext, mMockTelephonyManager, mMockSecureRandom, mMockCallback); + verifyUnsupportedType(EAP_REQUEST_SIM_START_PACKET, EAP_RESPONSE_NAK_PACKET); verifyEapAkaIdentity(); - verifyEapAkaChallenge(); - verifyEapSuccess(); + verifyEapAkaChallenge(BASE_64_RESPONSE_SUCCESS, EAP_AKA_CHALLENGE_RESPONSE); + verifyEapSuccess(MSK, EMSK); } @Test public void testEapAkaSynchronizationFailure() { verifyEapAkaIdentity(); verifyEapAkaSynchronizationFailure(); - verifyEapAkaChallenge(); - verifyEapSuccess(); + verifyEapAkaChallenge(BASE_64_RESPONSE_SUCCESS, EAP_AKA_CHALLENGE_RESPONSE); + verifyEapSuccess(MSK, EMSK); + } + + @Test + public void testEapAkaAuthenticationReject() { + verifyEapAkaIdentity(); + + // return null from TelephonyManager to simluate rejection of AUTN + verifyEapAkaChallenge(null, EAP_AKA_AUTHENTICATION_REJECT); + verifyEapFailure(); } private void verifyEapAkaIdentity() { @@ -210,15 +267,19 @@ public class EapAkaTest extends EapMethodEndToEndTest { mMockContext, mMockTelephonyManager, mMockSecureRandom, mMockCallback); } - private void verifyEapAkaChallenge() { + private void verifyEapAkaChallenge( + String challengeBase64, + String responseBase64, + byte[] incomingEapPacket, + byte[] outgoingEapPacket) { // EAP-AKA/Challenge request when(mMockTelephonyManager.getIccAuthentication( TelephonyManager.APPTYPE_USIM, TelephonyManager.AUTHTYPE_EAP_AKA, - BASE64_CHALLENGE_1)) - .thenReturn(BASE_64_RESPONSE_SUCCESS); + challengeBase64)) + .thenReturn(responseBase64); - mEapAuthenticator.processEapMessage(EAP_AKA_CHALLENGE_REQUEST); + mEapAuthenticator.processEapMessage(incomingEapPacket); mTestLooper.dispatchAll(); // verify EAP-AKA/Challenge response @@ -226,42 +287,45 @@ public class EapAkaTest extends EapMethodEndToEndTest { .getIccAuthentication( TelephonyManager.APPTYPE_USIM, TelephonyManager.AUTHTYPE_EAP_AKA, - BASE64_CHALLENGE_1); - verify(mMockCallback).onResponse(eq(EAP_AKA_CHALLENGE_RESPONSE)); + challengeBase64); + verify(mMockCallback).onResponse(eq(outgoingEapPacket)); + } + + private void verifyEapAkaChallenge(String responseBase64, byte[] outgoingPacket) { + verifyEapAkaChallenge( + BASE64_CHALLENGE_1, responseBase64, EAP_AKA_CHALLENGE_REQUEST, outgoingPacket); verifyNoMoreInteractions( mMockContext, mMockTelephonyManager, mMockSecureRandom, mMockCallback); } - private void verifyEapAkaSynchronizationFailure() { - // EAP-AKA/Challenge request - when(mMockTelephonyManager.getIccAuthentication( - TelephonyManager.APPTYPE_USIM, - TelephonyManager.AUTHTYPE_EAP_AKA, - BASE64_CHALLENGE_2)) - .thenReturn(BASE_64_RESPONSE_SYNC_FAIL); - - mEapAuthenticator.processEapMessage(EAP_AKA_CHALLENGE_REQUEST_SYNC_FAIL); - mTestLooper.dispatchAll(); + private void verifyEapAkaChallengeWithoutIdentityReq() { + verifyEapAkaChallenge( + BASE64_CHALLENGE_1, + BASE_64_RESPONSE_SUCCESS, + EAP_AKA_CHALLENGE_REQUEST_WITHOUT_IDENTITY_REQ, + EAP_AKA_CHALLENGE_RESPONSE_WITHOUT_IDENTITY_REQUEST); - // verify EAP-AKA/Synchronization-Failure response - verify(mMockTelephonyManager) - .getIccAuthentication( - TelephonyManager.APPTYPE_USIM, - TelephonyManager.AUTHTYPE_EAP_AKA, - BASE64_CHALLENGE_2); - verify(mMockCallback).onResponse(eq(EAP_AKA_SYNC_FAIL_RESPONSE)); + // also need to verify interactions with Context and TelephonyManager + verify(mMockContext).getSystemService(eq(Context.TELEPHONY_SERVICE)); + verify(mMockTelephonyManager).createForSubscriptionId(SUB_ID); verifyNoMoreInteractions( mMockContext, mMockTelephonyManager, mMockSecureRandom, mMockCallback); } - private void verifyEapSuccess() { - // EAP-Success - mEapAuthenticator.processEapMessage(EAP_SUCCESS); - mTestLooper.dispatchAll(); - - // verify that onSuccess callback made - verify(mMockCallback).onSuccess(eq(MSK), eq(EMSK)); + private void verifyEapAkaSynchronizationFailure() { + verifyEapAkaChallenge( + BASE64_CHALLENGE_2, + BASE_64_RESPONSE_SYNC_FAIL, + EAP_AKA_CHALLENGE_REQUEST_SYNC_FAIL, + EAP_AKA_SYNC_FAIL_RESPONSE); verifyNoMoreInteractions( mMockContext, mMockTelephonyManager, mMockSecureRandom, mMockCallback); } + + @Override + protected void verifyEapSuccess(byte[] msk, byte[] emsk) { + super.verifyEapSuccess(msk, emsk); + + verifyNoMoreInteractions(mMockTelephonyManager); + } } diff --git a/tests/iketests/src/java/com/android/ike/eap/EapMethodEndToEndTest.java b/tests/iketests/src/java/com/android/ike/eap/EapMethodEndToEndTest.java index 8a3517b1..aed73c25 100644 --- a/tests/iketests/src/java/com/android/ike/eap/EapMethodEndToEndTest.java +++ b/tests/iketests/src/java/com/android/ike/eap/EapMethodEndToEndTest.java @@ -16,8 +16,10 @@ package com.android.ike.eap; +import static com.android.ike.eap.message.EapTestMessageDefinitions.EAP_FAILURE_PACKET; import static com.android.ike.eap.message.EapTestMessageDefinitions.EAP_REQUEST_NOTIFICATION_PACKET; import static com.android.ike.eap.message.EapTestMessageDefinitions.EAP_RESPONSE_NOTIFICATION_PACKET; +import static com.android.ike.eap.message.EapTestMessageDefinitions.EAP_SUCCESS; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.mock; @@ -50,6 +52,15 @@ public class EapMethodEndToEndTest { mTestLooper = new TestLooper(); } + protected void verifyUnsupportedType(byte[] invalidMessageType, byte[] nakResponse) { + mEapAuthenticator.processEapMessage(invalidMessageType); + mTestLooper.dispatchAll(); + + // verify EAP-Response/Nak returned + verify(mMockCallback).onResponse(eq(nakResponse)); + verifyNoMoreInteractions(mMockCallback); + } + protected void verifyEapNotification(int callsToVerify) { mEapAuthenticator.processEapMessage(EAP_REQUEST_NOTIFICATION_PACKET); mTestLooper.dispatchAll(); @@ -58,4 +69,22 @@ public class EapMethodEndToEndTest { .onResponse(eq(EAP_RESPONSE_NOTIFICATION_PACKET)); verifyNoMoreInteractions(mMockCallback); } + + protected void verifyEapSuccess(byte[] msk, byte[] emsk) { + // EAP-Success + mEapAuthenticator.processEapMessage(EAP_SUCCESS); + mTestLooper.dispatchAll(); + + // verify that onSuccess callback made + verify(mMockCallback).onSuccess(eq(msk), eq(emsk)); + verifyNoMoreInteractions(mMockContext, mMockSecureRandom, mMockCallback); + } + + protected void verifyEapFailure() { + mEapAuthenticator.processEapMessage(EAP_FAILURE_PACKET); + mTestLooper.dispatchAll(); + + verify(mMockCallback).onFail(); + verifyNoMoreInteractions(mMockCallback); + } } diff --git a/tests/iketests/src/java/com/android/ike/eap/EapMsChapV2Test.java b/tests/iketests/src/java/com/android/ike/eap/EapMsChapV2Test.java index f3757298..d63b59f2 100644 --- a/tests/iketests/src/java/com/android/ike/eap/EapMsChapV2Test.java +++ b/tests/iketests/src/java/com/android/ike/eap/EapMsChapV2Test.java @@ -17,9 +17,7 @@ package com.android.ike.eap; import static com.android.ike.TestUtils.hexStringToByteArray; -import static com.android.ike.eap.message.EapTestMessageDefinitions.EAP_FAILURE_PACKET; import static com.android.ike.eap.message.EapTestMessageDefinitions.EAP_REQUEST_AKA_IDENTITY_PACKET; -import static com.android.ike.eap.message.EapTestMessageDefinitions.EAP_SUCCESS; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.eq; @@ -108,7 +106,7 @@ public class EapMsChapV2Test extends EapMethodEndToEndTest { public void testEapMsChapV2EndToEndSuccess() { verifyEapMsChapV2Challenge(); verifyEapMsChapV2SuccessRequest(); - verifyEapSuccess(); + verifyEapSuccess(MSK, new byte[0]); } @Test @@ -120,16 +118,11 @@ public class EapMsChapV2Test extends EapMethodEndToEndTest { @Test public void testEapMsChapV2UnsupportedType() { - mEapAuthenticator.processEapMessage(EAP_REQUEST_AKA_IDENTITY_PACKET); - mTestLooper.dispatchAll(); - - // verify EAP-Response/Nak returned - verify(mMockCallback).onResponse(eq(EAP_RESPONSE_NAK_PACKET)); - verifyNoMoreInteractions(mMockCallback); + verifyUnsupportedType(EAP_REQUEST_AKA_IDENTITY_PACKET, EAP_RESPONSE_NAK_PACKET); verifyEapMsChapV2Challenge(); verifyEapMsChapV2SuccessRequest(); - verifyEapSuccess(); + verifyEapSuccess(MSK, new byte[0]); } @Test @@ -142,7 +135,7 @@ public class EapMsChapV2Test extends EapMethodEndToEndTest { verifyEapMsChapV2SuccessRequest(); verifyEapNotification(3); - verifyEapSuccess(); + verifyEapSuccess(MSK, new byte[0]); } private void verifyEapMsChapV2Challenge() { @@ -168,14 +161,6 @@ public class EapMsChapV2Test extends EapMethodEndToEndTest { verifyNoMoreInteractions(mMockCallback); } - private void verifyEapSuccess() { - mEapAuthenticator.processEapMessage(EAP_SUCCESS); - mTestLooper.dispatchAll(); - - verify(mMockCallback).onSuccess(eq(MSK), eq(new byte[0])); - verifyNoMoreInteractions(mMockCallback); - } - private void verifyEapMsChapV2FailureRequest() { mEapAuthenticator.processEapMessage(EAP_MSCHAP_V2_FAILURE_REQUEST); mTestLooper.dispatchAll(); @@ -183,12 +168,4 @@ public class EapMsChapV2Test extends EapMethodEndToEndTest { verify(mMockCallback).onResponse(eq(EAP_MSCHAP_V2_FAILURE_RESPONSE)); verifyNoMoreInteractions(mMockCallback); } - - private void verifyEapFailure() { - mEapAuthenticator.processEapMessage(EAP_FAILURE_PACKET); - mTestLooper.dispatchAll(); - - verify(mMockCallback).onFail(); - verifyNoMoreInteractions(mMockCallback); - } } diff --git a/tests/iketests/src/java/com/android/ike/eap/EapSimTest.java b/tests/iketests/src/java/com/android/ike/eap/EapSimTest.java index 8d8d7f1d..b6f41659 100644 --- a/tests/iketests/src/java/com/android/ike/eap/EapSimTest.java +++ b/tests/iketests/src/java/com/android/ike/eap/EapSimTest.java @@ -21,7 +21,6 @@ import static android.telephony.TelephonyManager.APPTYPE_USIM; import static com.android.ike.TestUtils.hexStringToByteArray; import static com.android.ike.eap.message.EapTestMessageDefinitions.EAP_REQUEST_AKA_IDENTITY_PACKET; import static com.android.ike.eap.message.EapTestMessageDefinitions.EAP_RESPONSE_NAK_PACKET; -import static com.android.ike.eap.message.EapTestMessageDefinitions.EAP_SUCCESS; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.eq; @@ -48,6 +47,10 @@ public class EapSimTest extends EapMethodEndToEndTest { private static final byte[] NONCE = hexStringToByteArray("37f3ddd3954c4831a5ee08c574844398"); private static final String UNFORMATTED_IDENTITY = "123456789ABCDEF"; // IMSI + // EAP_IDENTITY = hex("test@android.net") + private static final byte[] EAP_IDENTITY = + hexStringToByteArray("7465737440616E64726F69642E6E6574"); + private static final int SUB_ID = 1; // Base 64 of: RAND @@ -56,21 +59,44 @@ public class EapSimTest extends EapMethodEndToEndTest { private static final String BASE64_RAND_3 = "ECEjRWeJq83vESNFZ4mrze8="; // BASE 64 of: "04" + SRES + "08" + KC + // SRES 1: 0ABCDEF0 KC 1: FEDCBA9876543210 + // SRES 2: 1ABCDEF1 KC 2: FEDCBA9876543211 + // SRES 3: 2ABCDEF2 KC 3: FEDCBA9876543212 private static final String BASE64_RESP_1 = "BAq83vAI/ty6mHZUMhA="; private static final String BASE64_RESP_2 = "BBq83vEI/ty6mHZUMhE="; private static final String BASE64_RESP_3 = "BCq83vII/ty6mHZUMhI="; - private static final byte[] MSK = hexStringToByteArray( - "9B1E2B6892BC113F6B6D0B5789DD8ADD" - + "B83BE2A84AA50FCAECD0003F92D8DA16" - + "4BF983C923695C309F1D7D68DB6992B0" - + "76EA8CE7129647A6F198F3A6AA8ADED9"); + // MK: 202FC68A3335E8A939A33BC0A0EA8C435DC10060 + // K_encr: F63E152461391FF655C2632E35D076ED + // K_aut: 48E001C8DBA37120FD0465153A56F712 + private static final byte[] MSK = + hexStringToByteArray( + "9B1E2B6892BC113F6B6D0B5789DD8ADD" + + "B83BE2A84AA50FCAECD0003F92D8DA16" + + "4BF983C923695C309F1D7D68DB6992B0" + + "76EA8CE7129647A6F198F3A6AA8ADED9"); private static final byte[] EMSK = hexStringToByteArray( "88210b6724400313539c740f417076b0" + "41da7e64658ec365bd2901a7cd7c2763" + "dad1a0508b92a42fdf85ac53c6f7e756" + "7f99b62bcaf467441b567f19b58d86ae"); + // MK: ED275A588A4C1AEC15C55261DCCD851189E5C5FD + // K_encr: FED573CFA6FC81267C08E264F50A0BB9 + // K_aut: 277B5D6A68FE5156A387996510AC5D61 + private static final byte[] MSK_WITHOUT_IDENTITY_REQ = + hexStringToByteArray( + "8023A49840433464DA1A4F2457FAB3D6" + + "B1A3CA6E5E1DB212FA1AEA17F0A5C933" + + "5541DE7448FE448AC3F09DC25BBAE1EE" + + "17DCE3D32099519CC75840F0E3FB612B"); + private static final byte[] EMSK_WITHOUT_IDENTITY_REQ = + hexStringToByteArray( + "F7E213F0E8F14A21C87F9B5DFADA9A75" + + "A8EAF4AD718BF8C3ED6557BDB60E4671" + + "E6AE109448B2F32F9B984667AE6C2B3F" + + "2FDFE67F97AF4D4727A2EA37F06B7785"); + private static final byte[] EAP_SIM_START_REQUEST = hexStringToByteArray( "01850014120a0000" // EAP header + "0f02000200010000" // AT_VERSION_LIST attribute @@ -87,9 +113,36 @@ public class EapSimTest extends EapMethodEndToEndTest { + "1123456789abcdef1123456789abcdef" // Rand 2 + "2123456789abcdef1123456789abcdef" // Rand 3 + "0b050000e4675b17fa7ba4d93db48d1af9ecbb01"); // AT_MAC attribute - private static final byte[] EAP_SIM_CHALLENGE_RESPONSE = hexStringToByteArray( - "0286001c120b0000" // EAP header - + "0b050000e5df9cb1d935ea5f54d449a038bed061"); // AT_NAC attribute + private static final byte[] EAP_SIM_CHALLENGE_RESPONSE = + hexStringToByteArray( + "0286001c120b0000" // EAP header + + "0b050000e5df9cb1d935ea5f54d449a038bed061"); // AT_MAC attribute + + private static final byte[] EAP_SIM_START_REQUEST_WITHOUT_IDENTITY_REQ = + hexStringToByteArray( + "01850010" // EAP-Request | ID | length in bytes + + "120a0000" // EAP-SIM | Start| 2B padding + + "0f02000200010000"); // AT_VERSION_LIST attribute + private static final byte[] EAP_SIM_START_RESPONSE_WITHOUT_IDENTITY_REQ = + hexStringToByteArray( + "02850020" // EAP-Response | ID | length in bytes + + "120a0000" // EAP-SIM | Start | 2B padding + + "0705000037f3ddd3954c4831a5ee08c574844398" // AT_NONCE_MT attribute + + "10010001"); // AT_SELECTED_VERSION attribute + private static final byte[] EAP_SIM_CHALLENGE_REQUEST_WITHOUT_IDENTITY_REQ = + hexStringToByteArray( + "01860050" // EAP-Request | ID | length in bytes + + "120b0000" // EAP-SIM | Challenge | 2B padding + + "010d0000" // AT_RAND attribute + + "0123456789abcdef1123456789abcdef" // Rand 1 + + "1123456789abcdef1123456789abcdef" // Rand 2 + + "2123456789abcdef1123456789abcdef" // Rand 3 + + "0b050000F2F8C10FCA946AAFE9555E2BD3693DF6"); // AT_MAC attribute + private static final byte[] EAP_SIM_CHALLENGE_RESPONSE_WITHOUT_IDENTITY_REQ = + hexStringToByteArray( + "0286001c" // EAP-Response | ID | length in bytes + + "120b0000" // EAP-SIM | Challenge | 2B padding + + "0b050000DAC3C1B7D9DBFBC923464A94F186E410"); // AT_MAC attribute private TelephonyManager mMockTelephonyManager; @@ -100,9 +153,11 @@ public class EapSimTest extends EapMethodEndToEndTest { mMockTelephonyManager = mock(TelephonyManager.class); - mEapSessionConfig = new EapSessionConfig.Builder() - .setEapSimConfig(SUB_ID, APPTYPE_USIM) - .build(); + mEapSessionConfig = + new EapSessionConfig.Builder() + .setEapIdentity(EAP_IDENTITY) + .setEapSimConfig(SUB_ID, APPTYPE_USIM) + .build(); mEapAuthenticator = new EapAuthenticator( mTestLooper.getLooper(), @@ -114,44 +169,45 @@ public class EapSimTest extends EapMethodEndToEndTest { @Test public void testEapSimEndToEnd() { - verifyEapSimStart(); - verifyEapSimChallenge(); - verifyEapSuccess(); + verifyEapSimStart(EAP_SIM_START_REQUEST, EAP_SIM_START_RESPONSE, true); + verifyEapSimChallenge(EAP_SIM_CHALLENGE_REQUEST, EAP_SIM_CHALLENGE_RESPONSE); + verifyEapSuccess(MSK, EMSK); } @Test - public void testEapSimUnsupportedType() { - // EAP-Request/AKA-Identity (unsupported type) - mEapAuthenticator.processEapMessage(EAP_REQUEST_AKA_IDENTITY_PACKET); - mTestLooper.dispatchAll(); + public void testEapSimEndToEndWithoutIdentityRequest() { + verifyEapSimStart( + EAP_SIM_START_REQUEST_WITHOUT_IDENTITY_REQ, + EAP_SIM_START_RESPONSE_WITHOUT_IDENTITY_REQ, + false); + verifyEapSimChallenge( + EAP_SIM_CHALLENGE_REQUEST_WITHOUT_IDENTITY_REQ, + EAP_SIM_CHALLENGE_RESPONSE_WITHOUT_IDENTITY_REQ); + verifyEapSuccess(MSK_WITHOUT_IDENTITY_REQ, EMSK_WITHOUT_IDENTITY_REQ); + } - // verify EAP-Response/Nak returned - verify(mMockCallback).onResponse(eq(EAP_RESPONSE_NAK_PACKET)); - verifyNoMoreInteractions( - mMockContext, - mMockTelephonyManager, - mMockSecureRandom, - mMockCallback); + @Test + public void testEapSimUnsupportedType() { + verifyUnsupportedType(EAP_REQUEST_AKA_IDENTITY_PACKET, EAP_RESPONSE_NAK_PACKET); - // Switch to EAP-SIM and go through protocol - verifyEapSimStart(); - verifyEapSimChallenge(); - verifyEapSuccess(); + verifyEapSimStart(EAP_SIM_START_REQUEST, EAP_SIM_START_RESPONSE, true); + verifyEapSimChallenge(EAP_SIM_CHALLENGE_REQUEST, EAP_SIM_CHALLENGE_RESPONSE); + verifyEapSuccess(MSK, EMSK); } @Test public void verifyEapSimWithEapNotifications() { verifyEapNotification(1); - verifyEapSimStart(); + verifyEapSimStart(EAP_SIM_START_REQUEST, EAP_SIM_START_RESPONSE, true); verifyEapNotification(2); - verifyEapSimChallenge(); - + verifyEapSimChallenge(EAP_SIM_CHALLENGE_REQUEST, EAP_SIM_CHALLENGE_RESPONSE); verifyEapNotification(3); - verifyEapSuccess(); + verifyEapSuccess(MSK, EMSK); } - private void verifyEapSimStart() { + private void verifyEapSimStart( + byte[] incomingEapPacket, byte[] outgoingEapPacket, boolean expectIdentityRequest) { // EAP-SIM/Start request when(mMockContext.getSystemService(Context.TELEPHONY_SERVICE)) .thenReturn(mMockTelephonyManager); @@ -164,15 +220,19 @@ public class EapSimTest extends EapMethodEndToEndTest { return null; }).when(mMockSecureRandom).nextBytes(eq(new byte[NONCE.length])); - mEapAuthenticator.processEapMessage(EAP_SIM_START_REQUEST); + mEapAuthenticator.processEapMessage(incomingEapPacket); mTestLooper.dispatchAll(); verify(mMockContext).getSystemService(eq(Context.TELEPHONY_SERVICE)); verify(mMockTelephonyManager).createForSubscriptionId(SUB_ID); - verify(mMockTelephonyManager).getSubscriberId(); + + if (expectIdentityRequest) { + verify(mMockTelephonyManager).getSubscriberId(); + } + verify(mMockSecureRandom).nextBytes(any(byte[].class)); // verify EAP-SIM/Start response - verify(mMockCallback).onResponse(eq(EAP_SIM_START_RESPONSE)); + verify(mMockCallback).onResponse(eq(outgoingEapPacket)); verifyNoMoreInteractions( mMockContext, mMockTelephonyManager, @@ -180,7 +240,7 @@ public class EapSimTest extends EapMethodEndToEndTest { mMockCallback); } - private void verifyEapSimChallenge() { + private void verifyEapSimChallenge(byte[] incomingEapPacket, byte[] outgoingEapPacket) { // EAP-SIM/Challenge request when(mMockTelephonyManager .getIccAuthentication( @@ -201,7 +261,7 @@ public class EapSimTest extends EapMethodEndToEndTest { BASE64_RAND_3)) .thenReturn(BASE64_RESP_3); - mEapAuthenticator.processEapMessage(EAP_SIM_CHALLENGE_REQUEST); + mEapAuthenticator.processEapMessage(incomingEapPacket); mTestLooper.dispatchAll(); // verify EAP-SIM/Challenge response @@ -220,7 +280,7 @@ public class EapSimTest extends EapMethodEndToEndTest { eq(TelephonyManager.APPTYPE_USIM), eq(TelephonyManager.AUTHTYPE_EAP_SIM), eq(BASE64_RAND_3)); - verify(mMockCallback).onResponse(eq(EAP_SIM_CHALLENGE_RESPONSE)); + verify(mMockCallback).onResponse(eq(outgoingEapPacket)); verifyNoMoreInteractions( mMockContext, mMockTelephonyManager, @@ -228,17 +288,10 @@ public class EapSimTest extends EapMethodEndToEndTest { mMockCallback); } - private void verifyEapSuccess() { - // EAP-Success - mEapAuthenticator.processEapMessage(EAP_SUCCESS); - mTestLooper.dispatchAll(); + @Override + protected void verifyEapSuccess(byte[] msk, byte[] emsk) { + super.verifyEapSuccess(msk, emsk); - // verify that onSuccess callback made - verify(mMockCallback).onSuccess(eq(MSK), eq(EMSK)); - verifyNoMoreInteractions( - mMockContext, - mMockTelephonyManager, - mMockSecureRandom, - mMockCallback); + verifyNoMoreInteractions(mMockTelephonyManager); } } diff --git a/tests/iketests/src/java/com/android/ike/eap/message/EapTestMessageDefinitions.java b/tests/iketests/src/java/com/android/ike/eap/message/EapTestMessageDefinitions.java index 79cb2e77..2e937332 100644 --- a/tests/iketests/src/java/com/android/ike/eap/message/EapTestMessageDefinitions.java +++ b/tests/iketests/src/java/com/android/ike/eap/message/EapTestMessageDefinitions.java @@ -69,6 +69,8 @@ public class EapTestMessageDefinitions { // EAP-SIM response containing SELECTED_VERSION (1) and IDENTITY attributes public static final byte[] EAP_SIM_RESPONSE_PACKET = hexStringToByteArray( "02" + ID + "0024120A0000100100010E060011" + IDENTITY_STRING + "000000"); + public static final byte[] EAP_SIM_RESPONSE_WITHOUT_IDENTITY = + hexStringToByteArray("02" + ID + "0020120A000007050000" + NONCE_MT_STRING + "10010001"); public static final byte[] EAP_SIM_NOTIFICATION_RESPONSE = hexStringToByteArray( "02" + ID + "0008120C0000"); public static final byte[] EAP_AKA_NOTIFICATION_RESPONSE = @@ -223,6 +225,8 @@ public class EapTestMessageDefinitions { public static final String EAP_AKA_UICC_RESP_SUCCESS_BASE_64 = "2wURIjNEVRAAESIzRFVmd4iZqrvM3e7/EP/u3cy7qpmId2ZVRDMiEQA="; + public static final byte[] EAP_AKA_AUTHENTICATION_REJECT = + hexStringToByteArray("02" + ID + "000817020000"); public static final String EAP_AKA_CHALLENGE_RESPONSE_MAC = "C70366512D9C5EBA8E3484509A25DCE4"; public static final byte[] EAP_AKA_CHALLENGE_RESPONSE_MAC_BYTES = hexStringToByteArray(EAP_AKA_CHALLENGE_RESPONSE_MAC); diff --git a/tests/iketests/src/java/com/android/ike/eap/message/simaka/EapAkaTypeDataTest.java b/tests/iketests/src/java/com/android/ike/eap/message/simaka/EapAkaTypeDataTest.java index f476b742..e5c6f9e8 100644 --- a/tests/iketests/src/java/com/android/ike/eap/message/simaka/EapAkaTypeDataTest.java +++ b/tests/iketests/src/java/com/android/ike/eap/message/simaka/EapAkaTypeDataTest.java @@ -16,6 +16,7 @@ package com.android.ike.eap.message.simaka; +import static com.android.ike.TestUtils.hexStringToByteArray; import static com.android.ike.eap.message.EapTestMessageDefinitions.EAP_AKA_CHALLENGE_RESPONSE_MAC_BYTES; import static com.android.ike.eap.message.EapTestMessageDefinitions.EAP_AKA_CHALLENGE_RESPONSE_TYPE_DATA; import static com.android.ike.eap.message.EapTestMessageDefinitions.EAP_AKA_IDENTITY_REQUEST; @@ -23,10 +24,15 @@ import static com.android.ike.eap.message.EapTestMessageDefinitions.INVALID_SUBT import static com.android.ike.eap.message.simaka.EapAkaTypeData.EAP_AKA_CHALLENGE; import static com.android.ike.eap.message.simaka.EapAkaTypeData.EAP_AKA_IDENTITY; import static com.android.ike.eap.message.simaka.EapSimAkaAttribute.EAP_AT_ANY_ID_REQ; +import static com.android.ike.eap.message.simaka.EapSimAkaAttribute.EAP_AT_AUTN; +import static com.android.ike.eap.message.simaka.EapSimAkaAttribute.EAP_AT_CHECKCODE; import static com.android.ike.eap.message.simaka.EapSimAkaAttribute.EAP_AT_MAC; +import static com.android.ike.eap.message.simaka.EapSimAkaAttribute.EAP_AT_RAND; import static com.android.ike.eap.message.simaka.EapSimAkaAttribute.EAP_AT_RES; import static com.android.ike.eap.message.simaka.attributes.EapTestAttributeDefinitions.RES_BYTES; +import static junit.framework.TestCase.fail; + import static org.junit.Assert.assertArrayEquals; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; @@ -34,19 +40,40 @@ import static org.junit.Assert.assertTrue; import com.android.ike.eap.message.simaka.EapAkaTypeData.EapAkaTypeDataDecoder; import com.android.ike.eap.message.simaka.EapSimAkaAttribute.AtAnyIdReq; +import com.android.ike.eap.message.simaka.EapSimAkaAttribute.AtAutn; import com.android.ike.eap.message.simaka.EapSimAkaAttribute.AtMac; +import com.android.ike.eap.message.simaka.EapSimAkaAttribute.AtRandAka; import com.android.ike.eap.message.simaka.EapSimAkaAttribute.AtRes; +import com.android.ike.eap.message.simaka.EapSimAkaAttribute.EapSimAkaUnsupportedAttribute; import com.android.ike.eap.message.simaka.EapSimAkaTypeData.DecodeResult; import org.junit.Before; import org.junit.Test; +import java.util.Arrays; import java.util.Iterator; import java.util.LinkedHashMap; import java.util.Map.Entry; public class EapAkaTypeDataTest { private static final int UNABLE_TO_PROCESS_CODE = 0; + private static final int INVALID_SUBTYPE_INT = -1; + + private static final int EAP_AT_TRUST_IND = 139; + private static final String RAND = "7A1FCDC0034BA1227E7B9FCEAFD47D53"; + private static final byte[] RAND_BYTES = hexStringToByteArray(RAND); + private static final String AUTN = "000102030405060708090A0B0C0D0E0F"; + private static final byte[] AUTN_BYTES = hexStringToByteArray(AUTN); + private static final String MAC = "95FEB9E70427F34B4FAC8F2C7A65A302"; + private static final byte[] MAC_BYTES = hexStringToByteArray(MAC); + private static final byte[] EAP_AKA_REQUEST = + hexStringToByteArray( + "010000" // Challenge | 2B padding + + "01050000" + RAND // AT_RAND attribute + + "02050000" + AUTN // AT_AUTN attribute + + "8B010002" // AT_RESULT_IND attribute (TS 124 302#8.2.3.1) + + "0B050000" + MAC // AT_MAC attribute + + "86010000"); // AT_CHECKCODE attribute private EapAkaTypeDataDecoder mEapAkaTypeDataDecoder; @@ -79,6 +106,40 @@ public class EapAkaTypeDataTest { } @Test + public void testDecodeWithOptionalAttributes() { + DecodeResult<EapAkaTypeData> result = mEapAkaTypeDataDecoder.decode(EAP_AKA_REQUEST); + + assertTrue(result.isSuccessfulDecode()); + EapAkaTypeData eapAkaTypeData = result.eapTypeData; + assertEquals(EAP_AKA_CHALLENGE, eapAkaTypeData.eapSubtype); + + // also check Map entries (needs to match input order) + Iterator<Entry<Integer, EapSimAkaAttribute>> itr = + eapAkaTypeData.attributeMap.entrySet().iterator(); + Entry<Integer, EapSimAkaAttribute> entry = itr.next(); + assertEquals(EAP_AT_RAND, (int) entry.getKey()); + assertArrayEquals(RAND_BYTES, ((AtRandAka) entry.getValue()).rand); + + entry = itr.next(); + assertEquals(EAP_AT_AUTN, (int) entry.getKey()); + assertArrayEquals(AUTN_BYTES, ((AtAutn) entry.getValue()).autn); + + entry = itr.next(); + assertEquals(EAP_AT_TRUST_IND, (int) entry.getKey()); + assertTrue(entry.getValue() instanceof EapSimAkaUnsupportedAttribute); + + entry = itr.next(); + assertEquals(EAP_AT_MAC, (int) entry.getKey()); + assertArrayEquals(MAC_BYTES, ((AtMac) entry.getValue()).mac); + + entry = itr.next(); + assertEquals(EAP_AT_CHECKCODE, (int) entry.getKey()); + assertTrue(entry.getValue() instanceof EapSimAkaUnsupportedAttribute); + + assertFalse(itr.hasNext()); + } + + @Test public void testDecodeInvalidSubtype() { DecodeResult<EapAkaTypeData> result = mEapAkaTypeDataDecoder.decode(INVALID_SUBTYPE); assertFalse(result.isSuccessfulDecode()); @@ -94,4 +155,22 @@ public class EapAkaTypeDataTest { byte[] result = eapAkaTypeData.encode(); assertArrayEquals(EAP_AKA_IDENTITY_REQUEST, result); } + + @Test + public void testConstructorInvalidSubtype() throws Exception { + try { + new EapAkaTypeData(INVALID_SUBTYPE_INT, Arrays.asList(new AtAnyIdReq())); + fail("Expected IllegalArgumentException for invalid subtype"); + } catch (IllegalArgumentException expected) { + } + } + + @Test + public void testConstructorDuplicateAttributes() throws Exception { + try { + new EapAkaTypeData(EAP_AKA_IDENTITY, Arrays.asList(new AtAnyIdReq(), new AtAnyIdReq())); + fail("Expected IllegalArgumentException for duplicate attributes"); + } catch (IllegalArgumentException expected) { + } + } } diff --git a/tests/iketests/src/java/com/android/ike/eap/message/simaka/EapSimTypeDataTest.java b/tests/iketests/src/java/com/android/ike/eap/message/simaka/EapSimTypeDataTest.java index 23437d75..40b55c19 100644 --- a/tests/iketests/src/java/com/android/ike/eap/message/simaka/EapSimTypeDataTest.java +++ b/tests/iketests/src/java/com/android/ike/eap/message/simaka/EapSimTypeDataTest.java @@ -25,6 +25,8 @@ import static com.android.ike.eap.message.EapTestMessageDefinitions.TYPE_DATA_IN import static com.android.ike.eap.message.simaka.EapSimAkaAttribute.EAP_AT_PERMANENT_ID_REQ; import static com.android.ike.eap.message.simaka.EapSimAkaAttribute.EAP_AT_VERSION_LIST; +import static junit.framework.TestCase.fail; + import static org.junit.Assert.assertArrayEquals; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; @@ -48,6 +50,7 @@ public class EapSimTypeDataTest { private static final int UNABLE_TO_PROCESS_CODE = 0; private static final int INSUFFICIENT_CHALLENGES_CODE = 2; private static final int EAP_SIM_START = 10; + private static final int INVALID_SUBTYPE_INT = -1; private EapSimTypeDataDecoder mEapSimTypeDataDecoder; @@ -151,4 +154,23 @@ public class EapSimTypeDataTest { assertFalse(result.isSuccessfulDecode()); assertEquals(UNABLE_TO_PROCESS_CODE, result.atClientErrorCode.errorCode); } + + @Test + public void testConstructorInvalidSubtype() throws Exception { + try { + new EapSimTypeData(INVALID_SUBTYPE_INT, Arrays.asList(new AtPermanentIdReq())); + fail("Expected IllegalArgumentException for invalid subtype"); + } catch (IllegalArgumentException expected) { + } + } + + @Test + public void testConstructorDuplicateAttributes() throws Exception { + try { + new EapSimTypeData( + EAP_SIM_START, Arrays.asList(new AtPermanentIdReq(), new AtPermanentIdReq())); + fail("Expected IllegalArgumentException for duplicate attributes"); + } catch (IllegalArgumentException expected) { + } + } } diff --git a/tests/iketests/src/java/com/android/ike/eap/statemachine/EapAkaChallengeStateTest.java b/tests/iketests/src/java/com/android/ike/eap/statemachine/EapAkaChallengeStateTest.java index 5d9a5e68..4deecf30 100644 --- a/tests/iketests/src/java/com/android/ike/eap/statemachine/EapAkaChallengeStateTest.java +++ b/tests/iketests/src/java/com/android/ike/eap/statemachine/EapAkaChallengeStateTest.java @@ -23,6 +23,7 @@ import static com.android.ike.eap.message.EapMessage.EAP_CODE_FAILURE; import static com.android.ike.eap.message.EapMessage.EAP_CODE_REQUEST; import static com.android.ike.eap.message.EapMessage.EAP_CODE_SUCCESS; import static com.android.ike.eap.message.EapTestMessageDefinitions.CK_BYTES; +import static com.android.ike.eap.message.EapTestMessageDefinitions.EAP_AKA_AUTHENTICATION_REJECT; import static com.android.ike.eap.message.EapTestMessageDefinitions.EAP_AKA_CHALLENGE_RESPONSE; import static com.android.ike.eap.message.EapTestMessageDefinitions.EAP_AKA_CLIENT_ERROR_UNABLE_TO_PROCESS; import static com.android.ike.eap.message.EapTestMessageDefinitions.EAP_AKA_SYNCHRONIZATION_FAILURE; @@ -57,7 +58,7 @@ import com.android.ike.eap.EapResult.EapFailure; import com.android.ike.eap.EapResult.EapResponse; import com.android.ike.eap.EapResult.EapSuccess; import com.android.ike.eap.exceptions.EapInvalidRequestException; -import com.android.ike.eap.exceptions.simaka.EapSimAkaAuthenticationFailureException; +import com.android.ike.eap.exceptions.simaka.EapAkaInvalidAuthenticationResponse; import com.android.ike.eap.exceptions.simaka.EapSimAkaInvalidLengthException; import com.android.ike.eap.message.EapData; import com.android.ike.eap.message.EapMessage; @@ -269,8 +270,8 @@ public class EapAkaChallengeStateTest extends EapAkaStateTest { BASE_64_CHALLENGE)) .thenReturn(null); - EapError eapError = (EapError) mEapAkaMethodStateMachine.process(eapMessage); - assertTrue(eapError.cause instanceof EapSimAkaAuthenticationFailureException); + EapResponse eapResponse = (EapResponse) mEapAkaMethodStateMachine.process(eapMessage); + assertArrayEquals(EAP_AKA_AUTHENTICATION_REJECT, eapResponse.packet); verify(mMockEapAkaTypeDataDecoder).decode(eq(DUMMY_EAP_TYPE_DATA)); verify(mMockTelephonyManager) @@ -304,7 +305,7 @@ public class EapAkaChallengeStateTest extends EapAkaStateTest { .thenReturn(EAP_AKA_UICC_RESP_INVALID_TAG); EapError eapError = (EapError) mEapAkaMethodStateMachine.process(eapMessage); - assertTrue(eapError.cause instanceof EapSimAkaAuthenticationFailureException); + assertTrue(eapError.cause instanceof EapAkaInvalidAuthenticationResponse); verify(mMockEapAkaTypeDataDecoder).decode(eq(DUMMY_EAP_TYPE_DATA)); verify(mMockTelephonyManager) diff --git a/tests/iketests/src/java/com/android/ike/eap/statemachine/EapAkaCreatedStateTest.java b/tests/iketests/src/java/com/android/ike/eap/statemachine/EapAkaCreatedStateTest.java index 5c0a6df2..c32fefac 100644 --- a/tests/iketests/src/java/com/android/ike/eap/statemachine/EapAkaCreatedStateTest.java +++ b/tests/iketests/src/java/com/android/ike/eap/statemachine/EapAkaCreatedStateTest.java @@ -24,6 +24,7 @@ import static com.android.ike.eap.message.EapTestMessageDefinitions.ID_INT; import static com.android.ike.eap.message.simaka.EapAkaTypeData.EAP_AKA_CHALLENGE; import static com.android.ike.eap.message.simaka.EapAkaTypeData.EAP_AKA_IDENTITY; +import static org.junit.Assert.assertArrayEquals; import static org.junit.Assert.assertTrue; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.times; @@ -81,7 +82,8 @@ public class EapAkaCreatedStateTest extends EapAkaStateTest { mEapAkaMethodStateMachine.process(eapMessage); - assertTrue(mEapAkaMethodStateMachine.getState() instanceof ChallengeState); + ChallengeState challengeState = (ChallengeState) mEapAkaMethodStateMachine.getState(); + assertArrayEquals(EAP_IDENTITY_BYTES, challengeState.mIdentity); // decoded in CreatedState and ChallengeState verify(mMockEapAkaTypeDataDecoder, times(2)).decode(DUMMY_EAP_TYPE_DATA); diff --git a/tests/iketests/src/java/com/android/ike/eap/statemachine/EapAkaMethodStateMachineTest.java b/tests/iketests/src/java/com/android/ike/eap/statemachine/EapAkaMethodStateMachineTest.java index c14dd04f..23c2649b 100644 --- a/tests/iketests/src/java/com/android/ike/eap/statemachine/EapAkaMethodStateMachineTest.java +++ b/tests/iketests/src/java/com/android/ike/eap/statemachine/EapAkaMethodStateMachineTest.java @@ -64,6 +64,10 @@ public class EapAkaMethodStateMachineTest { private static final int SUB_ID = 1; private static final byte[] DUMMY_EAP_TYPE_DATA = hexStringToByteArray("112233445566"); + // EAP-Identity = hex("test@android.net") + protected static final byte[] EAP_IDENTITY_BYTES = + hexStringToByteArray("7465737440616E64726F69642E6E6574"); + protected TelephonyManager mMockTelephonyManager; private EapAkaTypeDataDecoder mMockEapAkaTypeDataDecoder; @@ -80,7 +84,10 @@ public class EapAkaMethodStateMachineTest { mEapAkaMethodStateMachine = new EapAkaMethodStateMachine( - mMockTelephonyManager, mEapAkaConfig, mMockEapAkaTypeDataDecoder); + mMockTelephonyManager, + EAP_IDENTITY_BYTES, + mEapAkaConfig, + mMockEapAkaTypeDataDecoder); verify(mMockTelephonyManager).createForSubscriptionId(SUB_ID); } diff --git a/tests/iketests/src/java/com/android/ike/eap/statemachine/EapAkaStateTest.java b/tests/iketests/src/java/com/android/ike/eap/statemachine/EapAkaStateTest.java index 2f5c64e9..02ea9202 100644 --- a/tests/iketests/src/java/com/android/ike/eap/statemachine/EapAkaStateTest.java +++ b/tests/iketests/src/java/com/android/ike/eap/statemachine/EapAkaStateTest.java @@ -62,6 +62,10 @@ public class EapAkaStateTest { protected static final String NOTIFICATION_MESSAGE = "test"; protected static final byte[] DUMMY_EAP_TYPE_DATA = hexStringToByteArray("112233445566"); + // EAP-Identity = hex("test@android.net") + protected static final byte[] EAP_IDENTITY_BYTES = + hexStringToByteArray("7465737440616E64726F69642E6E6574"); + protected TelephonyManager mMockTelephonyManager; protected EapAkaTypeDataDecoder mMockEapAkaTypeDataDecoder; @@ -79,6 +83,7 @@ public class EapAkaStateTest { mEapAkaMethodStateMachine = new EapAkaMethodStateMachine( mMockTelephonyManager, + EAP_IDENTITY_BYTES, mEapAkaConfig, mMockEapAkaTypeDataDecoder); diff --git a/tests/iketests/src/java/com/android/ike/eap/statemachine/EapMsChapV2MethodStateMachineTest.java b/tests/iketests/src/java/com/android/ike/eap/statemachine/EapMsChapV2MethodStateMachineTest.java index 4d57e43d..16646a1d 100644 --- a/tests/iketests/src/java/com/android/ike/eap/statemachine/EapMsChapV2MethodStateMachineTest.java +++ b/tests/iketests/src/java/com/android/ike/eap/statemachine/EapMsChapV2MethodStateMachineTest.java @@ -69,14 +69,14 @@ public class EapMsChapV2MethodStateMachineTest { // Tests for MS CHAPv2 authentication utils. Test vectors from RFC 2759#9.2. @Test - public void testUsernameToBytes() throws Exception { + public void testUsernameToBytes() { assertArrayEquals( MSCHAP_V2_USERNAME_ASCII_BYTES, EapMsChapV2MethodStateMachine.usernameToBytes(MSCHAP_V2_USERNAME)); } @Test - public void testPasswordToBytes() throws Exception { + public void testPasswordToBytes() { assertArrayEquals( MSCHAP_V2_PASSWORD_UTF_BYTES, EapMsChapV2MethodStateMachine.passwordToBytes(MSCHAP_V2_PASSWORD)); @@ -104,13 +104,13 @@ public class EapMsChapV2MethodStateMachineTest { } @Test - public void testNtPasswordHash() throws Exception { + public void testNtPasswordHash() { byte[] passwordHash = EapMsChapV2MethodStateMachine.ntPasswordHash(MSCHAP_V2_PASSWORD); assertArrayEquals(MSCHAP_V2_PASSWORD_HASH, passwordHash); } @Test - public void testHashNtPasswordHash() throws Exception { + public void testHashNtPasswordHash() { byte[] passwordHashHash = EapMsChapV2MethodStateMachine.hashNtPasswordHash(MSCHAP_V2_PASSWORD_HASH); assertArrayEquals(MSCHAP_V2_PASSWORD_HASH_HASH, passwordHashHash); diff --git a/tests/iketests/src/java/com/android/ike/eap/statemachine/EapSimAkaMethodStateMachineTest.java b/tests/iketests/src/java/com/android/ike/eap/statemachine/EapSimAkaMethodStateMachineTest.java index 136e68da..f3cc5a03 100644 --- a/tests/iketests/src/java/com/android/ike/eap/statemachine/EapSimAkaMethodStateMachineTest.java +++ b/tests/iketests/src/java/com/android/ike/eap/statemachine/EapSimAkaMethodStateMachineTest.java @@ -126,6 +126,10 @@ public class EapSimAkaMethodStateMachineTest { private static final byte[] UICC_RESPONSE = hexStringToByteArray("04" + SRES_1 + "08" + KC_1); + // EAP-Identity = hex("test@android.net") + protected static final byte[] EAP_IDENTITY_BYTES = + hexStringToByteArray("7465737440616E64726F69642E6E6574"); + // K_encr + K_aut + MSK + EMSK private static final int PRF_OUTPUT_BYTES = (2 * KEY_LEN) + (2 * SESSION_KEY_LENGTH); @@ -139,7 +143,8 @@ public class EapSimAkaMethodStateMachineTest { mEapSimConfig = new EapSimConfig(SUB_ID, TelephonyManager.APPTYPE_USIM); mStateMachine = - new EapSimAkaMethodStateMachine(mMockTelephonyManager, mEapSimConfig) { + new EapSimAkaMethodStateMachine( + mMockTelephonyManager, EAP_IDENTITY_BYTES, mEapSimConfig) { @Override EapSimAkaTypeData getEapSimAkaTypeData(AtClientErrorCode clientErrorCode) { return new EapSimTypeData( @@ -362,7 +367,8 @@ public class EapSimAkaMethodStateMachineTest { Arrays.asList(new AtNotification(GENERAL_FAILURE_PRE_CHALLENGE))); EapResponse eapResponse = - (EapResponse) mStateMachine.handleEapSimAkaNotification(true, ID_INT, typeData); + (EapResponse) + mStateMachine.handleEapSimAkaNotification(TAG, true, ID_INT, typeData); assertArrayEquals(EAP_SIM_NOTIFICATION_RESPONSE, eapResponse.packet); assertTrue(mStateMachine.mHasReceivedSimAkaNotification); verify(mStateMachine, never()).transitionTo(any(EapMethodState.class)); @@ -376,7 +382,8 @@ public class EapSimAkaMethodStateMachineTest { Arrays.asList(new AtNotification(GENERAL_FAILURE_POST_CHALLENGE))); EapResponse eapResponse = - (EapResponse) mStateMachine.handleEapSimAkaNotification(true, ID_INT, typeData); + (EapResponse) + mStateMachine.handleEapSimAkaNotification(TAG, true, ID_INT, typeData); assertArrayEquals(EAP_SIM_CLIENT_ERROR_UNABLE_TO_PROCESS, eapResponse.packet); verify(mStateMachine, never()) .transitionTo(any(EapMethodStateMachine.EapMethodState.class)); @@ -389,10 +396,10 @@ public class EapSimAkaMethodStateMachineTest { EAP_SIM_NOTIFICATION, Arrays.asList(new AtNotification(GENERAL_FAILURE_PRE_CHALLENGE))); - mStateMachine.handleEapSimAkaNotification(true, ID_INT, typeData); + mStateMachine.handleEapSimAkaNotification(TAG, true, ID_INT, typeData); EapError eapError = - (EapError) mStateMachine.handleEapSimAkaNotification(true, ID_INT, typeData); + (EapError) mStateMachine.handleEapSimAkaNotification(TAG, true, ID_INT, typeData); assertTrue(eapError.cause instanceof EapInvalidRequestException); assertTrue(mStateMachine.mHasReceivedSimAkaNotification); verify(mStateMachine, never()) @@ -408,7 +415,8 @@ public class EapSimAkaMethodStateMachineTest { new AtNotification(GENERAL_FAILURE_PRE_CHALLENGE), new AtMac())); EapResponse eapResponse = - (EapResponse) mStateMachine.handleEapSimAkaNotification(true, ID_INT, typeData); + (EapResponse) + mStateMachine.handleEapSimAkaNotification(TAG, true, ID_INT, typeData); assertArrayEquals(EAP_SIM_CLIENT_ERROR_UNABLE_TO_PROCESS, eapResponse.packet); verify(mStateMachine, never()) .transitionTo(any(EapMethodStateMachine.EapMethodState.class)); @@ -431,7 +439,8 @@ public class EapSimAkaMethodStateMachineTest { mStateMachine.mMacAlgorithm = mockMac; EapResponse eapResponse = - (EapResponse) mStateMachine.handleEapSimAkaNotification(false, ID_INT, typeData); + (EapResponse) + mStateMachine.handleEapSimAkaNotification(TAG, false, ID_INT, typeData); assertArrayEquals(EAP_SIM_NOTIFICATION_RESPONSE_WITH_MAC, eapResponse.packet); assertTrue(mStateMachine.mHasReceivedSimAkaNotification); verify(mStateMachine, never()).transitionTo(any(EapMethodState.class)); @@ -449,7 +458,8 @@ public class EapSimAkaMethodStateMachineTest { Arrays.asList(new AtNotification(GENERAL_FAILURE_POST_CHALLENGE))); EapResponse eapResponse = - (EapResponse) mStateMachine.handleEapSimAkaNotification(false, ID_INT, typeData); + (EapResponse) + mStateMachine.handleEapSimAkaNotification(TAG, false, ID_INT, typeData); assertArrayEquals(EAP_SIM_CLIENT_ERROR_UNABLE_TO_PROCESS, eapResponse.packet); verify(mStateMachine, never()).transitionTo(any(EapMethodState.class)); } diff --git a/tests/iketests/src/java/com/android/ike/eap/statemachine/EapSimMethodStateMachineTest.java b/tests/iketests/src/java/com/android/ike/eap/statemachine/EapSimMethodStateMachineTest.java index 6ec51035..8aa41311 100644 --- a/tests/iketests/src/java/com/android/ike/eap/statemachine/EapSimMethodStateMachineTest.java +++ b/tests/iketests/src/java/com/android/ike/eap/statemachine/EapSimMethodStateMachineTest.java @@ -65,6 +65,10 @@ public class EapSimMethodStateMachineTest { private static final int SUB_ID = 1; private static final byte[] DUMMY_EAP_TYPE_DATA = hexStringToByteArray("112233445566"); + // EAP-Identity = hex("test@android.net") + protected static final byte[] EAP_IDENTITY_BYTES = + hexStringToByteArray("7465737440616E64726F69642E6E6574"); + private TelephonyManager mMockTelephonyManager; private EapSimTypeDataDecoder mMockEapSimTypeDataDecoder; @@ -83,6 +87,7 @@ public class EapSimMethodStateMachineTest { mEapSimMethodStateMachine = new EapSimMethodStateMachine( mMockTelephonyManager, + EAP_IDENTITY_BYTES, mEapSimConfig, new SecureRandom(), mMockEapSimTypeDataDecoder); diff --git a/tests/iketests/src/java/com/android/ike/eap/statemachine/EapSimStartStateTest.java b/tests/iketests/src/java/com/android/ike/eap/statemachine/EapSimStartStateTest.java index a45b52b8..4965c8fa 100644 --- a/tests/iketests/src/java/com/android/ike/eap/statemachine/EapSimStartStateTest.java +++ b/tests/iketests/src/java/com/android/ike/eap/statemachine/EapSimStartStateTest.java @@ -22,6 +22,7 @@ import static com.android.ike.eap.message.EapMessage.EAP_CODE_FAILURE; import static com.android.ike.eap.message.EapMessage.EAP_CODE_REQUEST; import static com.android.ike.eap.message.EapMessage.EAP_CODE_SUCCESS; import static com.android.ike.eap.message.EapTestMessageDefinitions.EAP_SIM_IDENTITY; +import static com.android.ike.eap.message.EapTestMessageDefinitions.EAP_SIM_RESPONSE_WITHOUT_IDENTITY; import static com.android.ike.eap.message.EapTestMessageDefinitions.ID_INT; import static com.android.ike.eap.message.EapTestMessageDefinitions.IMSI; import static com.android.ike.eap.message.simaka.EapSimAkaAttribute.EAP_AT_ANY_ID_REQ; @@ -30,12 +31,17 @@ import static com.android.ike.eap.message.simaka.EapSimAkaAttribute.EAP_AT_IV; import static com.android.ike.eap.message.simaka.EapSimAkaAttribute.EAP_AT_MAC; import static com.android.ike.eap.message.simaka.EapSimAkaAttribute.EAP_AT_PERMANENT_ID_REQ; import static com.android.ike.eap.message.simaka.EapSimAkaAttribute.EAP_AT_VERSION_LIST; +import static com.android.ike.eap.message.simaka.EapSimTypeData.EAP_SIM_CHALLENGE; import static com.android.ike.eap.message.simaka.EapSimTypeData.EAP_SIM_START; +import static com.android.ike.eap.message.simaka.attributes.EapTestAttributeDefinitions.NONCE_MT; import static org.junit.Assert.assertArrayEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verifyNoMoreInteractions; import static org.mockito.Mockito.when; @@ -43,6 +49,7 @@ import static org.mockito.Mockito.when; import com.android.ike.eap.EapResult; import com.android.ike.eap.EapResult.EapError; import com.android.ike.eap.EapResult.EapFailure; +import com.android.ike.eap.EapResult.EapResponse; import com.android.ike.eap.exceptions.EapInvalidRequestException; import com.android.ike.eap.exceptions.simaka.EapSimAkaIdentityUnavailableException; import com.android.ike.eap.message.EapData; @@ -51,12 +58,15 @@ import com.android.ike.eap.message.simaka.EapSimAkaAttribute; import com.android.ike.eap.message.simaka.EapSimAkaAttribute.AtAnyIdReq; import com.android.ike.eap.message.simaka.EapSimAkaAttribute.AtIdentity; import com.android.ike.eap.message.simaka.EapSimAkaAttribute.AtMac; +import com.android.ike.eap.message.simaka.EapSimAkaAttribute.AtNonceMt; import com.android.ike.eap.message.simaka.EapSimAkaAttribute.AtPermanentIdReq; import com.android.ike.eap.message.simaka.EapSimAkaAttribute.AtVersionList; import com.android.ike.eap.message.simaka.EapSimAkaTypeData.DecodeResult; import com.android.ike.eap.message.simaka.EapSimTypeData; import com.android.ike.eap.statemachine.EapMethodStateMachine.FinalState; +import com.android.ike.eap.statemachine.EapSimMethodStateMachine.ChallengeState; import com.android.ike.eap.statemachine.EapSimMethodStateMachine.StartState; +import com.android.ike.utils.Log; import org.junit.Before; import org.junit.Test; @@ -72,7 +82,15 @@ public class EapSimStartStateTest extends EapSimStateTest { @Before public void setUp() { super.setUp(); - mStartState = mEapSimMethodStateMachine.new StartState(null); + + AtNonceMt atNonceMt = null; + try { + atNonceMt = new AtNonceMt(NONCE_MT); + } catch (Exception e) { + fail("Failed to create AtNonceMt attribute in setUp()"); + } + + mStartState = mEapSimMethodStateMachine.new StartState(atNonceMt); mEapSimMethodStateMachine.transitionTo(mStartState); mAttributes = new LinkedHashMap<>(); @@ -193,4 +211,44 @@ public class EapSimStartStateTest extends EapSimStateTest { assertNull(atIdentity); verifyNoMoreInteractions(mMockTelephonyManager); } + + @Test + public void testProcessWithoutIdentityRequest() throws Exception { + EapMessage eapMessage = + new EapMessage( + EAP_CODE_REQUEST, ID_INT, new EapData(EAP_TYPE_SIM, DUMMY_EAP_TYPE_DATA)); + + // Send EAP-SIM/Start message without Identity request + mAttributes.put(EAP_AT_VERSION_LIST, new AtVersionList(8, 1)); + DecodeResult eapSimStartDecodeResult = + new DecodeResult(new EapSimTypeData(EAP_SIM_START, mAttributes)); + when(mMockEapSimTypeDataDecoder.decode(DUMMY_EAP_TYPE_DATA)) + .thenReturn(eapSimStartDecodeResult); + + EapResult result = mEapSimMethodStateMachine.process(eapMessage); + EapResponse eapResponse = (EapResponse) result; + assertArrayEquals( + Log.byteArrayToHexString(eapResponse.packet), + EAP_SIM_RESPONSE_WITHOUT_IDENTITY, + eapResponse.packet); + + verify(mMockEapSimTypeDataDecoder).decode(eq(DUMMY_EAP_TYPE_DATA)); + + // Send EAP-SIM/Challenge message + DecodeResult eapSimChallengeDecodeResult = + new DecodeResult(new EapSimTypeData(EAP_SIM_CHALLENGE, new LinkedHashMap<>())); + when(mMockEapSimTypeDataDecoder.decode(DUMMY_EAP_TYPE_DATA)) + .thenReturn(eapSimChallengeDecodeResult); + + // We only care about the transition to ChallengeState - the response doesn't matter + mEapSimMethodStateMachine.process(eapMessage); + ChallengeState challengeState = (ChallengeState) mEapSimMethodStateMachine.getState(); + assertArrayEquals(EAP_IDENTITY_BYTES, challengeState.mIdentity); + + // verify decode called 3x times: + // 1. decode in EAP-SIM/Start test above + // 2. decode in EAP-SIM/Challenge test for StartState + // 3. decode in EAP-SIM/Challenge test for ChallengeState + verify(mMockEapSimTypeDataDecoder, times(3)).decode(eq(DUMMY_EAP_TYPE_DATA)); + } } diff --git a/tests/iketests/src/java/com/android/ike/eap/statemachine/EapSimStateTest.java b/tests/iketests/src/java/com/android/ike/eap/statemachine/EapSimStateTest.java index 562da213..9a0a3c2c 100644 --- a/tests/iketests/src/java/com/android/ike/eap/statemachine/EapSimStateTest.java +++ b/tests/iketests/src/java/com/android/ike/eap/statemachine/EapSimStateTest.java @@ -63,6 +63,10 @@ public class EapSimStateTest { protected static final String NOTIFICATION_MESSAGE = "test"; protected static final byte[] DUMMY_EAP_TYPE_DATA = hexStringToByteArray("112233445566"); + // EAP-Identity = hex("test@android.net") + protected static final byte[] EAP_IDENTITY_BYTES = + hexStringToByteArray("7465737440616E64726F69642E6E6574"); + protected TelephonyManager mMockTelephonyManager; protected EapSimTypeDataDecoder mMockEapSimTypeDataDecoder; @@ -80,6 +84,7 @@ public class EapSimStateTest { mEapSimMethodStateMachine = new EapSimMethodStateMachine( mMockTelephonyManager, + EAP_IDENTITY_BYTES, mEapSimConfig, new SecureRandom(), mMockEapSimTypeDataDecoder); diff --git a/tests/iketests/src/java/com/android/ike/ikev2/ChildSessionStateMachineTest.java b/tests/iketests/src/java/com/android/ike/ikev2/ChildSessionStateMachineTest.java index 86967f53..9aca851e 100644 --- a/tests/iketests/src/java/com/android/ike/ikev2/ChildSessionStateMachineTest.java +++ b/tests/iketests/src/java/com/android/ike/ikev2/ChildSessionStateMachineTest.java @@ -16,6 +16,8 @@ package com.android.ike.ikev2; +import static android.system.OsConstants.AF_INET; + import static com.android.ike.ikev2.ChildSessionStateMachine.CMD_FORCE_TRANSITION; import static com.android.ike.ikev2.IkeSessionStateMachine.CMD_LOCAL_REQUEST_REKEY_CHILD; import static com.android.ike.ikev2.IkeSessionStateMachine.IKE_EXCHANGE_SUBTYPE_DELETE_CHILD; @@ -27,6 +29,7 @@ import static com.android.ike.ikev2.exceptions.IkeProtocolException.ERROR_TYPE_T import static com.android.ike.ikev2.message.IkeHeader.EXCHANGE_TYPE_CREATE_CHILD_SA; import static com.android.ike.ikev2.message.IkeHeader.EXCHANGE_TYPE_INFORMATIONAL; import static com.android.ike.ikev2.message.IkeNotifyPayload.NOTIFY_TYPE_REKEY_SA; +import static com.android.ike.ikev2.message.IkePayload.PAYLOAD_TYPE_CP; import static com.android.ike.ikev2.message.IkePayload.PAYLOAD_TYPE_DELETE; import static com.android.ike.ikev2.message.IkePayload.PAYLOAD_TYPE_KE; import static com.android.ike.ikev2.message.IkePayload.PAYLOAD_TYPE_NONCE; @@ -64,6 +67,7 @@ import android.content.Context; import android.net.IpSecManager; import android.net.IpSecManager.UdpEncapsulationSocket; import android.net.IpSecTransform; +import android.net.LinkAddress; import android.os.test.TestLooper; import androidx.test.InstrumentationRegistry; @@ -84,6 +88,10 @@ import com.android.ike.ikev2.exceptions.IkeInternalException; import com.android.ike.ikev2.exceptions.InvalidKeException; import com.android.ike.ikev2.exceptions.InvalidSyntaxException; import com.android.ike.ikev2.exceptions.NoValidProposalChosenException; +import com.android.ike.ikev2.message.IkeConfigPayload; +import com.android.ike.ikev2.message.IkeConfigPayload.ConfigAttribute; +import com.android.ike.ikev2.message.IkeConfigPayload.ConfigAttributeIpv4Address; +import com.android.ike.ikev2.message.IkeConfigPayload.ConfigAttributeIpv4Netmask; import com.android.ike.ikev2.message.IkeDeletePayload; import com.android.ike.ikev2.message.IkeKePayload; import com.android.ike.ikev2.message.IkeMessage; @@ -113,6 +121,7 @@ import java.net.Inet4Address; import java.net.InetAddress; import java.security.GeneralSecurityException; import java.util.ArrayList; +import java.util.Arrays; import java.util.LinkedList; import java.util.List; import java.util.concurrent.Executor; @@ -124,6 +133,10 @@ public final class ChildSessionStateMachineTest { (Inet4Address) (InetAddressUtils.parseNumericAddress("192.0.2.200")); private static final Inet4Address REMOTE_ADDRESS = (Inet4Address) (InetAddressUtils.parseNumericAddress("192.0.2.100")); + private static final Inet4Address INTERNAL_ADDRESS = + (Inet4Address) (InetAddressUtils.parseNumericAddress("203.0.113.100")); + + private static final int IPV4_PREFIX_LEN = 32; private static final String IKE_AUTH_RESP_SA_PAYLOAD = "2c00002c0000002801030403cae7019f0300000c0100000c800e0080" @@ -188,6 +201,9 @@ public final class ChildSessionStateMachineTest { ArgumentCaptor.forClass(ChildSaRecordConfig.class); private ArgumentCaptor<List<IkePayload>> mPayloadListCaptor = ArgumentCaptor.forClass(List.class); + private ArgumentCaptor<ChildSessionConfiguration> mChildConfigCaptor = + ArgumentCaptor.forClass(ChildSessionConfiguration.class); + private ArgumentMatcher<ChildLocalRequest> mRekeyChildLocalReqMatcher = (argument) -> { return CMD_LOCAL_REQUEST_REKEY_CHILD == argument.procedureType @@ -269,7 +285,11 @@ public final class ChildSessionStateMachineTest { } private ChildSessionOptions buildChildSessionOptions() throws Exception { - return new TunnelModeChildSessionOptions.Builder().addSaProposal(buildSaProposal()).build(); + return new TunnelModeChildSessionOptions.Builder() + .addSaProposal(buildSaProposal()) + .addInternalAddressRequest(AF_INET, 1) + .addInternalAddressRequest(INTERNAL_ADDRESS, IPV4_PREFIX_LEN) + .build(); } private void setUpChildSaRecords() { @@ -321,6 +341,17 @@ public final class ChildSessionStateMachineTest { // Build Nonce Payloads mFirstSaReqPayloads.add(new IkeNoncePayload()); mFirstSaRespPayloads.add(new IkeNoncePayload()); + + // Build Config Request Payload + List<ConfigAttribute> attrReqList = new LinkedList<>(); + attrReqList.add(new ConfigAttributeIpv4Address(INTERNAL_ADDRESS)); + attrReqList.add(new ConfigAttributeIpv4Netmask()); + mFirstSaReqPayloads.add(new IkeConfigPayload(false /*isReply*/, attrReqList)); + + // Build Config Reply Payload + List<ConfigAttribute> attrRespList = new LinkedList<>(); + attrRespList.add(new ConfigAttributeIpv4Address(INTERNAL_ADDRESS)); + mFirstSaRespPayloads.add(new IkeConfigPayload(true /*isReply*/, attrRespList)); } private ChildSaRecord makeSpyChildSaRecord(int inboundSpi, int outboundSpi) { @@ -444,7 +475,29 @@ public final class ChildSessionStateMachineTest { verify(mSpyUserCbExecutor).execute(any(Runnable.class)); verifyNotifyUsersCreateIpSecSa(mSpyCurrentChildSaRecord, true /*expectInbound*/); verifyNotifyUsersCreateIpSecSa(mSpyCurrentChildSaRecord, false /*expectInbound*/); - verify(mMockChildSessionCallback).onOpened(); + verify(mMockChildSessionCallback).onOpened(mChildConfigCaptor.capture()); + + // Verify Child Session Configuration + ChildSessionConfiguration sessionConfig = mChildConfigCaptor.getValue(); + verifyTsList( + Arrays.asList(mChildSessionOptions.getLocalTrafficSelectors()), + sessionConfig.getInboundTrafficSelectors()); + verifyTsList( + Arrays.asList(mChildSessionOptions.getRemoteTrafficSelectors()), + sessionConfig.getOutboundTrafficSelectors()); + + List<LinkAddress> addrList = sessionConfig.getInternalAddressList(); + assertEquals(1, addrList.size()); + assertEquals(INTERNAL_ADDRESS, addrList.get(0).getAddress()); + assertEquals(IPV4_PREFIX_LEN, addrList.get(0).getPrefixLength()); + } + + private void verifyTsList( + List<IkeTrafficSelector> expectedList, List<IkeTrafficSelector> tsList) { + assertEquals(expectedList.size(), tsList.size()); + for (int i = 0; i < expectedList.size(); i++) { + assertEquals(expectedList.get(i), tsList.get(i)); + } } @Test @@ -467,7 +520,8 @@ public final class ChildSessionStateMachineTest { quitAndVerify(); } - private void verifyOutboundCreatePayloadTypes(List<IkePayload> outboundPayloads) { + private void verifyOutboundCreatePayloadTypes( + List<IkePayload> outboundPayloads, boolean isRekey) { assertNotNull( IkePayload.getPayloadForTypeInProvidedList( PAYLOAD_TYPE_SA, IkeSaPayload.class, outboundPayloads)); @@ -483,6 +537,16 @@ public final class ChildSessionStateMachineTest { assertNull( IkePayload.getPayloadForTypeInProvidedList( PAYLOAD_TYPE_KE, IkeKePayload.class, outboundPayloads)); + + IkeConfigPayload configPayload = + IkePayload.getPayloadForTypeInProvidedList( + PAYLOAD_TYPE_CP, IkeConfigPayload.class, outboundPayloads); + if (isRekey) { + assertNull(configPayload); + } else { + assertNotNull(configPayload); + assertEquals(IkeConfigPayload.CONFIG_TYPE_REQUEST, configPayload.configType); + } } @Test @@ -503,7 +567,7 @@ public final class ChildSessionStateMachineTest { eq(mChildSessionStateMachine)); List<IkePayload> reqPayloadList = mPayloadListCaptor.getValue(); - verifyOutboundCreatePayloadTypes(reqPayloadList); + verifyOutboundCreatePayloadTypes(reqPayloadList, false /*isRekey*/); assertTrue( IkePayload.getPayloadListForTypeInProvidedList( PAYLOAD_TYPE_NOTIFY, IkeNotifyPayload.class, reqPayloadList) @@ -841,7 +905,7 @@ public final class ChildSessionStateMachineTest { // Verify outbound payload list List<IkePayload> reqPayloadList = mPayloadListCaptor.getValue(); - verifyOutboundCreatePayloadTypes(reqPayloadList); + verifyOutboundCreatePayloadTypes(reqPayloadList, true /*isRekey*/); verifyOutboundRekeySaPayload(reqPayloadList, false /*isResp*/); verifyOutboundRekeyNotifyPayload(reqPayloadList); @@ -1177,7 +1241,7 @@ public final class ChildSessionStateMachineTest { mPayloadListCaptor.capture(), eq(mChildSessionStateMachine)); List<IkePayload> respPayloadList = mPayloadListCaptor.getValue(); - verifyOutboundCreatePayloadTypes(respPayloadList); + verifyOutboundCreatePayloadTypes(respPayloadList, true /*isRekey*/); verifyOutboundRekeySaPayload(respPayloadList, true /*isResp*/); verifyOutboundRekeyNotifyPayload(respPayloadList); diff --git a/tests/iketests/src/java/com/android/ike/ikev2/TunnelModeChildSessionOptionsTest.java b/tests/iketests/src/java/com/android/ike/ikev2/TunnelModeChildSessionOptionsTest.java index a67d44f9..5ed6480c 100644 --- a/tests/iketests/src/java/com/android/ike/ikev2/TunnelModeChildSessionOptionsTest.java +++ b/tests/iketests/src/java/com/android/ike/ikev2/TunnelModeChildSessionOptionsTest.java @@ -20,8 +20,12 @@ import static android.system.OsConstants.AF_INET; import static android.system.OsConstants.AF_INET6; import static com.android.ike.ikev2.message.IkeConfigPayload.CONFIG_ATTR_INTERNAL_IP4_ADDRESS; +import static com.android.ike.ikev2.message.IkeConfigPayload.CONFIG_ATTR_INTERNAL_IP4_DNS; import static com.android.ike.ikev2.message.IkeConfigPayload.CONFIG_ATTR_INTERNAL_IP4_NETMASK; +import static com.android.ike.ikev2.message.IkeConfigPayload.CONFIG_ATTR_INTERNAL_IP4_SUBNET; import static com.android.ike.ikev2.message.IkeConfigPayload.CONFIG_ATTR_INTERNAL_IP6_ADDRESS; +import static com.android.ike.ikev2.message.IkeConfigPayload.CONFIG_ATTR_INTERNAL_IP6_DNS; +import static com.android.ike.ikev2.message.IkeConfigPayload.CONFIG_ATTR_INTERNAL_IP6_SUBNET; import static org.junit.Assert.assertArrayEquals; import static org.junit.Assert.assertEquals; @@ -52,6 +56,11 @@ public final class TunnelModeChildSessionOptionsTest { private static final Inet6Address IPV6_ADDRESS = (Inet6Address) (InetAddressUtils.parseNumericAddress("2001:db8::1")); + private static final Inet4Address IPV4_DNS_SERVER = + (Inet4Address) (InetAddressUtils.parseNumericAddress("8.8.8.8")); + private static final Inet6Address IPV6_DNS_SERVER = + (Inet6Address) (InetAddressUtils.parseNumericAddress("2001:4860:4860::8888")); + private ChildSaProposal mSaProposal; @Before @@ -130,4 +139,43 @@ public final class TunnelModeChildSessionOptionsTest { } } + + @Test + public void testBuildChildSessionOptionsWithDnsServerReq() { + TunnelModeChildSessionOptions childOptions = + new TunnelModeChildSessionOptions.Builder() + .addSaProposal(mSaProposal) + .addInternalDnsServerRequest(AF_INET, 1) + .addInternalDnsServerRequest(AF_INET6, 1) + .addInternalDnsServerRequest(IPV4_DNS_SERVER) + .addInternalDnsServerRequest(IPV6_DNS_SERVER) + .build(); + + verifyCommon(childOptions); + + SparseArray<Integer> exptectedAttrCntMap = new SparseArray<>(); + exptectedAttrCntMap.put(CONFIG_ATTR_INTERNAL_IP4_DNS, 2); + exptectedAttrCntMap.put(CONFIG_ATTR_INTERNAL_IP6_DNS, 2); + + verifyAttrTypes(exptectedAttrCntMap, childOptions); + } + + @Test + public void testBuildChildSessionOptionsWithSubnetReq() { + TunnelModeChildSessionOptions childOptions = + new TunnelModeChildSessionOptions.Builder() + .addSaProposal(mSaProposal) + .addInternalSubnetRequest(AF_INET, 1) + .addInternalSubnetRequest(AF_INET6, 1) + .build(); + + verifyCommon(childOptions); + + SparseArray<Integer> exptectedAttrCntMap = new SparseArray<>(); + exptectedAttrCntMap.put(CONFIG_ATTR_INTERNAL_IP4_SUBNET, 1); + exptectedAttrCntMap.put(CONFIG_ATTR_INTERNAL_IP6_SUBNET, 1); + + verifyAttrTypes(exptectedAttrCntMap, childOptions); + } } + diff --git a/tests/iketests/src/java/com/android/ike/ikev2/message/IkeAuthDigitalSignPayloadTest.java b/tests/iketests/src/java/com/android/ike/ikev2/message/IkeAuthDigitalSignPayloadTest.java index 52f9259a..239bd504 100644 --- a/tests/iketests/src/java/com/android/ike/ikev2/message/IkeAuthDigitalSignPayloadTest.java +++ b/tests/iketests/src/java/com/android/ike/ikev2/message/IkeAuthDigitalSignPayloadTest.java @@ -16,6 +16,8 @@ package com.android.ike.ikev2.message; +import static com.android.ike.ikev2.message.IkeAuthDigitalSignPayload.SIGNATURE_ALGO_RSA_SHA2_256; + import static org.junit.Assert.assertArrayEquals; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; @@ -31,6 +33,7 @@ import com.android.ike.ikev2.testutils.CertUtils; import org.junit.Before; import org.junit.Test; +import java.security.PrivateKey; import java.security.cert.X509Certificate; public final class IkeAuthDigitalSignPayloadTest { @@ -92,9 +95,7 @@ public final class IkeAuthDigitalSignPayloadTest { assertTrue(payload instanceof IkeAuthDigitalSignPayload); IkeAuthDigitalSignPayload dsPayload = (IkeAuthDigitalSignPayload) payload; - assertEquals( - IkeAuthDigitalSignPayload.SIGNATURE_ALGO_RSA_SHA2_256, - dsPayload.signatureAlgoAndHash); + assertEquals(SIGNATURE_ALGO_RSA_SHA2_256, dsPayload.signatureAlgoAndHash); assertArrayEquals(dsPayload.signature, TestUtils.hexStringToByteArray(SIGNATURE)); } @@ -136,7 +137,24 @@ public final class IkeAuthDigitalSignPayloadTest { PRF_RESP_KEY); fail("Expected to fail due to wrong certificate."); } catch (AuthenticationFailedException expected) { - } } + + @Test + public void testGenerateSignature() throws Exception { + PrivateKey key = CertUtils.createRsaPrivateKeyFromKeyFile("end-cert-key-a.key"); + + IkeAuthDigitalSignPayload authPayload = + new IkeAuthDigitalSignPayload( + SIGNATURE_ALGO_RSA_SHA2_256, + key, + IKE_INIT_RESP_REQUEST, + NONCE_INIT_RESP, + ID_RESP_PAYLOAD_BODY, + mIkeHmacSha1Prf, + PRF_RESP_KEY); + + assertEquals(SIGNATURE_ALGO_RSA_SHA2_256, authPayload.signatureAlgoAndHash); + assertArrayEquals(authPayload.signature, TestUtils.hexStringToByteArray(SIGNATURE)); + } } diff --git a/tests/iketests/src/java/com/android/ike/ikev2/message/IkeConfigPayloadTest.java b/tests/iketests/src/java/com/android/ike/ikev2/message/IkeConfigPayloadTest.java index 9ee6a620..e8a67d79 100644 --- a/tests/iketests/src/java/com/android/ike/ikev2/message/IkeConfigPayloadTest.java +++ b/tests/iketests/src/java/com/android/ike/ikev2/message/IkeConfigPayloadTest.java @@ -17,6 +17,7 @@ package com.android.ike.ikev2.message; import static com.android.ike.ikev2.message.IkeConfigPayload.CONFIG_ATTR_INTERNAL_IP4_ADDRESS; +import static com.android.ike.ikev2.message.IkeConfigPayload.CONFIG_ATTR_INTERNAL_IP4_DHCP; import static com.android.ike.ikev2.message.IkeConfigPayload.CONFIG_ATTR_INTERNAL_IP4_DNS; import static com.android.ike.ikev2.message.IkeConfigPayload.CONFIG_ATTR_INTERNAL_IP4_NETMASK; import static com.android.ike.ikev2.message.IkeConfigPayload.CONFIG_ATTR_INTERNAL_IP4_SUBNET; @@ -47,6 +48,7 @@ import com.android.ike.ikev2.message.IkeConfigPayload.ConfigAttrIpv4AddressBase; import com.android.ike.ikev2.message.IkeConfigPayload.ConfigAttrIpv6AddrRangeBase; import com.android.ike.ikev2.message.IkeConfigPayload.ConfigAttribute; import com.android.ike.ikev2.message.IkeConfigPayload.ConfigAttributeIpv4Address; +import com.android.ike.ikev2.message.IkeConfigPayload.ConfigAttributeIpv4Dhcp; import com.android.ike.ikev2.message.IkeConfigPayload.ConfigAttributeIpv4Dns; import com.android.ike.ikev2.message.IkeConfigPayload.ConfigAttributeIpv4Netmask; import com.android.ike.ikev2.message.IkeConfigPayload.ConfigAttributeIpv4Subnet; @@ -104,6 +106,13 @@ public final class IkeConfigPayloadTest { private static final byte[] IPV4_DNS_ATTRIBUTE_WITHOUT_VALUE = TestUtils.hexStringToByteArray("00030000"); + private static final Inet4Address IPV4_DHCP = + (Inet4Address) (InetAddressUtils.parseNumericAddress("192.0.2.200")); + private static final byte[] IPV4_DHCP_ATTRIBUTE_WITH_VALUE = + TestUtils.hexStringToByteArray("00060004c00002c8"); + private static final byte[] IPV4_DHCP_ATTRIBUTE_WITHOUT_VALUE = + TestUtils.hexStringToByteArray("00060000"); + private static final byte[] IPV4_SUBNET_ATTRIBUTE_VALUE = TestUtils.hexStringToByteArray("c0000264fffffff0"); private static final byte[] IPV4_SUBNET_ATTRIBUTE_WITH_VALUE = @@ -420,6 +429,44 @@ public final class IkeConfigPayloadTest { } @Test + public void testDecodeIpv4DhcpWithValue() throws Exception { + ConfigAttributeIpv4Dhcp attribute = new ConfigAttributeIpv4Dhcp(IPV4_DHCP.getAddress()); + + assertEquals(CONFIG_ATTR_INTERNAL_IP4_DHCP, attribute.attributeType); + assertEquals(IPV4_DHCP, attribute.address); + } + + @Test + public void testDecodeIpv4DhcpWithoutValue() throws Exception { + ConfigAttributeIpv4Dhcp attribute = new ConfigAttributeIpv4Dhcp(new byte[0]); + + assertEquals(CONFIG_ATTR_INTERNAL_IP4_DHCP, attribute.attributeType); + assertNull(attribute.address); + } + + @Test + public void testEncodeIpv4DhcpWithValue() throws Exception { + ConfigAttributeIpv4Dhcp attributeIp4Dhcp = new ConfigAttributeIpv4Dhcp(IPV4_DHCP); + + verifyEncodeIpv4AddresBaseAttribute( + attributeIp4Dhcp, + CONFIG_ATTR_INTERNAL_IP4_DHCP, + IPV4_DHCP_ATTRIBUTE_WITH_VALUE, + IPV4_DHCP); + } + + @Test + public void testEncodeIpv4DhcpWithoutValue() throws Exception { + ConfigAttributeIpv4Dhcp attribute = new ConfigAttributeIpv4Dhcp(); + + verifyEncodeIpv4AddresBaseAttribute( + attribute, + CONFIG_ATTR_INTERNAL_IP4_DHCP, + IPV4_DHCP_ATTRIBUTE_WITHOUT_VALUE, + null /*expectedAddress*/); + } + + @Test public void testDecodeIpv4SubnetWithValue() throws Exception { ConfigAttributeIpv4Subnet attributeIp4Subnet = new ConfigAttributeIpv4Subnet(IPV4_SUBNET_ATTRIBUTE_VALUE); @@ -450,18 +497,6 @@ public final class IkeConfigPayloadTest { } @Test - public void testEncodeIpv4SubnetWithValue() throws Exception { - ConfigAttributeIpv4Subnet attributeIp4Subnet = - new ConfigAttributeIpv4Subnet(IPV4_LINK_ADDRESS); - - verifyBuildAndEncodeAttributeCommon( - attributeIp4Subnet, - CONFIG_ATTR_INTERNAL_IP4_SUBNET, - IPV4_SUBNET_ATTRIBUTE_WITH_VALUE); - assertEquals(IPV4_LINK_ADDRESS, attributeIp4Subnet.linkAddress); - } - - @Test public void testEncodeIpv4SubnetWithoutValue() throws Exception { ConfigAttributeIpv4Subnet attributeIp4Subnet = new ConfigAttributeIpv4Subnet(); @@ -559,18 +594,6 @@ public final class IkeConfigPayloadTest { } @Test - public void testEncodeIpv6SubnetWithValue() throws Exception { - ConfigAttributeIpv6Subnet attributeIp6Subnet = - new ConfigAttributeIpv6Subnet(IPV6_LINK_ADDRESS); - - verifyEncodeIpv6RangeBaseAttribute( - attributeIp6Subnet, - CONFIG_ATTR_INTERNAL_IP6_SUBNET, - IPV6_SUBNET_ATTRIBUTE_WITH_VALUE, - IPV6_LINK_ADDRESS); - } - - @Test public void testEncodeIpv6SubnetWithoutValue() throws Exception { ConfigAttributeIpv6Subnet attributeIp6Subnet = new ConfigAttributeIpv6Subnet(); diff --git a/tests/iketests/src/java/com/android/ike/ikev2/testutils/CertUtils.java b/tests/iketests/src/java/com/android/ike/ikev2/testutils/CertUtils.java index e44551a0..e42e5647 100644 --- a/tests/iketests/src/java/com/android/ike/ikev2/testutils/CertUtils.java +++ b/tests/iketests/src/java/com/android/ike/ikev2/testutils/CertUtils.java @@ -21,14 +21,21 @@ import android.content.Context; import androidx.test.InstrumentationRegistry; import com.android.ike.ikev2.message.IkeMessage; +import com.android.org.bouncycastle.util.io.pem.PemObject; +import com.android.org.bouncycastle.util.io.pem.PemReader; import java.io.InputStream; +import java.io.InputStreamReader; +import java.security.KeyFactory; import java.security.cert.CertificateFactory; import java.security.cert.X509Certificate; +import java.security.interfaces.RSAPrivateKey; +import java.security.spec.PKCS8EncodedKeySpec; -/** CertUtils provides utility methods for creating X509 certificate. */ +/** CertUtils provides utility methods for creating X509 certificate and private key. */ public final class CertUtils { private static final String PEM_FOLDER_NAME = "pem"; + private static final String KEY_FOLDER_NAME = "key"; /** Creates an X509Certificate with a pem file */ public static X509Certificate createCertFromPemFile(String fileName) throws Exception { @@ -40,4 +47,17 @@ public final class CertUtils { CertificateFactory.getInstance("X.509", IkeMessage.getSecurityProvider()); return (X509Certificate) factory.generateCertificate(inputStream); } + + /** Creates an private key from a PKCS8 format key file */ + public static RSAPrivateKey createRsaPrivateKeyFromKeyFile(String fileName) throws Exception { + Context context = InstrumentationRegistry.getContext(); + InputStream inputStream = + context.getResources().getAssets().open(KEY_FOLDER_NAME + "/" + fileName); + + PemObject pemObject = new PemReader(new InputStreamReader(inputStream)).readPemObject(); + + KeyFactory keyFactory = KeyFactory.getInstance("RSA"); + return (RSAPrivateKey) + keyFactory.generatePrivate(new PKCS8EncodedKeySpec(pemObject.getContent())); + } } |