diff options
author | Cody Kesting <ckesting@google.com> | 2019-10-30 13:25:56 -0700 |
---|---|---|
committer | android-build-merger <android-build-merger@google.com> | 2019-10-30 13:25:56 -0700 |
commit | 3074ff706946cee394815e0b838f63429e4bb93c (patch) | |
tree | 4ddaacad101486740a7cedd73326dd030ac1f736 | |
parent | 7ec43bb63988dbd8518a5769457e808c3710ebfa (diff) | |
parent | eedd8d2f6549ec2dee1dfcfbf0a7f96243db4c18 (diff) | |
download | ike-3074ff706946cee394815e0b838f63429e4bb93c.tar.gz |
Create CK' and IK' for EAP-AKA'. am: 3868e2aa52
am: eedd8d2f65
Change-Id: I482653a455fdce1de5705c57cef697e023ba8e98
-rw-r--r-- | src/java/com/android/ike/eap/statemachine/EapAkaPrimeMethodStateMachine.java | 46 | ||||
-rw-r--r-- | tests/iketests/src/java/com/android/ike/eap/statemachine/EapAkaPrimeChallengeStateTest.java | 27 |
2 files changed, 73 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 1b365dc7..f047cf6f 100644 --- a/src/java/com/android/ike/eap/statemachine/EapAkaPrimeMethodStateMachine.java +++ b/src/java/com/android/ike/eap/statemachine/EapAkaPrimeMethodStateMachine.java @@ -32,17 +32,23 @@ import com.android.ike.eap.message.simaka.EapAkaPrimeTypeData; import com.android.ike.eap.message.simaka.EapAkaPrimeTypeData.EapAkaPrimeTypeDataDecoder; import com.android.ike.eap.message.simaka.EapAkaTypeData; import com.android.ike.eap.message.simaka.EapSimAkaAttribute; +import com.android.ike.eap.message.simaka.EapSimAkaAttribute.AtAutn; import com.android.ike.eap.message.simaka.EapSimAkaAttribute.AtClientErrorCode; import com.android.ike.eap.message.simaka.EapSimAkaAttribute.AtKdf; 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.ByteBuffer; import java.nio.charset.StandardCharsets; +import java.security.GeneralSecurityException; import java.util.Arrays; import java.util.List; import java.util.Map; +import javax.crypto.Mac; +import javax.crypto.spec.SecretKeySpec; + /** * EapAkaPrimeMethodStateMachine represents the valid paths possible for the EAP-AKA' protocol. * @@ -68,6 +74,9 @@ public class EapAkaPrimeMethodStateMachine extends EapAkaMethodStateMachine { // 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 final EapAkaPrimeConfig mEapAkaPrimeConfig; private final EapAkaPrimeTypeDataDecoder mEapAkaPrimeTypeDataDecoder; @@ -203,6 +212,43 @@ public class EapAkaPrimeMethodStateMachine extends EapAkaMethodStateMachine { return true; } + + /** + * Derives CK' and IK' values from CK and IK + * + * <p>CK' and IK' generation is specified in TS 133 402 Annex A.2, which relies on the key + * derivation function KDF specified in TS 133 220 Annex B.2. + */ + @VisibleForTesting + byte[] deriveCkIkPrime( + RandChallengeResult randChallengeResult, AtKdfInput atKdfInput, AtAutn atAutn) + throws GeneralSecurityException { + final int fcLen = 1; + int lengthFieldLen = 2; + + // SQN ^ AK is the first 6B of the AUTN value + byte[] sqnXorAk = Arrays.copyOf(atAutn.autn, SQN_XOR_AK_LEN); + int sLength = + fcLen + + atKdfInput.networkName.length + lengthFieldLen + + SQN_XOR_AK_LEN + lengthFieldLen; + + ByteBuffer dataToSign = ByteBuffer.allocate(sLength); + dataToSign.put((byte) FC); + dataToSign.put(atKdfInput.networkName); + dataToSign.putShort((short) atKdfInput.networkName.length); + dataToSign.put(sqnXorAk); + dataToSign.putShort((short) SQN_XOR_AK_LEN); + + int keyLen = randChallengeResult.ck.length + randChallengeResult.ik.length; + ByteBuffer key = ByteBuffer.allocate(keyLen); + key.put(randChallengeResult.ck); + key.put(randChallengeResult.ik); + + Mac mac = Mac.getInstance(MAC_ALGORITHM_STRING); + mac.init(new SecretKeySpec(key.array(), MAC_ALGORITHM_STRING)); + return mac.doFinal(dataToSign.array()); + } } EapAkaPrimeTypeData getEapSimAkaTypeData(AtClientErrorCode clientErrorCode) { 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 43fbf41c..32041435 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 @@ -18,18 +18,22 @@ package com.android.ike.eap.statemachine; import static android.telephony.TelephonyManager.APPTYPE_USIM; +import static com.android.ike.TestUtils.hexStringToByteArray; import static com.android.ike.eap.message.EapData.EAP_TYPE_AKA_PRIME; import static com.android.ike.eap.message.EapMessage.EAP_CODE_REQUEST; +import static com.android.ike.eap.message.EapTestMessageDefinitions.CK_BYTES; import static com.android.ike.eap.message.EapTestMessageDefinitions.EAP_AKA_PRIME_AUTHENTICATION_REJECT; import static com.android.ike.eap.message.EapTestMessageDefinitions.EAP_AKA_PRIME_IDENTITY_BYTES; import static com.android.ike.eap.message.EapTestMessageDefinitions.EAP_AKA_PRIME_IDENTITY_RESPONSE; import static com.android.ike.eap.message.EapTestMessageDefinitions.ID_INT; +import static com.android.ike.eap.message.EapTestMessageDefinitions.IK_BYTES; import static com.android.ike.eap.message.EapTestMessageDefinitions.IMSI; import static com.android.ike.eap.message.simaka.EapAkaTypeData.EAP_AKA_CHALLENGE; import static com.android.ike.eap.message.simaka.EapAkaTypeData.EAP_AKA_IDENTITY; import static com.android.ike.eap.message.simaka.attributes.EapTestAttributeDefinitions.AUTN_BYTES; import static com.android.ike.eap.message.simaka.attributes.EapTestAttributeDefinitions.MAC_BYTES; import static com.android.ike.eap.message.simaka.attributes.EapTestAttributeDefinitions.RAND_1_BYTES; +import static com.android.ike.eap.message.simaka.attributes.EapTestAttributeDefinitions.RES_BYTES; import static org.junit.Assert.assertArrayEquals; import static org.junit.Assert.assertFalse; @@ -52,6 +56,7 @@ import com.android.ike.eap.message.simaka.EapSimAkaAttribute.AtKdfInput; import com.android.ike.eap.message.simaka.EapSimAkaAttribute.AtMac; import com.android.ike.eap.message.simaka.EapSimAkaAttribute.AtRandAka; import com.android.ike.eap.message.simaka.EapSimAkaTypeData.DecodeResult; +import com.android.ike.eap.statemachine.EapAkaMethodStateMachine.ChallengeState.RandChallengeResult; import com.android.ike.eap.statemachine.EapAkaPrimeMethodStateMachine.ChallengeState; import org.junit.Before; @@ -71,6 +76,10 @@ public class EapAkaPrimeChallengeStateTest extends EapAkaPrimeStateTest { private static final int VALID_KDF = 1; private static final int INVALID_KDF = 10; + private static final byte[] EXPECTED_CK_IK_PRIME = + hexStringToByteArray( + "A0B37E7C7E9CC4F37A5C0AAA55DC87BE51FDA70A9D8F37E62E23B15F1B3941E6"); + private ChallengeState mState; @Before @@ -269,4 +278,22 @@ public class EapAkaPrimeChallengeStateTest extends EapAkaPrimeStateTest { assertFalse( mState.hasMatchingNetworkNames(INCORRECT_NETWORK_NAME, SERVER_NETWORK_NAME_STRING)); } + + @Test + public void testDeriveCkIkPrime() throws Exception { + RandChallengeResult randChallengeResult = + mState.new RandChallengeResult(RES_BYTES, IK_BYTES, CK_BYTES); + AtKdfInput atKdfInput = + new AtKdfInput(0, PEER_NETWORK_NAME.getBytes(StandardCharsets.UTF_8)); + AtAutn atAutn = new AtAutn(AUTN_BYTES); + + // S = FC | Network Name | len(Network Name) | SQN ^ AK | len(SQN ^ AK) + // = 20666F6F3A62617200070123456789AB0006 + // K = CK | IK + // = FFEEDDCCBBAA9988776655443322110000112233445566778899AABBCCDDEEFF + // CK' | IK' = HMAC-SHA256(K, S) + // = A0B37E7C7E9CC4F37A5C0AAA55DC87BE51FDA70A9D8F37E62E23B15F1B3941E6 + byte[] result = mState.deriveCkIkPrime(randChallengeResult, atKdfInput, atAutn); + assertArrayEquals(EXPECTED_CK_IK_PRIME, result); + } } |