diff options
author | Cody Kesting <ckesting@google.com> | 2019-10-21 13:19:21 -0700 |
---|---|---|
committer | Cody Kesting <ckesting@google.com> | 2019-10-29 12:33:41 -0700 |
commit | b0f35bbac9767b9681e837ed9f89659d2d0a9558 (patch) | |
tree | f7ad30ad4487040780579277d2190f5d10ac13d0 | |
parent | e93bb5e45e3f543efd42043775b2042b8278631e (diff) | |
download | ike-b0f35bbac9767b9681e837ed9f89659d2d0a9558.tar.gz |
Refactor IkeMacPrf impl to shared package.
Both IKEv2 and EAP require the IKEv2 prf+(K, S) function defined in RFC
7296#2.13. The function implementation is moved from
com.android.ike.ikev2.crypto to com.android.ike.crypto in order to avoid
any direct dependencies bewteen the EAP and IKEv2 libraries.
Bug: 142968025
Test: atest FrameworksIkeTests
Change-Id: I9db5af855593bf5a33dc6a72c6ed33ebfbc2574a
-rw-r--r-- | src/java/com/android/ike/crypto/KeyGenerationUtils.java | 81 | ||||
-rw-r--r-- | src/java/com/android/ike/ikev2/crypto/IkeMac.java | 5 | ||||
-rw-r--r-- | src/java/com/android/ike/ikev2/crypto/IkeMacPrf.java | 22 |
3 files changed, 87 insertions, 21 deletions
diff --git a/src/java/com/android/ike/crypto/KeyGenerationUtils.java b/src/java/com/android/ike/crypto/KeyGenerationUtils.java new file mode 100644 index 00000000..5ac8c579 --- /dev/null +++ b/src/java/com/android/ike/crypto/KeyGenerationUtils.java @@ -0,0 +1,81 @@ +/* + * 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.crypto; + +import java.nio.ByteBuffer; + +/** + * KeyGenerationUtils is a util class that contains utils for key generation needed by IKEv2 and + * EAP. + */ +public class KeyGenerationUtils { + /** + * Returns the derived pseudorandom number with the specified length by iteratively applying a + * PRF. + * + * <p>prf+(K, S) outputs a pseudorandom stream by using the PRF iteratively. In this way it can + * generate long enough keying material containing all the keys. + * + * @see <a href="https://tools.ietf.org/html/rfc7296#section-2.13">RFC 7296 Internet Key + * Exchange Protocol Version 2 (IKEv2) 2.13. Generating Keying Material </a> + * @param byteSigner the PRF used to sign the given data using the given key. + * @param keyBytes the key to sign data. + * @param dataToSign the data to be signed. + * @param keyMaterialLen the length of keying materials to be generated. + * @return the byte array of keying materials + */ + public static byte[] prfPlus( + ByteSigner byteSigner, byte[] keyBytes, byte[] dataToSign, int keyMaterialLen) { + ByteBuffer keyMatBuffer = ByteBuffer.allocate(keyMaterialLen); + + byte[] previousMac = new byte[0]; + final int padLen = 1; + byte padValue = 1; + + while (keyMatBuffer.remaining() > 0) { + ByteBuffer dataToSignBuffer = + ByteBuffer.allocate(previousMac.length + dataToSign.length + padLen); + dataToSignBuffer.put(previousMac).put(dataToSign).put(padValue); + + previousMac = byteSigner.signBytes(keyBytes, dataToSignBuffer.array()); + + keyMatBuffer.put( + previousMac, 0, Math.min(previousMac.length, keyMatBuffer.remaining())); + + padValue++; + } + + return keyMatBuffer.array(); + } + + /** + * ByteSigner is an interface to be used for implementing the byte-signing for generating keys + * using {@link KeyGenerationUtils#prfPlus(ByteSigner, byte[], byte[], int)}. + */ + public interface ByteSigner { + /** + * Signs the given data using the key given. + * + * <p>Caller is responsible for providing a valid key according to their use cases. + * + * @param keyBytes the key to sign data. + * @param dataToSign the data to be signed. + * @return the signed value. + */ + byte[] signBytes(byte[] keyBytes, byte[] dataToSign); + } +} diff --git a/src/java/com/android/ike/ikev2/crypto/IkeMac.java b/src/java/com/android/ike/ikev2/crypto/IkeMac.java index 4f233459..028f746c 100644 --- a/src/java/com/android/ike/ikev2/crypto/IkeMac.java +++ b/src/java/com/android/ike/ikev2/crypto/IkeMac.java @@ -16,6 +16,8 @@ package com.android.ike.ikev2.crypto; +import com.android.ike.crypto.KeyGenerationUtils.ByteSigner; + import java.nio.ByteBuffer; import java.security.InvalidKeyException; import java.security.NoSuchAlgorithmException; @@ -30,7 +32,7 @@ import javax.crypto.spec.SecretKeySpec; * IkeMac is an abstract class that represents common information for all negotiated algorithms that * generates Message Authentication Code (MAC), e.g. PRF and integrity algorithm. */ -abstract class IkeMac extends IkeCrypto { +abstract class IkeMac extends IkeCrypto implements ByteSigner { // STOPSHIP: b/130190639 Catch unchecked exceptions, notify users and close the IKE session. private final boolean mIsEncryptAlgo; private final Mac mMac; @@ -69,6 +71,7 @@ abstract class IkeMac extends IkeCrypto { * @param dataToSign the data to be signed. * @return the calculated MAC. */ + @Override public byte[] signBytes(byte[] keyBytes, byte[] dataToSign) { try { SecretKeySpec secretKey = new SecretKeySpec(keyBytes, getAlgorithmName()); diff --git a/src/java/com/android/ike/ikev2/crypto/IkeMacPrf.java b/src/java/com/android/ike/ikev2/crypto/IkeMacPrf.java index 34ef3bf8..b25ba34d 100644 --- a/src/java/com/android/ike/ikev2/crypto/IkeMacPrf.java +++ b/src/java/com/android/ike/ikev2/crypto/IkeMacPrf.java @@ -16,6 +16,7 @@ package com.android.ike.ikev2.crypto; +import com.android.ike.crypto.KeyGenerationUtils; import com.android.ike.ikev2.SaProposal; import com.android.ike.ikev2.message.IkeSaPayload.PrfTransform; @@ -135,26 +136,7 @@ public class IkeMacPrf extends IkeMac { * @return the byte array of keying materials */ public byte[] generateKeyMat(byte[] keyBytes, byte[] dataToSign, int keyMaterialLen) { - ByteBuffer keyMatBuffer = ByteBuffer.allocate(keyMaterialLen); - - byte[] previousMac = new byte[0]; - final int padLen = 1; - byte padValue = 1; - - while (keyMatBuffer.remaining() > 0) { - ByteBuffer dataToSignBuffer = - ByteBuffer.allocate(previousMac.length + dataToSign.length + padLen); - dataToSignBuffer.put(previousMac).put(dataToSign).put(padValue); - - previousMac = signBytes(keyBytes, dataToSignBuffer.array()); - - keyMatBuffer.put( - previousMac, 0, Math.min(previousMac.length, keyMatBuffer.remaining())); - - padValue++; - } - - return keyMatBuffer.array(); + return KeyGenerationUtils.prfPlus(this, keyBytes, dataToSign, keyMaterialLen); } /** |