aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorevitayan <evitayan@google.com>2019-03-05 10:35:43 -0800
committerandroid-build-merger <android-build-merger@google.com>2019-03-05 10:35:43 -0800
commitedef32aba243271eb3188e2330ea54baf246d941 (patch)
tree021e21e84664af1008cdcf5505eaf7a7c8a6311d
parentfbe41f418387d06a7b5533012984626fae27e303 (diff)
parent04177d35228000474011c6fb875ba66e0dbf574c (diff)
downloadike-edef32aba243271eb3188e2330ea54baf246d941.tar.gz
Support building and validating SaProposal am: 1d3f038662 am: 37a409a167
am: 04177d3522 Change-Id: I9329de615e3a86c6b6f07923b9859e3b71caf251
-rw-r--r--src/java/com/android/ike/ikev2/SaProposal.java97
-rw-r--r--tests/iketests/src/java/com/android/ike/ikev2/SaProposalTest.java248
-rw-r--r--tests/iketests/src/java/com/android/ike/ikev2/message/IkeSaPayloadTest.java27
3 files changed, 355 insertions, 17 deletions
diff --git a/src/java/com/android/ike/ikev2/SaProposal.java b/src/java/com/android/ike/ikev2/SaProposal.java
index 232ffd7f..e5b258e7 100644
--- a/src/java/com/android/ike/ikev2/SaProposal.java
+++ b/src/java/com/android/ike/ikev2/SaProposal.java
@@ -209,24 +209,89 @@ public final class SaProposal {
ERROR_TAG + "Encryption algorithm must be proposed.");
}
- return (EncryptionTransform[]) mProposedEncryptAlgos.toArray();
+ return mProposedEncryptAlgos.toArray(
+ new EncryptionTransform[mProposedEncryptAlgos.size()]);
}
private PrfTransform[] buildPrfsOrThrow() {
- // TODO: Validate that PRF must be proposed for IKE SA and PRF must not be
- // proposed for Child SA.
- throw new UnsupportedOperationException("Cannot validate user proposed algorithm.");
+ if (mIsIkeProposal == mProposedPrfs.isEmpty()) {
+ throw new IllegalArgumentException(
+ ERROR_TAG + "Invalid PRF configuration for this SA Proposal.");
+ }
+
+ return mProposedPrfs.toArray(new PrfTransform[mProposedPrfs.size()]);
+ }
+
+ private IntegrityTransform[] buildIntegAlgosForIkeOrThrow() {
+ // When building IKE SA Proposal with normal-mode ciphers, mProposedIntegrityAlgos must
+ // not be empty and must not have INTEGRITY_ALGORITHM_NONE. When building IKE SA
+ // Proposal with combined-mode ciphers, mProposedIntegrityAlgos must be either empty or
+ // only have INTEGRITY_ALGORITHM_NONE.
+ if (mProposedIntegrityAlgos.isEmpty() && !mHasAead) {
+ throw new IllegalArgumentException(
+ ERROR_TAG
+ + "Integrity algorithm "
+ + "must be proposed with normal ciphers in IKE proposal.");
+ }
+
+ for (IntegrityTransform transform : mProposedIntegrityAlgos) {
+ if ((transform.id == INTEGRITY_ALGORITHM_NONE) != mHasAead) {
+ throw new IllegalArgumentException(
+ ERROR_TAG
+ + "Invalid integrity algorithm configuration"
+ + " for this SA Proposal");
+ }
+ }
+
+ return mProposedIntegrityAlgos.toArray(
+ new IntegrityTransform[mProposedIntegrityAlgos.size()]);
}
- private IntegrityTransform[] buildIntegAlgosOrThrow() {
- // TODO: Validate proposed integrity algorithms according to existence of AEAD.
- throw new UnsupportedOperationException("Cannot validate user proposed algorithm.");
+ private IntegrityTransform[] buildIntegAlgosForChildOrThrow() {
+ // When building Child SA Proposal with normal-mode ciphers, there is no contraint on
+ // integrity algorithm. When building Child SA Proposal with combined-mode ciphers,
+ // mProposedIntegrityAlgos must be either empty or only have INTEGRITY_ALGORITHM_NONE.
+ for (IntegrityTransform transform : mProposedIntegrityAlgos) {
+ if (transform.id != INTEGRITY_ALGORITHM_NONE && mHasAead) {
+ throw new IllegalArgumentException(
+ ERROR_TAG
+ + "Only INTEGRITY_ALGORITHM_NONE can be"
+ + " proposed with combined-mode ciphers in any proposal.");
+ }
+ }
+
+ return mProposedIntegrityAlgos.toArray(
+ new IntegrityTransform[mProposedIntegrityAlgos.size()]);
}
- private DhGroupTransform[] buildDhGroupsOrThrow() {
- // TODO: Validate proposed DH groups according to the usage of SaProposal (for
- // IKE SA, for first Child SA or for addtional Child SA)
- throw new UnsupportedOperationException("Cannot validate user proposed algorithm.");
+ private DhGroupTransform[] buildDhGroupsForIkeOrThrow() {
+ if (mProposedDhGroups.isEmpty()) {
+ throw new IllegalArgumentException(
+ ERROR_TAG + "DH group must be proposed in IKE SA proposal.");
+ }
+
+ for (DhGroupTransform transform : mProposedDhGroups) {
+ if (transform.id == DH_GROUP_NONE) {
+ throw new IllegalArgumentException(
+ ERROR_TAG
+ + "None-value DH group must not"
+ + " be proposed in IKE SA proposal");
+ }
+ }
+
+ return mProposedDhGroups.toArray(new DhGroupTransform[mProposedDhGroups.size()]);
+ }
+
+ private DhGroupTransform[] buildDhGroupsForChildOrThrow() {
+ for (DhGroupTransform transform : mProposedDhGroups) {
+ if (transform.id != DH_GROUP_NONE && mIsFirstChild) {
+ throw new IllegalArgumentException(
+ ERROR_TAG
+ + "Only DH_GROUP_NONE can be"
+ + " proposed in first Child SA proposal.");
+ }
+ }
+ return mProposedDhGroups.toArray(new DhGroupTransform[mProposedDhGroups.size()]);
}
/** Returns a new Builder for a IKE SA Proposal. */
@@ -338,13 +403,17 @@ public final class SaProposal {
*
* @return SaProposal the validated SaProposal.
* @throws IllegalArgumentException if SaProposal is invalid.
- * */
+ */
public SaProposal buildOrThrow() {
EncryptionTransform[] encryptionTransforms = buildEncryptAlgosOrThrow();
PrfTransform[] prfTransforms = buildPrfsOrThrow();
- IntegrityTransform[] integrityTransforms = buildIntegAlgosOrThrow();
- DhGroupTransform[] dhGroupTransforms = buildDhGroupsOrThrow();
+ IntegrityTransform[] integrityTransforms =
+ mIsIkeProposal
+ ? buildIntegAlgosForIkeOrThrow()
+ : buildIntegAlgosForChildOrThrow();
+ DhGroupTransform[] dhGroupTransforms =
+ mIsIkeProposal ? buildDhGroupsForIkeOrThrow() : buildDhGroupsForChildOrThrow();
// IKE library only supports negotiating ESP Child SA.
int protocol = mIsIkeProposal ? IkePayload.PROTOCOL_ID_IKE : IkePayload.PROTOCOL_ID_ESP;
diff --git a/tests/iketests/src/java/com/android/ike/ikev2/SaProposalTest.java b/tests/iketests/src/java/com/android/ike/ikev2/SaProposalTest.java
index 522d44bc..4b0656da 100644
--- a/tests/iketests/src/java/com/android/ike/ikev2/SaProposalTest.java
+++ b/tests/iketests/src/java/com/android/ike/ikev2/SaProposalTest.java
@@ -16,19 +16,129 @@
package com.android.ike.ikev2;
+import static org.junit.Assert.assertArrayEquals;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import com.android.ike.ikev2.SaProposal.Builder;
+import com.android.ike.ikev2.message.IkePayload;
+import com.android.ike.ikev2.message.IkeSaPayload.DhGroupTransform;
+import com.android.ike.ikev2.message.IkeSaPayload.EncryptionTransform;
+import com.android.ike.ikev2.message.IkeSaPayload.IntegrityTransform;
+import com.android.ike.ikev2.message.IkeSaPayload.PrfTransform;
import org.junit.Test;
public final class SaProposalTest {
+ private final EncryptionTransform mEncryption3DesTransform;
+ private final EncryptionTransform mEncryptionAesGcm8Transform;
+ private final IntegrityTransform mIntegrityHmacSha1Transform;
+ private final IntegrityTransform mIntegrityNoneTransform;
+ private final PrfTransform mPrfAes128XCbcTransform;
+ private final DhGroupTransform mDhGroup1024Transform;
+
+ public SaProposalTest() {
+ mEncryption3DesTransform = new EncryptionTransform(SaProposal.ENCRYPTION_ALGORITHM_3DES);
+ mEncryptionAesGcm8Transform =
+ new EncryptionTransform(
+ SaProposal.ENCRYPTION_ALGORITHM_AES_GCM_8, SaProposal.KEY_LEN_AES_128);
+ mIntegrityHmacSha1Transform =
+ new IntegrityTransform(SaProposal.INTEGRITY_ALGORITHM_HMAC_SHA1_96);
+ mIntegrityNoneTransform = new IntegrityTransform(SaProposal.INTEGRITY_ALGORITHM_NONE);
+ mPrfAes128XCbcTransform = new PrfTransform(SaProposal.PSEUDORANDOM_FUNCTION_AES128_XCBC);
+ mDhGroup1024Transform = new DhGroupTransform(SaProposal.DH_GROUP_1024_BIT_MODP);
+ }
+
+ @Test
+ public void testBuildIkeSaProposalWithNormalModeCipher() throws Exception {
+ Builder builder = Builder.newIkeSaProposalBuilder();
+ SaProposal proposal =
+ builder.addEncryptionAlgorithm(SaProposal.ENCRYPTION_ALGORITHM_3DES)
+ .addIntegrityAlgorithm(SaProposal.INTEGRITY_ALGORITHM_HMAC_SHA1_96)
+ .addPseudorandomFunction(SaProposal.PSEUDORANDOM_FUNCTION_AES128_XCBC)
+ .addDhGroup(SaProposal.DH_GROUP_1024_BIT_MODP)
+ .buildOrThrow();
+
+ assertEquals(IkePayload.PROTOCOL_ID_IKE, proposal.mProtocolId);
+ assertArrayEquals(
+ new EncryptionTransform[] {mEncryption3DesTransform},
+ proposal.mEncryptionAlgorithms);
+ assertArrayEquals(
+ new IntegrityTransform[] {mIntegrityHmacSha1Transform},
+ proposal.mIntegrityAlgorithms);
+ assertArrayEquals(
+ new PrfTransform[] {mPrfAes128XCbcTransform}, proposal.mPseudorandomFunctions);
+ assertArrayEquals(new DhGroupTransform[] {mDhGroup1024Transform}, proposal.mDhGroups);
+ }
+
+ @Test
+ public void testBuildIkeSaProposalWithCombinedModeCipher() throws Exception {
+ Builder builder = Builder.newIkeSaProposalBuilder();
+ SaProposal proposal =
+ builder.addEncryptionAlgorithm(
+ SaProposal.ENCRYPTION_ALGORITHM_AES_GCM_8,
+ SaProposal.KEY_LEN_AES_128)
+ .addPseudorandomFunction(SaProposal.PSEUDORANDOM_FUNCTION_AES128_XCBC)
+ .addDhGroup(SaProposal.DH_GROUP_1024_BIT_MODP)
+ .buildOrThrow();
+
+ assertEquals(IkePayload.PROTOCOL_ID_IKE, proposal.mProtocolId);
+ assertArrayEquals(
+ new EncryptionTransform[] {mEncryptionAesGcm8Transform},
+ proposal.mEncryptionAlgorithms);
+ assertArrayEquals(
+ new PrfTransform[] {mPrfAes128XCbcTransform}, proposal.mPseudorandomFunctions);
+ assertArrayEquals(new DhGroupTransform[] {mDhGroup1024Transform}, proposal.mDhGroups);
+ assertTrue(proposal.mIntegrityAlgorithms.length == 0);
+ }
+
+ @Test
+ public void testBuildFirstChildSaProposalWithCombinedCipher() throws Exception {
+ Builder builder = Builder.newChildSaProposalBuilder(true);
+ SaProposal proposal =
+ builder.addEncryptionAlgorithm(
+ SaProposal.ENCRYPTION_ALGORITHM_AES_GCM_8,
+ SaProposal.KEY_LEN_AES_128)
+ .addIntegrityAlgorithm(SaProposal.INTEGRITY_ALGORITHM_NONE)
+ .buildOrThrow();
+
+ assertEquals(IkePayload.PROTOCOL_ID_ESP, proposal.mProtocolId);
+ assertArrayEquals(
+ new EncryptionTransform[] {mEncryptionAesGcm8Transform},
+ proposal.mEncryptionAlgorithms);
+ assertArrayEquals(
+ new IntegrityTransform[] {mIntegrityNoneTransform}, proposal.mIntegrityAlgorithms);
+ assertTrue(proposal.mPseudorandomFunctions.length == 0);
+ assertTrue(proposal.mDhGroups.length == 0);
+ }
+
+ @Test
+ public void testBuildAdditionalChildSaProposalWithNormalCipher() throws Exception {
+ Builder builder = Builder.newChildSaProposalBuilder(false);
+
+ SaProposal proposal =
+ builder.addEncryptionAlgorithm(SaProposal.ENCRYPTION_ALGORITHM_3DES)
+ .addIntegrityAlgorithm(SaProposal.INTEGRITY_ALGORITHM_NONE)
+ .addDhGroup(SaProposal.DH_GROUP_1024_BIT_MODP)
+ .buildOrThrow();
+
+ assertEquals(IkePayload.PROTOCOL_ID_ESP, proposal.mProtocolId);
+ assertArrayEquals(
+ new EncryptionTransform[] {mEncryption3DesTransform},
+ proposal.mEncryptionAlgorithms);
+ assertArrayEquals(
+ new IntegrityTransform[] {mIntegrityNoneTransform}, proposal.mIntegrityAlgorithms);
+ assertArrayEquals(new DhGroupTransform[] {mDhGroup1024Transform}, proposal.mDhGroups);
+ assertTrue(proposal.mPseudorandomFunctions.length == 0);
+ }
+
@Test
public void testBuildEncryptAlgosWithNoAlgorithm() throws Exception {
Builder builder = Builder.newIkeSaProposalBuilder();
try {
builder.buildOrThrow();
- fail("Encryption algorithm is not provided.");
+ fail("Expected to fail when no encryption algorithm is proposed.");
} catch (IllegalArgumentException expected) {
}
@@ -39,7 +149,7 @@ public final class SaProposalTest {
Builder builder = Builder.newIkeSaProposalBuilder();
try {
builder.addEncryptionAlgorithm(-1);
- fail("Encryption algorithm is not recognized.");
+ fail("Expected to fail when unrecognized encryption algorithm is proposed.");
} catch (IllegalArgumentException expected) {
}
@@ -51,7 +161,139 @@ public final class SaProposalTest {
try {
builder.addEncryptionAlgorithm(SaProposal.ENCRYPTION_ALGORITHM_3DES)
.addEncryptionAlgorithm(SaProposal.ENCRYPTION_ALGORITHM_AES_GCM_12);
- fail("Expect failure when normal and combined-mode ciphers are proposed together.");
+ fail(
+ "Expected to fail when "
+ + "normal and combined-mode ciphers are proposed together.");
+ } catch (IllegalArgumentException expected) {
+
+ }
+ }
+
+ @Test
+ public void testBuildIkeProposalWithoutPrf() throws Exception {
+ Builder builder = Builder.newIkeSaProposalBuilder();
+ try {
+ builder.addEncryptionAlgorithm(SaProposal.ENCRYPTION_ALGORITHM_3DES).buildOrThrow();
+ fail("Expected to fail when PRF is not provided in IKE SA proposal.");
+ } catch (IllegalArgumentException expected) {
+
+ }
+ }
+
+ @Test
+ public void testBuildChildProposalWithPrf() throws Exception {
+ Builder builder = Builder.newChildSaProposalBuilder(false);
+ try {
+ builder.addEncryptionAlgorithm(SaProposal.ENCRYPTION_ALGORITHM_3DES)
+ .addPseudorandomFunction(SaProposal.PSEUDORANDOM_FUNCTION_HMAC_SHA1)
+ .buildOrThrow();
+
+ fail("Expected to fail when PRF is provided in Child SA proposal.");
+ } catch (IllegalArgumentException expected) {
+
+ }
+ }
+
+ // Test throwing exception when building IKE SA Proposal with AEAD and not-none integrity
+ // algorithm.
+ @Test
+ public void testBuildAeadWithIntegrityAlgo() throws Exception {
+ Builder builder = Builder.newChildSaProposalBuilder(false);
+ try {
+ builder.addEncryptionAlgorithm(SaProposal.ENCRYPTION_ALGORITHM_AES_GCM_12)
+ .addIntegrityAlgorithm(SaProposal.INTEGRITY_ALGORITHM_NONE)
+ .addIntegrityAlgorithm(SaProposal.INTEGRITY_ALGORITHM_HMAC_SHA1_96)
+ .buildOrThrow();
+
+ fail("Expected to fail when not-none integrity algorithm is proposed with AEAD");
+ } catch (IllegalArgumentException expected) {
+
+ }
+ }
+
+ // Test throwing exception when building IKE SA Proposal with normal mode cipher and without
+ // integrity algorithm.
+ @Test
+ public void testBuildIkeProposalNormalCipherWithoutIntegrityAlgo() throws Exception {
+ Builder builder = Builder.newChildSaProposalBuilder(false);
+ try {
+ builder.addEncryptionAlgorithm(SaProposal.ENCRYPTION_ALGORITHM_3DES)
+ .addPseudorandomFunction(SaProposal.PSEUDORANDOM_FUNCTION_HMAC_SHA1)
+ .buildOrThrow();
+
+ fail(
+ "Expected to fail when"
+ + " no integrity algorithm is proposed with non-combined cipher");
+ } catch (IllegalArgumentException expected) {
+
+ }
+ }
+
+ // Test throwing exception when building IKE SA Proposal with normal mode cipher and none-value
+ // integrity algorithm.
+ @Test
+ public void testBuildIkeProposalNormalCipherWithNoneValueIntegrityAlgo() throws Exception {
+ Builder builder = Builder.newChildSaProposalBuilder(false);
+ try {
+ builder.addEncryptionAlgorithm(SaProposal.ENCRYPTION_ALGORITHM_3DES)
+ .addPseudorandomFunction(SaProposal.PSEUDORANDOM_FUNCTION_HMAC_SHA1)
+ .addIntegrityAlgorithm(SaProposal.INTEGRITY_ALGORITHM_NONE)
+ .addIntegrityAlgorithm(SaProposal.INTEGRITY_ALGORITHM_HMAC_SHA1_96)
+ .buildOrThrow();
+
+ fail(
+ "Expected to fail when none-value integrity algorithm is proposed"
+ + " with non-combined cipher");
+ } catch (IllegalArgumentException expected) {
+
+ }
+ }
+
+ @Test
+ public void testBuildIkeProposalWithoutDhGroup() throws Exception {
+ Builder builder = Builder.newIkeSaProposalBuilder();
+ try {
+ builder.addEncryptionAlgorithm(SaProposal.ENCRYPTION_ALGORITHM_3DES)
+ .addIntegrityAlgorithm(SaProposal.INTEGRITY_ALGORITHM_HMAC_SHA1_96)
+ .addPseudorandomFunction(SaProposal.PSEUDORANDOM_FUNCTION_AES128_XCBC)
+ .buildOrThrow();
+
+ fail("Expected to fail when no DH Group is proposed in IKE SA proposal.");
+ } catch (IllegalArgumentException expected) {
+
+ }
+ }
+
+ @Test
+ public void testBuildIkeProposalWithNoneValueDhGroup() throws Exception {
+ Builder builder = Builder.newIkeSaProposalBuilder();
+ try {
+ builder.addEncryptionAlgorithm(SaProposal.ENCRYPTION_ALGORITHM_3DES)
+ .addIntegrityAlgorithm(SaProposal.INTEGRITY_ALGORITHM_HMAC_SHA1_96)
+ .addPseudorandomFunction(SaProposal.PSEUDORANDOM_FUNCTION_AES128_XCBC)
+ .addDhGroup(SaProposal.DH_GROUP_1024_BIT_MODP)
+ .addDhGroup(SaProposal.DH_GROUP_NONE)
+ .buildOrThrow();
+
+ fail("Expected to fail when none-value DH Group is proposed in IKE SA proposal.");
+ } catch (IllegalArgumentException expected) {
+
+ }
+ }
+
+ // Test throwing exception when building first Child SA Proposal with not-none-value DH Group.
+ @Test
+ public void testBuildFirstChildProposalWithNotNoneValueDhGroup() throws Exception {
+ Builder builder = Builder.newChildSaProposalBuilder(true);
+ try {
+ builder.addEncryptionAlgorithm(SaProposal.ENCRYPTION_ALGORITHM_3DES)
+ .addIntegrityAlgorithm(SaProposal.INTEGRITY_ALGORITHM_HMAC_SHA1_96)
+ .addDhGroup(SaProposal.DH_GROUP_1024_BIT_MODP)
+ .buildOrThrow();
+
+ fail(
+ "Expected to fail when"
+ + " not-none-value DH Group is proposed in first Child SA proposal.");
} catch (IllegalArgumentException expected) {
}
diff --git a/tests/iketests/src/java/com/android/ike/ikev2/message/IkeSaPayloadTest.java b/tests/iketests/src/java/com/android/ike/ikev2/message/IkeSaPayloadTest.java
index d2db6db9..cfde10e5 100644
--- a/tests/iketests/src/java/com/android/ike/ikev2/message/IkeSaPayloadTest.java
+++ b/tests/iketests/src/java/com/android/ike/ikev2/message/IkeSaPayloadTest.java
@@ -18,6 +18,7 @@ package com.android.ike.ikev2.message;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotEquals;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import static org.mockito.Matchers.any;
@@ -383,6 +384,32 @@ public final class IkeSaPayloadTest {
}
@Test
+ public void testTransformEquals() throws Exception {
+ EncryptionTransform mEncrAesGcm8Key128TransformLeft =
+ new EncryptionTransform(
+ SaProposal.ENCRYPTION_ALGORITHM_AES_GCM_8, SaProposal.KEY_LEN_AES_128);
+ EncryptionTransform mEncrAesGcm8Key128TransformRight =
+ new EncryptionTransform(
+ SaProposal.ENCRYPTION_ALGORITHM_AES_GCM_8, SaProposal.KEY_LEN_AES_128);
+
+ assertEquals(mEncrAesGcm8Key128TransformLeft, mEncrAesGcm8Key128TransformRight);
+
+ EncryptionTransform mEncrAesGcm8Key192TransformLeft =
+ new EncryptionTransform(
+ SaProposal.ENCRYPTION_ALGORITHM_AES_GCM_8, SaProposal.KEY_LEN_AES_192);
+
+ assertNotEquals(mEncrAesGcm8Key128TransformLeft, mEncrAesGcm8Key192TransformLeft);
+
+ IntegrityTransform mIntegHmacSha1TransformLeft =
+ new IntegrityTransform(SaProposal.INTEGRITY_ALGORITHM_HMAC_SHA1_96);
+ IntegrityTransform mIntegHmacSha1TransformRight =
+ new IntegrityTransform(SaProposal.INTEGRITY_ALGORITHM_HMAC_SHA1_96);
+
+ assertNotEquals(mEncrAesGcm8Key128TransformLeft, mIntegHmacSha1TransformLeft);
+ assertEquals(mIntegHmacSha1TransformLeft, mIntegHmacSha1TransformRight);
+ }
+
+ @Test
public void testDecodeSingleProposal() throws Exception {
byte[] inputPacket = TestUtils.hexStringToByteArray(PROPOSAL_RAW_PACKET);
ByteBuffer inputBuffer = ByteBuffer.wrap(inputPacket);