diff options
-rw-r--r-- | src/java/com/android/ike/ikev2/message/IkeAuthPskPayload.java | 40 | ||||
-rw-r--r-- | tests/iketests/src/java/com/android/ike/ikev2/message/IkeAuthPskPayloadTest.java | 67 |
2 files changed, 94 insertions, 13 deletions
diff --git a/src/java/com/android/ike/ikev2/message/IkeAuthPskPayload.java b/src/java/com/android/ike/ikev2/message/IkeAuthPskPayload.java index 9109850d..182df8a8 100644 --- a/src/java/com/android/ike/ikev2/message/IkeAuthPskPayload.java +++ b/src/java/com/android/ike/ikev2/message/IkeAuthPskPayload.java @@ -16,8 +16,11 @@ package com.android.ike.ikev2.message; +import com.android.ike.ikev2.exceptions.AuthenticationFailedException; + import java.nio.ByteBuffer; import java.security.InvalidKeyException; +import java.util.Arrays; import javax.crypto.Mac; @@ -60,8 +63,8 @@ public final class IkeAuthPskPayload extends IkeAuthPayload { * @param nonce nonce of IKE responder for calculating IKE initiator's SignedOctets. * @param idPayloadBodyBytes ID-Initiator payload body for calculating IKE initiator's * SignedOctets. - * @param prfMac locally store PRF - * @param prfKeyBytes locally store PRF keys + * @param prfMac locally stored PRF + * @param prfKeyBytes locally stored PRF keys */ public IkeAuthPskPayload( byte[] psk, @@ -93,6 +96,39 @@ public final class IkeAuthPskPayload extends IkeAuthPayload { } } + /** + * Verify received signature in inbound IKE packet. + * + * <p>Since IKE library is always a client, inbound IkeAuthPskPayload always signs IKE + * responder's SignedOctets, which is concatenation of the IKE_INIT response message, the Nonce + * of IKE initiator and the signed ID-Responder payload body. + * + * @param psk locally stored pre-shared key + * @param ikeInitBytes IKE_INIT response for calculating IKE responder's SignedOctets. + * @param nonce nonce of IKE initiator for calculating IKE responder's SignedOctets. + * @param idPayloadBodyBytes ID-Responder payload body for calculating IKE responder's + * SignedOctets. + * @param prfMac locally stored PRF + * @param prfKeyBytes locally stored PRF keys + * @throws AuthenticationFailedException if received signature is not equal to calculated + * signature. + */ + public void verifyInboundSignature( + byte[] psk, + byte[] ikeInitBytes, + byte[] nonce, + byte[] idPayloadBodyBytes, + Mac prfMac, + byte[] prfKeyBytes) + throws AuthenticationFailedException { + byte[] calculatedSignature = + calculatePskSignature( + psk, ikeInitBytes, nonce, idPayloadBodyBytes, prfMac, prfKeyBytes); + if (!Arrays.equals(signature, calculatedSignature)) { + throw new AuthenticationFailedException("Signature verification failed."); + } + } + @Override protected void encodeAuthDataToByteBuffer(ByteBuffer byteBuffer) { byteBuffer.put(signature); diff --git a/tests/iketests/src/java/com/android/ike/ikev2/message/IkeAuthPskPayloadTest.java b/tests/iketests/src/java/com/android/ike/ikev2/message/IkeAuthPskPayloadTest.java index 398e9626..baa8059c 100644 --- a/tests/iketests/src/java/com/android/ike/ikev2/message/IkeAuthPskPayloadTest.java +++ b/tests/iketests/src/java/com/android/ike/ikev2/message/IkeAuthPskPayloadTest.java @@ -18,17 +18,22 @@ 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 com.android.ike.ikev2.exceptions.AuthenticationFailedException; import org.junit.Test; import java.nio.ByteBuffer; +import java.util.Arrays; import javax.crypto.Mac; - public final class IkeAuthPskPayloadTest { private static final String PSK_AUTH_PAYLOAD_HEX_STRING = "2100001c02000000df7c038aefaaa32d3f44b228b52a332744dfb2c1"; + private static final String PSK_AUTH_PAYLOAD_BODY_HEX_STRING = + "02000000df7c038aefaaa32d3f44b228b52a332744dfb2c1"; private static final String PSK_AUTH_PAYLOAD_SIGNATURE_HEX_STRING = "df7c038aefaaa32d3f44b228b52a332744dfb2c1"; @@ -59,24 +64,26 @@ public final class IkeAuthPskPayloadTest { private static final String PRF_HMAC_SHA1_ALGO_NAME = "HmacSHA1"; + private static final byte[] PSK = TestUtils.hexStringToByteArray(PSK_HEX_STRING); + private static final byte[] IKE_INIT_REQUEST = + TestUtils.hexStringToByteArray(PSK_IKE_INIT_REQUEST_HEX_STRING); + private static final byte[] NONCE = TestUtils.hexStringToByteArray(PSK_NONCE_RESP_HEX_STRING); + private static final byte[] ID_PAYLOAD_BODY = + TestUtils.hexStringToByteArray(PSK_ID_INITIATOR_PAYLOAD_HEX_STRING); + private static final byte[] PRF_KEY = TestUtils.hexStringToByteArray(PSK_SKP_HEX_STRING); + private static final byte[] SIGNATURE = + TestUtils.hexStringToByteArray(PSK_AUTH_PAYLOAD_SIGNATURE_HEX_STRING); + @Test public void testBuildOutboundIkeAuthPskPayload() throws Exception { - byte[] psk = TestUtils.hexStringToByteArray(PSK_HEX_STRING); - byte[] ikeInitBytes = TestUtils.hexStringToByteArray(PSK_IKE_INIT_REQUEST_HEX_STRING); - byte[] nonce = TestUtils.hexStringToByteArray(PSK_NONCE_RESP_HEX_STRING); - byte[] idPayloadBodyBytes = - TestUtils.hexStringToByteArray(PSK_ID_INITIATOR_PAYLOAD_HEX_STRING); - byte[] prfKeyBytes = TestUtils.hexStringToByteArray(PSK_SKP_HEX_STRING); Mac prfMac = Mac.getInstance(PRF_HMAC_SHA1_ALGO_NAME, IkeMessage.getSecurityProvider()); IkeAuthPskPayload payload = new IkeAuthPskPayload( - psk, ikeInitBytes, nonce, idPayloadBodyBytes, prfMac, prfKeyBytes); + PSK, IKE_INIT_REQUEST, NONCE, ID_PAYLOAD_BODY, prfMac, PRF_KEY); assertEquals(IkeAuthPayload.AUTH_METHOD_PRE_SHARED_KEY, payload.authMethod); - byte[] expectedSignature = - TestUtils.hexStringToByteArray(PSK_AUTH_PAYLOAD_SIGNATURE_HEX_STRING); - assertArrayEquals(expectedSignature, payload.signature); + assertArrayEquals(SIGNATURE, payload.signature); // Verify payload length int payloadLength = payload.getPayloadLength(); @@ -88,4 +95,42 @@ public final class IkeAuthPskPayloadTest { payload.encodeToByteBuffer(IkePayload.PAYLOAD_TYPE_SA, byteBuffer); assertArrayEquals(expectedPayload, byteBuffer.array()); } + + private IkeAuthPskPayload buildPskPayload() throws Exception { + byte[] payloadBody = TestUtils.hexStringToByteArray(PSK_AUTH_PAYLOAD_BODY_HEX_STRING); + IkeAuthPskPayload pskPayload = + (IkeAuthPskPayload) IkeAuthPayload.getIkeAuthPayload(false, payloadBody); + return pskPayload; + } + + @Test + public void testDecodeIkeAuthPskPayload() throws Exception { + IkeAuthPskPayload pskPayload = buildPskPayload(); + + assertArrayEquals(SIGNATURE, pskPayload.signature); + } + + @Test + public void testVerifyReceivedSignature() throws Exception { + Mac prfMac = Mac.getInstance(PRF_HMAC_SHA1_ALGO_NAME, IkeMessage.getSecurityProvider()); + IkeAuthPskPayload pskPayload = buildPskPayload(); + + pskPayload.verifyInboundSignature( + PSK, IKE_INIT_REQUEST, NONCE, ID_PAYLOAD_BODY, prfMac, PRF_KEY); + } + + @Test + public void testVerifyReceivedSignatureFailure() throws Exception { + Mac prfMac = Mac.getInstance(PRF_HMAC_SHA1_ALGO_NAME, IkeMessage.getSecurityProvider()); + IkeAuthPskPayload pskPayload = buildPskPayload(); + byte[] nonce = Arrays.copyOf(NONCE, NONCE.length); + nonce[0]++; + + try { + pskPayload.verifyInboundSignature( + PSK, IKE_INIT_REQUEST, nonce, ID_PAYLOAD_BODY, prfMac, PRF_KEY); + fail("Expected signature verification to have failed due to mismatched signatures."); + } catch (AuthenticationFailedException expected) { + } + } } |