aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCody Kesting <ckesting@google.com>2019-10-31 10:09:47 -0700
committerandroid-build-merger <android-build-merger@google.com>2019-10-31 10:09:47 -0700
commitce0dac31e279ce3ba48020bb8aff14317866636d (patch)
treeedbf1bcfde6b3208bdfc08b5386024f69e8facbf
parentc11729c1dc27454356498dce24d8588fcd7f8680 (diff)
parent8c0c0644902af46e3f2d5223dcb4b660df4d686f (diff)
downloadike-ce0dac31e279ce3ba48020bb8aff14317866636d.tar.gz
Override key generation for EAP-AKA'. am: 47f189aa4d
am: 8c0c064490 Change-Id: I3be6f2a30647a2579b4b097fb80ff541256aa8d8
-rw-r--r--src/java/com/android/ike/eap/statemachine/EapAkaPrimeMethodStateMachine.java70
-rw-r--r--tests/iketests/src/java/com/android/ike/eap/statemachine/EapAkaPrimeChallengeStateTest.java54
-rw-r--r--tests/iketests/src/java/com/android/ike/eap/statemachine/EapAkaPrimeMethodStateMachineTest.java15
3 files changed, 139 insertions, 0 deletions
diff --git a/src/java/com/android/ike/eap/statemachine/EapAkaPrimeMethodStateMachine.java b/src/java/com/android/ike/eap/statemachine/EapAkaPrimeMethodStateMachine.java
index f047cf6f..b70c3f71 100644
--- a/src/java/com/android/ike/eap/statemachine/EapAkaPrimeMethodStateMachine.java
+++ b/src/java/com/android/ike/eap/statemachine/EapAkaPrimeMethodStateMachine.java
@@ -19,13 +19,17 @@ package com.android.ike.eap.statemachine;
import static com.android.ike.eap.EapAuthenticator.LOG;
import static com.android.ike.eap.message.EapData.EAP_TYPE_AKA_PRIME;
import static com.android.ike.eap.message.simaka.EapAkaTypeData.EAP_AKA_CLIENT_ERROR;
+import static com.android.ike.eap.message.simaka.EapSimAkaAttribute.EAP_AT_AUTN;
import static com.android.ike.eap.message.simaka.EapSimAkaAttribute.EAP_AT_KDF;
import static com.android.ike.eap.message.simaka.EapSimAkaAttribute.EAP_AT_KDF_INPUT;
+import android.annotation.Nullable;
import android.content.Context;
+import com.android.ike.crypto.KeyGenerationUtils;
import com.android.ike.eap.EapResult;
import com.android.ike.eap.EapSessionConfig.EapAkaPrimeConfig;
+import com.android.ike.eap.crypto.HmacSha256ByteSigner;
import com.android.ike.eap.message.EapData.EapMethod;
import com.android.ike.eap.message.EapMessage;
import com.android.ike.eap.message.simaka.EapAkaPrimeTypeData;
@@ -39,6 +43,8 @@ import com.android.ike.eap.message.simaka.EapSimAkaAttribute.AtKdfInput;
import com.android.ike.eap.message.simaka.EapSimAkaTypeData.DecodeResult;
import com.android.internal.annotations.VisibleForTesting;
+import java.nio.BufferOverflowException;
+import java.nio.BufferUnderflowException;
import java.nio.ByteBuffer;
import java.nio.charset.StandardCharsets;
import java.security.GeneralSecurityException;
@@ -71,12 +77,22 @@ import javax.crypto.spec.SecretKeySpec;
* Protocol Method for 3rd Generation Authentication and Key Agreement (EAP-AKA')</a>
*/
public class EapAkaPrimeMethodStateMachine extends EapAkaMethodStateMachine {
+ public static final int K_AUT_LEN = 32;
+ public static final int K_RE_LEN = 32;
+
// EAP-AKA' identity prefix (RFC 5448#3)
private static final String AKA_PRIME_IDENTITY_PREFIX = "6";
private static final int SUPPORTED_KDF = 1;
private static final int FC = 0x20; // Required by TS 133 402 Annex A.2
private static final int SQN_XOR_AK_LEN = 6;
private static final String MAC_ALGORITHM_STRING = "HmacSHA256";
+ private static final String MK_DATA_PREFIX = "EAP-AKA'";
+
+ // MK_LEN_BYTES = len(K_encr | K_aut | K_re | MSK | EMSK)
+ private static final int MK_LEN_BYTES =
+ KEY_LEN + K_AUT_LEN + K_RE_LEN + (2 * SESSION_KEY_LENGTH);
+
+ public final byte[] mKRe = new byte[getKReLen()];
private final EapAkaPrimeConfig mEapAkaPrimeConfig;
private final EapAkaPrimeTypeDataDecoder mEapAkaPrimeTypeDataDecoder;
@@ -110,6 +126,15 @@ public class EapAkaPrimeMethodStateMachine extends EapAkaMethodStateMachine {
}
@Override
+ protected int getKAutLength() {
+ return K_AUT_LEN;
+ }
+
+ protected int getKReLen() {
+ return K_RE_LEN;
+ }
+
+ @Override
protected DecodeResult<EapAkaTypeData> decode(byte[] typeData) {
return mEapAkaPrimeTypeDataDecoder.decode(typeData);
}
@@ -213,6 +238,51 @@ public class EapAkaPrimeMethodStateMachine extends EapAkaMethodStateMachine {
return true;
}
+ @Nullable
+ @Override
+ protected EapResult generateAndPersistEapAkaKeys(
+ RandChallengeResult result, int eapIdentifier, EapAkaTypeData eapAkaTypeData) {
+ try {
+ AtKdfInput atKdfInput =
+ (AtKdfInput) eapAkaTypeData.attributeMap.get(EAP_AT_KDF_INPUT);
+ AtAutn atAutn = (AtAutn) eapAkaTypeData.attributeMap.get(EAP_AT_AUTN);
+ byte[] ckIkPrime = deriveCkIkPrime(result, atKdfInput, atAutn);
+
+ int dataToSignLen = MK_DATA_PREFIX.length() + mIdentity.length;
+ ByteBuffer dataToSign = ByteBuffer.allocate(dataToSignLen);
+ dataToSign.put(MK_DATA_PREFIX.getBytes(StandardCharsets.US_ASCII));
+ dataToSign.put(mIdentity);
+
+ ByteBuffer mk =
+ ByteBuffer.wrap(
+ KeyGenerationUtils.prfPlus(
+ HmacSha256ByteSigner.getInstance(),
+ ckIkPrime,
+ dataToSign.array(),
+ MK_LEN_BYTES));
+
+ mk.get(mKEncr);
+ mk.get(mKAut);
+ mk.get(mKRe);
+ mk.get(mMsk);
+ mk.get(mEmsk);
+
+ // Log as hash unless PII debug mode enabled
+ LOG.d(mTAG, "K_encr=" + LOG.pii(mKEncr));
+ LOG.d(mTAG, "K_aut=" + LOG.pii(mKAut));
+ LOG.d(mTAG, "K_re=" + LOG.pii(mKRe));
+ LOG.d(mTAG, "MSK=" + LOG.pii(mMsk));
+ LOG.d(mTAG, "EMSK=" + LOG.pii(mEmsk));
+ return null;
+ } catch (GeneralSecurityException
+ | BufferOverflowException
+ | BufferUnderflowException ex) {
+ LOG.e(mTAG, "Error while generating keys", ex);
+ return buildClientErrorResponse(
+ eapIdentifier, getEapMethod(), AtClientErrorCode.UNABLE_TO_PROCESS);
+ }
+ }
+
/**
* Derives CK' and IK' values from CK and IK
*
diff --git a/tests/iketests/src/java/com/android/ike/eap/statemachine/EapAkaPrimeChallengeStateTest.java b/tests/iketests/src/java/com/android/ike/eap/statemachine/EapAkaPrimeChallengeStateTest.java
index 32041435..a768376f 100644
--- a/tests/iketests/src/java/com/android/ike/eap/statemachine/EapAkaPrimeChallengeStateTest.java
+++ b/tests/iketests/src/java/com/android/ike/eap/statemachine/EapAkaPrimeChallengeStateTest.java
@@ -37,6 +37,7 @@ import static com.android.ike.eap.message.simaka.attributes.EapTestAttributeDefi
import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.times;
@@ -79,6 +80,21 @@ public class EapAkaPrimeChallengeStateTest extends EapAkaPrimeStateTest {
private static final byte[] EXPECTED_CK_IK_PRIME =
hexStringToByteArray(
"A0B37E7C7E9CC4F37A5C0AAA55DC87BE51FDA70A9D8F37E62E23B15F1B3941E6");
+ private static final byte[] K_ENCR = hexStringToByteArray("15a5bb098528210cde9e8d4a1bd63850");
+ private static final byte[] K_AUT =
+ hexStringToByteArray(
+ "957b3d518ac9ff028f2cc5177fedad841f5f812cb06e2b88aceaa98129680f35");
+ private static final byte[] K_RE =
+ hexStringToByteArray(
+ "3c15cf7112935a8170d0904622ecbb67c49dcba5d50814bdd81958e045e42f9c");
+ private static final byte[] MSK =
+ hexStringToByteArray(
+ "1dcca0351a58d2b858e6cf2380551470d67cc8749d1915409793171abd360118"
+ + "e3ae271bf088ca5a41bb1b9b8f7028bcba888298bfbf64d7b8a4f53a6c2cdf18");
+ private static final byte[] EMSK =
+ hexStringToByteArray(
+ "a5e6b66a9cb2daa9fe3867d41145848e7bf50d749bfd1bb0d090257402e6a555"
+ + "da6d538e76b71e9f80afe60709965a63a355bdccc4e3a8b358e098e41545fa67");
private ChallengeState mState;
@@ -296,4 +312,42 @@ public class EapAkaPrimeChallengeStateTest extends EapAkaPrimeStateTest {
byte[] result = mState.deriveCkIkPrime(randChallengeResult, atKdfInput, atAutn);
assertArrayEquals(EXPECTED_CK_IK_PRIME, result);
}
+
+ @Test
+ public void testGenerateAndPersistEapAkaKeys() throws Exception {
+ RandChallengeResult randChallengeResult =
+ mState.new RandChallengeResult(RES_BYTES, IK_BYTES, CK_BYTES);
+
+ AtRandAka atRandAka = new AtRandAka(RAND_1_BYTES);
+ AtAutn atAutn = new AtAutn(AUTN_BYTES);
+ AtMac atMac = new AtMac(MAC_BYTES);
+ AtKdfInput atKdfInput =
+ new AtKdfInput(0, PEER_NETWORK_NAME.getBytes(StandardCharsets.UTF_8));
+ AtKdf atKdf = new AtKdf(VALID_KDF);
+
+ EapAkaPrimeTypeData eapAkaPrimeTypeData =
+ new EapAkaPrimeTypeData(
+ EAP_AKA_CHALLENGE,
+ Arrays.asList(atRandAka, atAutn, atMac, atKdfInput, atKdf));
+
+ // CK' | IK' = A0B37E7C7E9CC4F37A5C0AAA55DC87BE51FDA70A9D8F37E62E23B15F1B3941E6
+ // data = "EAP-AKA'" | Identity
+ // = 4541502D414B41277465737440616E64726F69642E6E6574
+ // prf+(CK' | IK', data) = T1 | T2 | T3 | T4 | T5 | T6 | T7
+ // T1 = 15a5bb098528210cde9e8d4a1bd63850957b3d518ac9ff028f2cc5177fedad84
+ // T2 = 1f5f812cb06e2b88aceaa98129680f353c15cf7112935a8170d0904622ecbb67
+ // T3 = c49dcba5d50814bdd81958e045e42f9c1dcca0351a58d2b858e6cf2380551470
+ // T4 = d67cc8749d1915409793171abd360118e3ae271bf088ca5a41bb1b9b8f7028bc
+ // T5 = ba888298bfbf64d7b8a4f53a6c2cdf18a5e6b66a9cb2daa9fe3867d41145848e
+ // T6 = 7bf50d749bfd1bb0d090257402e6a555da6d538e76b71e9f80afe60709965a63
+ // T7 = a355bdccc4e3a8b358e098e41545fa677897d8341c4a107a2343f393ec966181
+ // K_encr | K_aut | K_re | MSK | EMSK = prf+(CK' | IK', data)
+ assertNull(
+ mState.generateAndPersistEapAkaKeys(randChallengeResult, 0, eapAkaPrimeTypeData));
+ assertArrayEquals(K_ENCR, mStateMachine.mKEncr);
+ assertArrayEquals(K_AUT, mStateMachine.mKAut);
+ assertArrayEquals(K_RE, mStateMachine.mKRe);
+ assertArrayEquals(MSK, mStateMachine.mMsk);
+ assertArrayEquals(EMSK, mStateMachine.mEmsk);
+ }
}
diff --git a/tests/iketests/src/java/com/android/ike/eap/statemachine/EapAkaPrimeMethodStateMachineTest.java b/tests/iketests/src/java/com/android/ike/eap/statemachine/EapAkaPrimeMethodStateMachineTest.java
index c96f3fe2..84f92b42 100644
--- a/tests/iketests/src/java/com/android/ike/eap/statemachine/EapAkaPrimeMethodStateMachineTest.java
+++ b/tests/iketests/src/java/com/android/ike/eap/statemachine/EapAkaPrimeMethodStateMachineTest.java
@@ -16,6 +16,12 @@
package com.android.ike.eap.statemachine;
+import static com.android.ike.eap.statemachine.EapAkaPrimeMethodStateMachine.K_AUT_LEN;
+import static com.android.ike.eap.statemachine.EapAkaPrimeMethodStateMachine.K_RE_LEN;
+import static com.android.ike.eap.statemachine.EapSimAkaMethodStateMachine.KEY_LEN;
+import static com.android.ike.eap.statemachine.EapSimAkaMethodStateMachine.SESSION_KEY_LENGTH;
+
+import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import com.android.ike.eap.statemachine.EapAkaMethodStateMachine.CreatedState;
@@ -27,4 +33,13 @@ public class EapAkaPrimeMethodStateMachineTest extends EapAkaPrimeTest {
public void testEapAkaPrimeMethodStateMachineStartState() {
assertTrue(mStateMachine.getState() instanceof CreatedState);
}
+
+ @Test
+ public void testKeyLengths() {
+ assertEquals(KEY_LEN, mStateMachine.getKEncrLength());
+ assertEquals(K_AUT_LEN, mStateMachine.getKAutLength());
+ assertEquals(K_RE_LEN, mStateMachine.getKReLen());
+ assertEquals(SESSION_KEY_LENGTH, mStateMachine.getMskLength());
+ assertEquals(SESSION_KEY_LENGTH, mStateMachine.getEmskLength());
+ }
}