blob: fcb3eff6b10b9447e2d6d0cbb298a028c9100ac0 [file] [log] [blame]
/*
* Copyright (C) 2019 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.ike.ikev2.message;
import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.fail;
import org.junit.Before;
import org.junit.Test;
import java.security.GeneralSecurityException;
import java.util.Arrays;
import javax.crypto.Cipher;
import javax.crypto.Mac;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
public final class IkeEncryptedPayloadBodyTest {
private static final String IKE_AUTH_INIT_REQUEST_HEADER =
"5f54bf6d8b48e6e1909232b3d1edcb5c2e20230800000001000000ec";
private static final String IKE_AUTH_INIT_REQUEST_SK_HEADER = "230000d0";
private static final String IKE_AUTH_INIT_REQUEST_IV = "b9132b7bb9f658dfdc648e5017a6322a";
private static final String IKE_AUTH_INIT_REQUEST_ENCRYPT_PADDED_DATA =
"030c316ce55f365760d46426ce5cfc78bd1ed9abff63eb9594c1bd58"
+ "46de333ecd3ea2b705d18293b130395300ba92a351041345"
+ "0a10525cea51b2753b4e92b081fd78d995659a98f742278f"
+ "f9b8fd3e21554865c15c79a5134d66b2744966089e416c60"
+ "a274e44a9a3f084eb02f3bdce1e7de9de8d9a62773ab563b"
+ "9a69ba1db03c752acb6136452b8a86c41addb4210d68c423"
+ "efed80e26edca5fa3fe5d0a5ca9375ce332c474b93fb1fa3"
+ "59eb4e81";
private static final String IKE_AUTH_INIT_REQUEST_CHECKSUM = "ae6e0f22abdad69ba8007d50";
private static final String IKE_AUTH_INIT_REQUEST_UNENCRYPTED_DATA =
"2400000c010000000a50500d2700000c010000000a505050"
+ "2100001c02000000df7c038aefaaa32d3f44b228b52a3327"
+ "44dfb2c12c00002c00000028010304032ad4c0a20300000c"
+ "0100000c800e008003000008030000020000000805000000"
+ "2d00001801000000070000100000ffff00000000ffffffff"
+ "2900001801000000070000100000ffff00000000ffffffff"
+ "29000008000040000000000c0000400100000001";
private static final String IKE_AUTH_INIT_REQUEST_PADDING = "0000000000000000000000";
private static final int HMAC_SHA1_CHECKSUM_LEN = 12;
private static final String ENCR_KEY_FROM_INIT_TO_RESP = "5cbfd33f75796c0188c4a3a546aec4a1";
private static final String INTE_KEY_FROM_INIT_TO_RESP =
"554fbf5a05b7f511e05a30ce23d874db9ef55e51";
private static final String ENCR_ALGO_AES_CBC = "AES/CBC/NoPadding";
private static final String INTE_ALGO_HMAC_SHA1 = "HmacSHA1";
private Cipher mAesCbcCipher;
private SecretKey mAesCbcKey;
private Mac mHmacSha1IntegrityMac;
private byte[] mDataToPadAndEncrypt;
private byte[] mDataToAuthenticate;
private byte[] mEncryptedPaddedData;
private byte[] mIkeMessage;
private byte[] mChecksum;
private byte[] mIv;
private byte[] mPadding;
// TODO: Add tests for authenticating and decrypting received message.
@Before
public void setUp() throws Exception {
mDataToPadAndEncrypt =
TestUtils.hexStringToByteArray(IKE_AUTH_INIT_REQUEST_UNENCRYPTED_DATA);
String hexStringToAuthenticate =
IKE_AUTH_INIT_REQUEST_HEADER
+ IKE_AUTH_INIT_REQUEST_SK_HEADER
+ IKE_AUTH_INIT_REQUEST_IV
+ IKE_AUTH_INIT_REQUEST_ENCRYPT_PADDED_DATA;
mDataToAuthenticate = TestUtils.hexStringToByteArray(hexStringToAuthenticate);
mEncryptedPaddedData =
TestUtils.hexStringToByteArray(IKE_AUTH_INIT_REQUEST_ENCRYPT_PADDED_DATA);
mIkeMessage =
TestUtils.hexStringToByteArray(
IKE_AUTH_INIT_REQUEST_HEADER
+ IKE_AUTH_INIT_REQUEST_SK_HEADER
+ IKE_AUTH_INIT_REQUEST_IV
+ IKE_AUTH_INIT_REQUEST_ENCRYPT_PADDED_DATA
+ IKE_AUTH_INIT_REQUEST_CHECKSUM);
mChecksum = TestUtils.hexStringToByteArray(IKE_AUTH_INIT_REQUEST_CHECKSUM);
mIv = TestUtils.hexStringToByteArray(IKE_AUTH_INIT_REQUEST_IV);
mPadding = TestUtils.hexStringToByteArray(IKE_AUTH_INIT_REQUEST_PADDING);
mAesCbcCipher = Cipher.getInstance(ENCR_ALGO_AES_CBC, IkeMessage.getSecurityProvider());
byte[] encryptKeyBytes = TestUtils.hexStringToByteArray(ENCR_KEY_FROM_INIT_TO_RESP);
mAesCbcKey = new SecretKeySpec(encryptKeyBytes, ENCR_ALGO_AES_CBC);
mHmacSha1IntegrityMac =
Mac.getInstance(INTE_ALGO_HMAC_SHA1, IkeMessage.getSecurityProvider());
byte[] integrityKeyBytes = TestUtils.hexStringToByteArray(INTE_KEY_FROM_INIT_TO_RESP);
SecretKeySpec integrityKey = new SecretKeySpec(integrityKeyBytes, INTE_ALGO_HMAC_SHA1);
mHmacSha1IntegrityMac.init(integrityKey);
}
@Test
public void testCalculateChecksum() throws Exception {
byte[] calculatedChecksum =
IkeEncryptedPayloadBody.calculateChecksum(
mDataToAuthenticate, mHmacSha1IntegrityMac, HMAC_SHA1_CHECKSUM_LEN);
assertArrayEquals(mChecksum, calculatedChecksum);
}
@Test
public void testValidateChecksum() throws Exception {
IkeEncryptedPayloadBody.validateChecksumOrThrow(
mDataToAuthenticate, mHmacSha1IntegrityMac, mChecksum);
}
@Test
public void testThrowForInvalidChecksum() throws Exception {
byte[] dataToAuthenticate = Arrays.copyOf(mDataToAuthenticate, mDataToAuthenticate.length);
dataToAuthenticate[0]++;
try {
IkeEncryptedPayloadBody.validateChecksumOrThrow(
dataToAuthenticate, mHmacSha1IntegrityMac, mChecksum);
fail("Expected GeneralSecurityException due to mismatched checksum.");
} catch (GeneralSecurityException expected) {
}
}
@Test
public void testCalculatePaddingPlaintextShorterThanBlockSize() throws Exception {
int blockSize = 16;
int plainTextLength = 15;
int expectedPadLength = 0;
byte[] calculatedPadding =
IkeEncryptedPayloadBody.calculatePadding(plainTextLength, blockSize);
assertEquals(expectedPadLength, calculatedPadding.length);
}
@Test
public void testCalculatePaddingPlaintextInBlockSize() throws Exception {
int blockSize = 16;
int plainTextLength = 16;
int expectedPadLength = 15;
byte[] calculatedPadding =
IkeEncryptedPayloadBody.calculatePadding(plainTextLength, blockSize);
assertEquals(expectedPadLength, calculatedPadding.length);
}
@Test
public void testCalculatePaddingPlaintextLongerThanBlockSize() throws Exception {
int blockSize = 16;
int plainTextLength = 17;
int expectedPadLength = 14;
byte[] calculatedPadding =
IkeEncryptedPayloadBody.calculatePadding(plainTextLength, blockSize);
assertEquals(expectedPadLength, calculatedPadding.length);
}
@Test
public void testEncrypt() throws Exception {
byte[] calculatedData =
IkeEncryptedPayloadBody.encrypt(
mDataToPadAndEncrypt, mAesCbcCipher, mAesCbcKey, mIv, mPadding);
assertArrayEquals(mEncryptedPaddedData, calculatedData);
}
@Test
public void testDecrypt() throws Exception {
byte[] calculatedPlainText =
IkeEncryptedPayloadBody.decrypt(
mEncryptedPaddedData, mAesCbcCipher, mAesCbcKey, mIv);
assertArrayEquals(mDataToPadAndEncrypt, calculatedPlainText);
}
@Test
public void testBuildAndEncodeOutboundIkeEncryptedPayloadBody() throws Exception {
IkeHeader ikeHeader = new IkeHeader(mIkeMessage);
IkeEncryptedPayloadBody paylaodBody =
new IkeEncryptedPayloadBody(
ikeHeader,
IkePayload.PAYLOAD_TYPE_ID_INITIATOR,
mDataToPadAndEncrypt,
mHmacSha1IntegrityMac,
HMAC_SHA1_CHECKSUM_LEN,
mAesCbcCipher,
mAesCbcKey,
mIv,
mPadding);
byte[] expectedEncodedData =
TestUtils.hexStringToByteArray(
IKE_AUTH_INIT_REQUEST_IV
+ IKE_AUTH_INIT_REQUEST_ENCRYPT_PADDED_DATA
+ IKE_AUTH_INIT_REQUEST_CHECKSUM);
assertArrayEquals(expectedEncodedData, paylaodBody.encode());
}
@Test
public void testAuthenticateAndDecryptInboundIkeEncryptedPayloadBody() throws Exception {
IkeEncryptedPayloadBody paylaodBody =
new IkeEncryptedPayloadBody(
mIkeMessage,
mHmacSha1IntegrityMac,
HMAC_SHA1_CHECKSUM_LEN,
mAesCbcCipher,
mAesCbcKey);
assertArrayEquals(mDataToPadAndEncrypt, paylaodBody.getUnencryptedData());
}
}