Merge "Encode unencrypted IKE message to byte array"
diff --git a/src/java/com/android/ike/ikev2/message/IkeHeader.java b/src/java/com/android/ike/ikev2/message/IkeHeader.java
index cd41516..851442b 100644
--- a/src/java/com/android/ike/ikev2/message/IkeHeader.java
+++ b/src/java/com/android/ike/ikev2/message/IkeHeader.java
@@ -47,14 +47,14 @@
 
     @Retention(RetentionPolicy.SOURCE)
     @IntDef({
-        EXCHANGE_TYPE_IKE_INIT_SA,
+        EXCHANGE_TYPE_IKE_SA_INIT,
         EXCHANGE_TYPE_IKE_AUTH,
         EXCHANGE_TYPE_CREATE_CHILD_SA,
         EXCHANGE_TYPE_INFORMATIONAL
     })
     public @interface ExchangeType {}
 
-    public static final int EXCHANGE_TYPE_IKE_INIT_SA = 34;
+    public static final int EXCHANGE_TYPE_IKE_SA_INIT = 34;
     public static final int EXCHANGE_TYPE_IKE_AUTH = 35;
     public static final int EXCHANGE_TYPE_CREATE_CHILD_SA = 36;
     public static final int EXCHANGE_TYPE_INFORMATIONAL = 37;
@@ -150,7 +150,7 @@
             // error.
             throw new InvalidSyntaxException("Major version is smaller than 2.");
         }
-        if (exchangeType < EXCHANGE_TYPE_IKE_INIT_SA
+        if (exchangeType < EXCHANGE_TYPE_IKE_SA_INIT
                 || exchangeType > EXCHANGE_TYPE_INFORMATIONAL) {
             throw new InvalidSyntaxException("Invalid IKE Exchange Type.");
         }
diff --git a/src/java/com/android/ike/ikev2/message/IkeMessage.java b/src/java/com/android/ike/ikev2/message/IkeMessage.java
index 118e2f0..0261ec2 100644
--- a/src/java/com/android/ike/ikev2/message/IkeMessage.java
+++ b/src/java/com/android/ike/ikev2/message/IkeMessage.java
@@ -138,4 +138,22 @@
 
         return byteBuffer.array();
     }
+
+    // TODO: Add a method that takes cyptographic algorithms and parameters to encrypt all payloads
+    // to a byte array.
+
+    /**
+     * Encode entire IKE message to a byte array.
+     *
+     * @param encodedIkeBody IKE message body in byte array. IKE message body is encrypted and
+     *     integrity protected except in an IKE_SA_INIT message.
+     * @return the entire encoded IKE message as a byte array.
+     */
+    public byte[] encode(byte[] encodedIkeBody) {
+        ByteBuffer outputBuffer =
+                ByteBuffer.allocate(IkeHeader.IKE_HEADER_LENGTH + encodedIkeBody.length);
+        ikeHeader.encodeToByteBuffer(outputBuffer);
+        outputBuffer.put(encodedIkeBody);
+        return outputBuffer.array();
+    }
 }
diff --git a/tests/iketests/src/java/com/android/ike/ikev2/message/IkeHeaderTest.java b/tests/iketests/src/java/com/android/ike/ikev2/message/IkeHeaderTest.java
index fd4ca91..70b2d65 100644
--- a/tests/iketests/src/java/com/android/ike/ikev2/message/IkeHeaderTest.java
+++ b/tests/iketests/src/java/com/android/ike/ikev2/message/IkeHeaderTest.java
@@ -54,7 +54,7 @@
     private static final byte IKE_MINOR_VERSION = 0;
 
     @IkeHeader.ExchangeType
-    private static final int IKE_EXCHANGE_TYPE = IkeHeader.EXCHANGE_TYPE_IKE_INIT_SA;
+    private static final int IKE_EXCHANGE_TYPE = IkeHeader.EXCHANGE_TYPE_IKE_SA_INIT;
 
     private static final int IKE_MSG_ID = 0;
     private static final int IKE_MSG_LENGTH = 336;
diff --git a/tests/iketests/src/java/com/android/ike/ikev2/message/IkeMessageTest.java b/tests/iketests/src/java/com/android/ike/ikev2/message/IkeMessageTest.java
index 8978f68..e2a1c9e 100644
--- a/tests/iketests/src/java/com/android/ike/ikev2/message/IkeMessageTest.java
+++ b/tests/iketests/src/java/com/android/ike/ikev2/message/IkeMessageTest.java
@@ -16,6 +16,7 @@
 
 package com.android.ike.ikev2.message;
 
+import static org.junit.Assert.assertArrayEquals;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.fail;
 
@@ -30,9 +31,10 @@
 import java.nio.ByteBuffer;
 
 public final class IkeMessageTest {
-    private static final String IKE_SA_INIT_RAW_PACKET =
-            "8f54bf6d8b48e6e100000000000000002120220800000000"
-                    + "00000150220000300000002c010100040300000c0100000c"
+    private static final String IKE_SA_INIT_HEADER_RAW_PACKET =
+            "8f54bf6d8b48e6e10000000000000000212022080000000000000150";
+    private static final String IKE_SA_INIT_BODY_RAW_PACKET =
+            "220000300000002c010100040300000c0100000c"
                     + "800e00800300000803000002030000080400000200000008"
                     + "020000022800008800020000b4a2faf4bb54878ae21d6385"
                     + "12ece55d9236fc5046ab6cef82220f421f3ce6361faf3656"
@@ -45,6 +47,8 @@
                     + "881eab2051d8663f421d10b02b00001c00004005d915368c"
                     + "a036004cb578ae3e3fb268509aeab1900000002069936922"
                     + "8741c6d4ca094c93e242c9de19e7b7c60000000500000500";
+    private static final String IKE_SA_INIT_RAW_PACKET =
+            IKE_SA_INIT_HEADER_RAW_PACKET + IKE_SA_INIT_BODY_RAW_PACKET;
 
     private static final int FIRST_PAYLOAD_TYPE_POSITION = 16;
     private static final int VERSION_POSITION = 17;
@@ -182,4 +186,15 @@
                 || payloadType == IkePayload.PAYLOAD_TYPE_VENDOR
                 || payloadType == IkePayload.PAYLOAD_TYPE_SK);
     }
+
+    @Test
+    public void testEncode() throws Exception {
+        byte[] inputPacket = TestUtils.hexStringToByteArray(IKE_SA_INIT_RAW_PACKET);
+        byte[] ikeBodyBytes = TestUtils.hexStringToByteArray(IKE_SA_INIT_BODY_RAW_PACKET);
+        IkeHeader header = new IkeHeader(inputPacket);
+        IkeMessage message = IkeMessage.decode(header, inputPacket);
+
+        byte[] encodedIkeMessage = message.encode(ikeBodyBytes);
+        assertArrayEquals(inputPacket, encodedIkeMessage);
+    }
 }