diff options
3 files changed, 152 insertions, 26 deletions
diff --git a/src/java/com/android/ike/ikev2/SaProposal.java b/src/java/com/android/ike/ikev2/SaProposal.java index 8fa0743d..a88e550f 100644 --- a/src/java/com/android/ike/ikev2/SaProposal.java +++ b/src/java/com/android/ike/ikev2/SaProposal.java @@ -84,6 +84,34 @@ public final class SaProposal { SUPPORTED_PSEUDORANDOM_FUNCTION.add(PSEUDORANDOM_FUNCTION_AES128_XCBC); } + @Retention(RetentionPolicy.SOURCE) + @IntDef({ + INTEGRITY_ALGORITHM_HMAC_SHA1_96, + INTEGRITY_ALGORITHM_AES_XCBC_96, + INTEGRITY_ALGORITHM_HMAC_SHA2_256_128, + INTEGRITY_ALGORITHM_HMAC_SHA2_384_192, + INTEGRITY_ALGORITHM_HMAC_SHA2_512_256 + }) + + public @interface IntegrityAlgorithm {} + + public static final int INTEGRITY_ALGORITHM_HMAC_SHA1_96 = 2; + public static final int INTEGRITY_ALGORITHM_AES_XCBC_96 = 5; + public static final int INTEGRITY_ALGORITHM_HMAC_SHA2_256_128 = 12; + public static final int INTEGRITY_ALGORITHM_HMAC_SHA2_384_192 = 13; + public static final int INTEGRITY_ALGORITHM_HMAC_SHA2_512_256 = 14; + + private static final Set<Integer> SUPPORTED_INTEGRITY_ALGORITHM; + + static { + SUPPORTED_INTEGRITY_ALGORITHM = new ArraySet<>(); + SUPPORTED_INTEGRITY_ALGORITHM.add(INTEGRITY_ALGORITHM_HMAC_SHA1_96); + SUPPORTED_INTEGRITY_ALGORITHM.add(INTEGRITY_ALGORITHM_AES_XCBC_96); + SUPPORTED_INTEGRITY_ALGORITHM.add(INTEGRITY_ALGORITHM_HMAC_SHA2_256_128); + SUPPORTED_INTEGRITY_ALGORITHM.add(INTEGRITY_ALGORITHM_HMAC_SHA2_384_192); + SUPPORTED_INTEGRITY_ALGORITHM.add(INTEGRITY_ALGORITHM_HMAC_SHA2_512_256); + } + /** * Check if the provided algorithm is a supported encryption algorithm. * @@ -104,6 +132,16 @@ public final class SaProposal { return SUPPORTED_PSEUDORANDOM_FUNCTION.contains(algorithm); } + /** + * Check if the provided algorithm is a supported integrity algorithm. + * + * @param algorithm IKE standard integrity algorithm id. + * @return true if the provided algorithm is a supported integrity algorithm. + */ + public static boolean isSupportedIntegrityAlgorithm(@IntegrityAlgorithm int algorithm) { + return SUPPORTED_INTEGRITY_ALGORITHM.contains(algorithm); + } + // TODO: Implement constructing SaProposal with a Builder that supports adding // encryption/integrity algorithms, prf, and DH Group. } diff --git a/src/java/com/android/ike/ikev2/message/IkeSaPayload.java b/src/java/com/android/ike/ikev2/message/IkeSaPayload.java index 8ce034ae..6234cbe5 100644 --- a/src/java/com/android/ike/ikev2/message/IkeSaPayload.java +++ b/src/java/com/android/ike/ikev2/message/IkeSaPayload.java @@ -24,6 +24,7 @@ import android.util.ArraySet; import android.util.Pair; import com.android.ike.ikev2.SaProposal; +import com.android.ike.ikev2.SaProposal.IntegrityAlgorithm; import com.android.ike.ikev2.exceptions.IkeException; import com.android.ike.ikev2.exceptions.InvalidSyntaxException; import com.android.internal.annotations.VisibleForTesting; @@ -44,7 +45,7 @@ import java.util.Set; public final class IkeSaPayload extends IkePayload { public final List<Proposal> proposalList; /** - * Construct an instance of IkeSaPayload in the context of IkePayloadFactory. + * Construct an instance of IkeSaPayload for decoding an inbound packet. * * @param critical indicates if this payload is critical. Ignored in supported payload as * instructed by the RFC 7296. @@ -220,7 +221,7 @@ public final class IkeSaPayload extends IkePayload { public final int id; public final boolean isSupported; - /** Construct an instance of Transform in the context of {@link SaProposal} */ + /** Construct an instance of Transform for building an outbound packet. */ protected Transform(int type, int id) { this.type = type; this.id = id; @@ -231,7 +232,7 @@ public final class IkeSaPayload extends IkePayload { this.isSupported = true; } - /** Construct an instance of Transform in the context of {@link Transform} */ + /** Construct an instance of Transform for decoding an inbound packet. */ protected Transform(int type, int id, List<Attribute> attributeList) { this.type = type; this.id = id; @@ -268,7 +269,9 @@ public final class IkeSaPayload extends IkePayload { return new EncryptionTransform(id, attributeList); case TRANSFORM_TYPE_PRF: return new PrfTransform(id, attributeList); - // TODO: Add Integrity algorithm, DhGroup and ESN + case TRANSFORM_TYPE_INTEG: + return new IntegrityTransform(id, attributeList); + // TODO: Add DhGroup and ESN default: return new UnrecognizedTransform(type, id, attributeList); } @@ -286,19 +289,16 @@ public final class IkeSaPayload extends IkePayload { } } - // Check if this Transform ID is supported. - protected abstract boolean isSupportedTransformId(int id); - - // Check if there is Attribute with unrecognized type. + // Check if there is Attribute with unrecognized type. Most Transforms do not have any + // supported attribute types. Return true by default, and override in Transforms that + // support Transform Attributes. protected boolean hasUnrecognizedAttribute(List<Attribute> attributeList) { - for (Attribute attr : attributeList) { - if (attr instanceof UnrecognizedAttribute) { - return true; - } - } - return false; + return true; } + // Check if this Transform ID is supported. + protected abstract boolean isSupportedTransformId(int id); + /** * Get Tranform Type as a String. * @@ -328,9 +328,19 @@ public final class IkeSaPayload extends IkePayload { return SaProposal.isSupportedEncryptionAlgorithm(id); } + @Override + protected boolean hasUnrecognizedAttribute(List<Attribute> attributeList) { + for (Attribute attr : attributeList) { + if (attr instanceof UnrecognizedAttribute) { + return true; + } + } + return false; + } + /** - * Contruct an instance of EncryptionTransform in the context of {@link SaProposal} with - * fixed key length. + * Contruct an instance of EncryptionTransform with fixed key length for building an + * outbound packet. * * @param id the IKE standard Transform ID. */ @@ -339,8 +349,8 @@ public final class IkeSaPayload extends IkePayload { } /** - * Contruct an instance of EncryptionTransform in the context of {@link SaProposal} with - * variable key length. + * Contruct an instance of EncryptionTransform with variable key length for building an + * outbound packet. * * @param id the IKE standard Transform ID. * @param keyLength the specified key length of this encryption algorithm. @@ -357,8 +367,7 @@ public final class IkeSaPayload extends IkePayload { } /** - * Contruct an instance of EncryptionTransform in the context of abstract class {@link - * Transform}. + * Contruct an instance of EncryptionTransform for decoding an inbound packet. * * @param id the IKE standard Transform ID. * @param attributeList the decoded list of Attribute. @@ -440,8 +449,6 @@ public final class IkeSaPayload extends IkePayload { /** * PrfTransform represents an pseudorandom function. * - * <p>Currently it does not have any supported {@link Attribute}. - * * @see <a href="https://tools.ietf.org/html/rfc7296#section-3.3.2">RFC 7296, Internet Key * Exchange Protocol Version 2 (IKEv2). */ @@ -452,7 +459,7 @@ public final class IkeSaPayload extends IkePayload { } /** - * Contruct an instance of PrfTransform in the context of {@link SaProposal}. + * Contruct an instance of PrfTransform for building an outbound packet. * * @param id the IKE standard Transform ID. */ @@ -461,7 +468,7 @@ public final class IkeSaPayload extends IkePayload { } /** - * Contruct an instance of PrfTransform in the context of abstract class {@link Transform}. + * Contruct an instance of PrfTransform for decoding an inbound packet. * * @param id the IKE standard Transform ID. * @param attributeList the decoded list of Attribute. @@ -479,6 +486,45 @@ public final class IkeSaPayload extends IkePayload { } /** + * IntegrityTransform represents an integrity algorithm. + * + * @see <a href="https://tools.ietf.org/html/rfc7296#section-3.3.2">RFC 7296, Internet Key + * Exchange Protocol Version 2 (IKEv2). + */ + public static final class IntegrityTransform extends Transform { + @Override + protected boolean isSupportedTransformId(int id) { + return SaProposal.isSupportedIntegrityAlgorithm(id); + } + + /** + * Contruct an instance of IntegrityTransform for building an outbound packet. + * + * @param id the IKE standard Transform ID. + */ + public IntegrityTransform(@IntegrityAlgorithm int id) { + super(Transform.TRANSFORM_TYPE_INTEG, id); + } + + /** + * Contruct an instance of IntegrityTransform for decoding an inbound packet. + * + * @param id the IKE standard Transform ID. + * @param attributeList the decoded list of Attribute. + * @throws InvalidSyntaxException for syntax error. + */ + protected IntegrityTransform(int id, List<Attribute> attributeList) + throws InvalidSyntaxException { + super(Transform.TRANSFORM_TYPE_INTEG, id, attributeList); + } + + @Override + public String getTransformTypeString() { + return "Integrity Algorithm"; + } + } + + /** * UnrecognizedTransform represents a Transform with unrecognized Transform Type. * * <p>Proposals containing an UnrecognizedTransform should be ignored. 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 20bc67e0..a76a89c8 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 @@ -33,6 +33,7 @@ import com.android.ike.ikev2.exceptions.InvalidSyntaxException; import com.android.ike.ikev2.message.IkeSaPayload.Attribute; import com.android.ike.ikev2.message.IkeSaPayload.AttributeDecoder; import com.android.ike.ikev2.message.IkeSaPayload.EncryptionTransform; +import com.android.ike.ikev2.message.IkeSaPayload.IntegrityTransform; import com.android.ike.ikev2.message.IkeSaPayload.KeyLengthAttribute; import com.android.ike.ikev2.message.IkeSaPayload.PrfTransform; import com.android.ike.ikev2.message.IkeSaPayload.Proposal; @@ -73,6 +74,8 @@ public final class IkeSaPayloadTest { + "00000804000012000000080400000e"; private static final String ENCR_TRANSFORM_RAW_PACKET = "0300000c0100000c800e0080"; private static final String PRF_TRANSFORM_RAW_PACKET = "0000000802000002"; + private static final String INTEG_TRANSFORM_RAW_PACKET = "0300000803000002"; + private static final int TRANSFORM_TYPE_POSITION = 4; private static final int TRANSFORM_ID_POSITION = 7; @@ -151,7 +154,7 @@ public final class IkeSaPayloadTest { } @Test - public void testConstructEncryptionTransformWithUnSupportedId() throws Exception { + public void testConstructEncryptionTransformWithUnsupportedId() throws Exception { try { new EncryptionTransform(SaProposal.ENCRYPTION_ALGORITHM_3DES + 1); fail("Expected IllegalArgumentException for unsupported Transform ID"); @@ -184,7 +187,7 @@ public final class IkeSaPayloadTest { } @Test - public void testConstructPrfTransformWithUnSupportedId() throws Exception { + public void testConstructPrfTransformWithUnsupportedId() throws Exception { try { new PrfTransform(SaProposal.PSEUDORANDOM_FUNCTION_AES128_XCBC + 1); fail("Expected IllegalArgumentException for unsupported Transform ID"); @@ -193,6 +196,45 @@ public final class IkeSaPayloadTest { } @Test + public void testDecodeIntegrityTransform() throws Exception { + byte[] inputPacket = TestUtils.hexStringToByteArray(INTEG_TRANSFORM_RAW_PACKET); + ByteBuffer inputBuffer = ByteBuffer.wrap(inputPacket); + + when(mMockedAttributeDecoder.decodeAttributes(anyInt(), any())) + .thenReturn(new LinkedList<Attribute>()); + Transform.sAttributeDecoder = mMockedAttributeDecoder; + + Transform transform = Transform.readFrom(inputBuffer); + assertEquals(Transform.TRANSFORM_TYPE_INTEG, transform.type); + assertEquals(SaProposal.INTEGRITY_ALGORITHM_HMAC_SHA1_96, transform.id); + assertTrue(transform.isSupported); + } + + @Test + public void testDecodeIntegrityTransformWithUnrecognizedAttribute() throws Exception { + byte[] inputPacket = TestUtils.hexStringToByteArray(INTEG_TRANSFORM_RAW_PACKET); + ByteBuffer inputBuffer = ByteBuffer.wrap(inputPacket); + + when(mMockedAttributeDecoder.decodeAttributes(anyInt(), any())) + .thenReturn(mAttributeListWithKeyLength128); + Transform.sAttributeDecoder = mMockedAttributeDecoder; + + Transform transform = Transform.readFrom(inputBuffer); + assertEquals(Transform.TRANSFORM_TYPE_INTEG, transform.type); + assertEquals(SaProposal.INTEGRITY_ALGORITHM_HMAC_SHA1_96, transform.id); + assertFalse(transform.isSupported); + } + + @Test + public void testConstructIntegrityTransformWithUnsupportedId() throws Exception { + try { + new IntegrityTransform(SaProposal.INTEGRITY_ALGORITHM_HMAC_SHA1_96 + 1); + fail("Expected IllegalArgumentException for unsupported Transform ID"); + } catch (IllegalArgumentException expected) { + } + } + + @Test public void testDecodeUnrecognizedTransform() throws Exception { byte[] inputPacket = TestUtils.hexStringToByteArray(ENCR_TRANSFORM_RAW_PACKET); inputPacket[TRANSFORM_TYPE_POSITION] = 6; |